mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-04-19 04:56:17 +00:00
Merge pull request #657 from acelaya-forks/feature/mar-tests
Feature/mar tests
This commit is contained in:
@@ -29,7 +29,7 @@ const normalizeOrderByInParams = (params: ShlinkShortUrlsListParams): ShlinkShor
|
|||||||
return { ...rest, orderBy: orderToString(orderBy) };
|
return { ...rest, orderBy: orderToString(orderBy) };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ShlinkApiClient {
|
export class ShlinkApiClient {
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly axios: AxiosInstance,
|
private readonly axios: AxiosInstance,
|
||||||
private readonly baseUrl: string,
|
private readonly baseUrl: string,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { AxiosInstance } from 'axios';
|
|||||||
import { prop } from 'ramda';
|
import { prop } from 'ramda';
|
||||||
import { hasServerData, SelectedServer, ServerWithId } from '../../servers/data';
|
import { hasServerData, SelectedServer, ServerWithId } from '../../servers/data';
|
||||||
import { GetState } from '../../container/types';
|
import { GetState } from '../../container/types';
|
||||||
import ShlinkApiClient from './ShlinkApiClient';
|
import { ShlinkApiClient } from './ShlinkApiClient';
|
||||||
|
|
||||||
const apiClients: Record<string, ShlinkApiClient> = {};
|
const apiClients: Record<string, ShlinkApiClient> = {};
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ const getSelectedServerFromState = (getState: GetState): SelectedServer => prop(
|
|||||||
|
|
||||||
export type ShlinkApiClientBuilder = (getStateOrSelectedServer: GetState | ServerWithId) => ShlinkApiClient;
|
export type ShlinkApiClientBuilder = (getStateOrSelectedServer: GetState | ServerWithId) => ShlinkApiClient;
|
||||||
|
|
||||||
const buildShlinkApiClient = (axios: AxiosInstance): ShlinkApiClientBuilder => (
|
export const buildShlinkApiClient = (axios: AxiosInstance): ShlinkApiClientBuilder => (
|
||||||
getStateOrSelectedServer: GetState | ServerWithId,
|
getStateOrSelectedServer: GetState | ServerWithId,
|
||||||
) => {
|
) => {
|
||||||
const server = isGetState(getStateOrSelectedServer)
|
const server = isGetState(getStateOrSelectedServer)
|
||||||
@@ -32,5 +32,3 @@ const buildShlinkApiClient = (axios: AxiosInstance): ShlinkApiClientBuilder => (
|
|||||||
|
|
||||||
return apiClients[clientKey];
|
return apiClients[clientKey];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default buildShlinkApiClient;
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Bottle from 'bottlejs';
|
import Bottle from 'bottlejs';
|
||||||
import buildShlinkApiClient from './ShlinkApiClientBuilder';
|
import { buildShlinkApiClient } from './ShlinkApiClientBuilder';
|
||||||
|
|
||||||
const provideServices = (bottle: Bottle) => {
|
const provideServices = (bottle: Bottle) => {
|
||||||
bottle.serviceFactory('buildShlinkApiClient', buildShlinkApiClient, 'axios');
|
bottle.serviceFactory('buildShlinkApiClient', buildShlinkApiClient, 'axios');
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const AsideMenuItem: FC<AsideMenuItemProps> = ({ children, to, className, ...res
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
);
|
);
|
||||||
|
|
||||||
const AsideMenu = (DeleteServerButton: FC<DeleteServerButtonProps>) => (
|
export const AsideMenu = (DeleteServerButton: FC<DeleteServerButtonProps>) => (
|
||||||
{ selectedServer, showOnMobile = false }: AsideMenuProps,
|
{ selectedServer, showOnMobile = false }: AsideMenuProps,
|
||||||
) => {
|
) => {
|
||||||
const hasId = isServerWithId(selectedServer);
|
const hasId = isServerWithId(selectedServer);
|
||||||
@@ -89,5 +89,3 @@ const AsideMenu = (DeleteServerButton: FC<DeleteServerButtonProps>) => (
|
|||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AsideMenu;
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Card, Row } from 'reactstrap';
|
|||||||
import { ExternalLink } from 'react-external-link';
|
import { ExternalLink } from 'react-external-link';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faExternalLinkAlt, faPlus } from '@fortawesome/free-solid-svg-icons';
|
import { faExternalLinkAlt, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||||
import ServersListGroup from '../servers/ServersListGroup';
|
import { ServersListGroup } from '../servers/ServersListGroup';
|
||||||
import { ServersMap } from '../servers/data';
|
import { ServersMap } from '../servers/data';
|
||||||
import { ShlinkLogo } from './img/ShlinkLogo';
|
import { ShlinkLogo } from './img/ShlinkLogo';
|
||||||
import './Home.scss';
|
import './Home.scss';
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const VersionLink = ({ project, version }: { project: 'shlink' | 'shlink-web-cli
|
|||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
);
|
);
|
||||||
|
|
||||||
const ShlinkVersions = ({ selectedServer, clientVersion = SHLINK_WEB_CLIENT_VERSION }: ShlinkVersionsProps) => {
|
export const ShlinkVersions = ({ selectedServer, clientVersion = SHLINK_WEB_CLIENT_VERSION }: ShlinkVersionsProps) => {
|
||||||
const normalizedClientVersion = normalizeVersion(clientVersion);
|
const normalizedClientVersion = normalizeVersion(clientVersion);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -29,5 +29,3 @@ const ShlinkVersions = ({ selectedServer, clientVersion = SHLINK_WEB_CLIENT_VERS
|
|||||||
</small>
|
</small>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShlinkVersions;
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { SelectedServer } from '../servers/data';
|
import { SelectedServer } from '../servers/data';
|
||||||
import ShlinkVersions from './ShlinkVersions';
|
import { ShlinkVersions } from './ShlinkVersions';
|
||||||
import { Sidebar } from './reducers/sidebar';
|
import { Sidebar } from './reducers/sidebar';
|
||||||
import './ShlinkVersionsContainer.scss';
|
import './ShlinkVersionsContainer.scss';
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ export interface ShlinkVersionsContainerProps {
|
|||||||
sidebar: Sidebar;
|
sidebar: Sidebar;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShlinkVersionsContainer = ({ selectedServer, sidebar }: ShlinkVersionsContainerProps) => {
|
export const ShlinkVersionsContainer = ({ selectedServer, sidebar }: ShlinkVersionsContainerProps) => {
|
||||||
const classes = classNames('text-center', {
|
const classes = classNames('text-center', {
|
||||||
'shlink-versions-container--with-sidebar': sidebar.sidebarPresent,
|
'shlink-versions-container--with-sidebar': sidebar.sidebarPresent,
|
||||||
});
|
});
|
||||||
@@ -20,5 +20,3 @@ const ShlinkVersionsContainer = ({ selectedServer, sidebar }: ShlinkVersionsCont
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShlinkVersionsContainer;
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { ScrollToTop } from '../ScrollToTop';
|
|||||||
import { MainHeader } from '../MainHeader';
|
import { MainHeader } from '../MainHeader';
|
||||||
import { Home } from '../Home';
|
import { Home } from '../Home';
|
||||||
import { MenuLayout } from '../MenuLayout';
|
import { MenuLayout } from '../MenuLayout';
|
||||||
import AsideMenu from '../AsideMenu';
|
import { AsideMenu } from '../AsideMenu';
|
||||||
import { ErrorHandler } from '../ErrorHandler';
|
import { ErrorHandler } from '../ErrorHandler';
|
||||||
import ShlinkVersionsContainer from '../ShlinkVersionsContainer';
|
import { ShlinkVersionsContainer } from '../ShlinkVersionsContainer';
|
||||||
import { ConnectDecorator } from '../../container/types';
|
import { ConnectDecorator } from '../../container/types';
|
||||||
import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServer';
|
import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServer';
|
||||||
import { sidebarNotPresent, sidebarPresent } from '../reducers/sidebar';
|
import { sidebarNotPresent, sidebarPresent } from '../reducers/sidebar';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { FC, useEffect } from 'react';
|
import { FC, useEffect } from 'react';
|
||||||
import Message from '../utils/Message';
|
import { Message } from '../utils/Message';
|
||||||
import { Result } from '../utils/Result';
|
import { Result } from '../utils/Result';
|
||||||
import { ShlinkApiError } from '../api/ShlinkApiError';
|
import { ShlinkApiError } from '../api/ShlinkApiError';
|
||||||
import { SimpleCard } from '../utils/SimpleCard';
|
import { SimpleCard } from '../utils/SimpleCard';
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const ImportResult = ({ type }: { type: 'error' | 'success' }) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const CreateServer = (ImportServersBtn: FC<ImportServersBtnProps>, useStateFlagTimeout: StateFlagTimeout) => (
|
export const CreateServer = (ImportServersBtn: FC<ImportServersBtnProps>, useStateFlagTimeout: StateFlagTimeout) => (
|
||||||
{ servers, createServer }: CreateServerProps,
|
{ servers, createServer }: CreateServerProps,
|
||||||
) => {
|
) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -77,5 +77,3 @@ const CreateServer = (ImportServersBtn: FC<ImportServersBtnProps>, useStateFlagT
|
|||||||
</NoMenuLayout>
|
</NoMenuLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CreateServer;
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export type DeleteServerButtonProps = PropsWithChildren<{
|
|||||||
textClassName?: string;
|
textClassName?: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const DeleteServerButton = (DeleteServerModal: FC<DeleteServerModalProps>): FC<DeleteServerButtonProps> => (
|
export const DeleteServerButton = (DeleteServerModal: FC<DeleteServerModalProps>): FC<DeleteServerButtonProps> => (
|
||||||
{ server, className, children, textClassName },
|
{ server, className, children, textClassName },
|
||||||
) => {
|
) => {
|
||||||
const [isModalOpen, , showModal, hideModal] = useToggle();
|
const [isModalOpen, , showModal, hideModal] = useToggle();
|
||||||
@@ -27,5 +27,3 @@ const DeleteServerButton = (DeleteServerModal: FC<DeleteServerModalProps>): FC<D
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DeleteServerButton;
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ interface DeleteServerModalConnectProps extends DeleteServerModalProps {
|
|||||||
deleteServer: (server: ServerWithId) => void;
|
deleteServer: (server: ServerWithId) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeleteServerModal: FC<DeleteServerModalConnectProps> = (
|
export const DeleteServerModal: FC<DeleteServerModalConnectProps> = (
|
||||||
{ server, toggle, isOpen, deleteServer, redirectHome = true },
|
{ server, toggle, isOpen, deleteServer, redirectHome = true },
|
||||||
) => {
|
) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -43,5 +43,3 @@ const DeleteServerModal: FC<DeleteServerModalConnectProps> = (
|
|||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DeleteServerModal;
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const ServerListItem = ({ id, name }: { id: string; name: string }) => (
|
|||||||
</ListGroupItem>
|
</ListGroupItem>
|
||||||
);
|
);
|
||||||
|
|
||||||
const ServersListGroup: FC<ServersListGroupProps> = ({ servers, children, embedded = false }) => (
|
export const ServersListGroup: FC<ServersListGroupProps> = ({ servers, children, embedded = false }) => (
|
||||||
<>
|
<>
|
||||||
{children && <h5 className="mb-md-3">{children}</h5>}
|
{children && <h5 className="mb-md-3">{children}</h5>}
|
||||||
{servers.length > 0 && (
|
{servers.length > 0 && (
|
||||||
@@ -31,5 +31,3 @@ const ServersListGroup: FC<ServersListGroupProps> = ({ servers, children, embedd
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default ServersListGroup;
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ interface ImportServersBtnConnectProps extends ImportServersBtnProps {
|
|||||||
const serversFiltering = (servers: ServerData[]) =>
|
const serversFiltering = (servers: ServerData[]) =>
|
||||||
({ url, apiKey }: ServerData) => servers.some((server) => server.url === url && server.apiKey === apiKey);
|
({ url, apiKey }: ServerData) => servers.some((server) => server.url === url && server.apiKey === apiKey);
|
||||||
|
|
||||||
const ImportServersBtn = ({ importServersFromFile }: ServersImporter): FC<ImportServersBtnConnectProps> => ({
|
export const ImportServersBtn = ({ importServersFromFile }: ServersImporter): FC<ImportServersBtnConnectProps> => ({
|
||||||
createServers,
|
createServers,
|
||||||
servers,
|
servers,
|
||||||
fileRef,
|
fileRef,
|
||||||
@@ -89,5 +89,3 @@ const ImportServersBtn = ({ importServersFromFile }: ServersImporter): FC<Import
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ImportServersBtn;
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import Message from '../../utils/Message';
|
import { Message } from '../../utils/Message';
|
||||||
import ServersListGroup from '../ServersListGroup';
|
import { ServersListGroup } from '../ServersListGroup';
|
||||||
import { DeleteServerButtonProps } from '../DeleteServerButton';
|
import { DeleteServerButtonProps } from '../DeleteServerButton';
|
||||||
import { isServerWithId, SelectedServer, ServersMap } from '../data';
|
import { isServerWithId, SelectedServer, ServersMap } from '../data';
|
||||||
import { NoMenuLayout } from '../../common/NoMenuLayout';
|
import { NoMenuLayout } from '../../common/NoMenuLayout';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FC, useEffect } from 'react';
|
import { FC, useEffect } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import Message from '../../utils/Message';
|
import { Message } from '../../utils/Message';
|
||||||
import { isNotFoundServer, SelectedServer } from '../data';
|
import { isNotFoundServer, SelectedServer } from '../data';
|
||||||
import { NoMenuLayout } from '../../common/NoMenuLayout';
|
import { NoMenuLayout } from '../../common/NoMenuLayout';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { values } from 'ramda';
|
import { values } from 'ramda';
|
||||||
import LocalStorage from '../../utils/services/LocalStorage';
|
import { LocalStorage } from '../../utils/services/LocalStorage';
|
||||||
import { ServersMap, serverWithIdToServerData } from '../data';
|
import { ServersMap, serverWithIdToServerData } from '../data';
|
||||||
import { saveCsv } from '../../utils/helpers/files';
|
import { saveCsv } from '../../utils/helpers/files';
|
||||||
import { JsonToCsv } from '../../utils/helpers/csvjson';
|
import { JsonToCsv } from '../../utils/helpers/csvjson';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import Bottle from 'bottlejs';
|
import Bottle from 'bottlejs';
|
||||||
import CreateServer from '../CreateServer';
|
import { CreateServer } from '../CreateServer';
|
||||||
import { ServersDropdown } from '../ServersDropdown';
|
import { ServersDropdown } from '../ServersDropdown';
|
||||||
import DeleteServerModal from '../DeleteServerModal';
|
import { DeleteServerModal } from '../DeleteServerModal';
|
||||||
import DeleteServerButton from '../DeleteServerButton';
|
import { DeleteServerButton } from '../DeleteServerButton';
|
||||||
import { EditServer } from '../EditServer';
|
import { EditServer } from '../EditServer';
|
||||||
import ImportServersBtn from '../helpers/ImportServersBtn';
|
import { ImportServersBtn } from '../helpers/ImportServersBtn';
|
||||||
import { resetSelectedServer, selectServer } from '../reducers/selectedServer';
|
import { resetSelectedServer, selectServer } from '../reducers/selectedServer';
|
||||||
import { createServer, createServers, deleteServer, editServer, setAutoConnect } from '../reducers/servers';
|
import { createServer, createServers, deleteServer, editServer, setAutoConnect } from '../reducers/servers';
|
||||||
import { fetchServers } from '../reducers/remoteServers';
|
import { fetchServers } from '../reducers/remoteServers';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FormGroup, Input } from 'reactstrap';
|
import { FormGroup, Input } from 'reactstrap';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import ToggleSwitch from '../utils/ToggleSwitch';
|
import { ToggleSwitch } from '../utils/ToggleSwitch';
|
||||||
import { SimpleCard } from '../utils/SimpleCard';
|
import { SimpleCard } from '../utils/SimpleCard';
|
||||||
import { FormText } from '../utils/forms/FormText';
|
import { FormText } from '../utils/forms/FormText';
|
||||||
import { LabeledFormGroup } from '../utils/forms/LabeledFormGroup';
|
import { LabeledFormGroup } from '../utils/forms/LabeledFormGroup';
|
||||||
@@ -14,7 +14,7 @@ interface RealTimeUpdatesProps {
|
|||||||
|
|
||||||
const intervalValue = (interval?: number) => (!interval ? '' : `${interval}`);
|
const intervalValue = (interval?: number) => (!interval ? '' : `${interval}`);
|
||||||
|
|
||||||
const RealTimeUpdatesSettings = (
|
export const RealTimeUpdatesSettings = (
|
||||||
{ settings: { realTimeUpdates }, toggleRealTimeUpdates, setRealTimeUpdatesInterval }: RealTimeUpdatesProps,
|
{ settings: { realTimeUpdates }, toggleRealTimeUpdates, setRealTimeUpdatesInterval }: RealTimeUpdatesProps,
|
||||||
) => (
|
) => (
|
||||||
<SimpleCard title="Real-time updates" className="h-100">
|
<SimpleCard title="Real-time updates" className="h-100">
|
||||||
@@ -52,5 +52,3 @@ const RealTimeUpdatesSettings = (
|
|||||||
</LabeledFormGroup>
|
</LabeledFormGroup>
|
||||||
</SimpleCard>
|
</SimpleCard>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default RealTimeUpdatesSettings;
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const SettingsSections: FC<{ items: ReactNode[] }> = ({ items }) => (
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const Settings = (
|
export const Settings = (
|
||||||
RealTimeUpdates: FC,
|
RealTimeUpdates: FC,
|
||||||
ShortUrlCreation: FC,
|
ShortUrlCreation: FC,
|
||||||
ShortUrlsList: FC,
|
ShortUrlsList: FC,
|
||||||
@@ -32,5 +32,3 @@ const Settings = (
|
|||||||
</Routes>
|
</Routes>
|
||||||
</NoMenuLayout>
|
</NoMenuLayout>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default Settings;
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { FC, ReactNode } from 'react';
|
import { FC, ReactNode } from 'react';
|
||||||
import { DropdownItem, FormGroup } from 'reactstrap';
|
import { DropdownItem, FormGroup } from 'reactstrap';
|
||||||
import { SimpleCard } from '../utils/SimpleCard';
|
import { SimpleCard } from '../utils/SimpleCard';
|
||||||
import ToggleSwitch from '../utils/ToggleSwitch';
|
import { ToggleSwitch } from '../utils/ToggleSwitch';
|
||||||
import { DropdownBtn } from '../utils/DropdownBtn';
|
import { DropdownBtn } from '../utils/DropdownBtn';
|
||||||
import { FormText } from '../utils/forms/FormText';
|
import { FormText } from '../utils/forms/FormText';
|
||||||
import { LabeledFormGroup } from '../utils/forms/LabeledFormGroup';
|
import { LabeledFormGroup } from '../utils/forms/LabeledFormGroup';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { FC } from 'react';
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faSun, faMoon } from '@fortawesome/free-solid-svg-icons';
|
import { faSun, faMoon } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { SimpleCard } from '../utils/SimpleCard';
|
import { SimpleCard } from '../utils/SimpleCard';
|
||||||
import ToggleSwitch from '../utils/ToggleSwitch';
|
import { ToggleSwitch } from '../utils/ToggleSwitch';
|
||||||
import { changeThemeInMarkup, Theme } from '../utils/theme';
|
import { changeThemeInMarkup, Theme } from '../utils/theme';
|
||||||
import { Settings, UiSettings } from './reducers/settings';
|
import { Settings, UiSettings } from './reducers/settings';
|
||||||
import './UserInterfaceSettings.scss';
|
import './UserInterfaceSettings.scss';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Bottle from 'bottlejs';
|
import Bottle from 'bottlejs';
|
||||||
import RealTimeUpdatesSettings from '../RealTimeUpdatesSettings';
|
import { RealTimeUpdatesSettings } from '../RealTimeUpdatesSettings';
|
||||||
import Settings from '../Settings';
|
import { Settings } from '../Settings';
|
||||||
import {
|
import {
|
||||||
setRealTimeUpdatesInterval,
|
setRealTimeUpdatesInterval,
|
||||||
setShortUrlCreationSettings,
|
setShortUrlCreationSettings,
|
||||||
|
|||||||
@@ -33,7 +33,10 @@ const getInitialState = (settings?: ShortUrlCreationSettings): ShortUrlData => (
|
|||||||
forwardQuery: settings?.forwardQuery ?? true,
|
forwardQuery: settings?.forwardQuery ?? true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const CreateShortUrl = (ShortUrlForm: FC<ShortUrlFormProps>, CreateShortUrlResult: FC<CreateShortUrlResultProps>) => ({
|
export const CreateShortUrl = (
|
||||||
|
ShortUrlForm: FC<ShortUrlFormProps>,
|
||||||
|
CreateShortUrlResult: FC<CreateShortUrlResultProps>,
|
||||||
|
) => ({
|
||||||
createShortUrl,
|
createShortUrl,
|
||||||
shortUrlCreationResult,
|
shortUrlCreationResult,
|
||||||
resetCreateShortUrl,
|
resetCreateShortUrl,
|
||||||
@@ -64,5 +67,3 @@ const CreateShortUrl = (ShortUrlForm: FC<ShortUrlFormProps>, CreateShortUrlResul
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CreateShortUrl;
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { SelectedServer } from '../servers/data';
|
|||||||
import { Settings, ShortUrlCreationSettings } from '../settings/reducers/settings';
|
import { Settings, ShortUrlCreationSettings } from '../settings/reducers/settings';
|
||||||
import { OptionalString } from '../utils/utils';
|
import { OptionalString } from '../utils/utils';
|
||||||
import { parseQuery } from '../utils/helpers/query';
|
import { parseQuery } from '../utils/helpers/query';
|
||||||
import Message from '../utils/Message';
|
import { Message } from '../utils/Message';
|
||||||
import { Result } from '../utils/Result';
|
import { Result } from '../utils/Result';
|
||||||
import { ShlinkApiError } from '../api/ShlinkApiError';
|
import { ShlinkApiError } from '../api/ShlinkApiError';
|
||||||
import { useGoBack, useToggle } from '../utils/helpers/hooks';
|
import { useGoBack, useToggle } from '../utils/helpers/hooks';
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ interface PaginatorProps {
|
|||||||
currentQueryString?: string;
|
currentQueryString?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Paginator = ({ paginator, serverId, currentQueryString = '' }: PaginatorProps) => {
|
export const Paginator = ({ paginator, serverId, currentQueryString = '' }: PaginatorProps) => {
|
||||||
const { currentPage = 0, pagesCount = 0 } = paginator ?? {};
|
const { currentPage = 0, pagesCount = 0 } = paginator ?? {};
|
||||||
const urlForPage = (pageNumber: NumberOrEllipsis) =>
|
const urlForPage = (pageNumber: NumberOrEllipsis) =>
|
||||||
`/server/${serverId}/list-short-urls/${pageNumber}${currentQueryString}`;
|
`/server/${serverId}/list-short-urls/${pageNumber}${currentQueryString}`;
|
||||||
@@ -49,5 +49,3 @@ const Paginator = ({ paginator, serverId, currentQueryString = '' }: PaginatorPr
|
|||||||
</Pagination>
|
</Pagination>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Paginator;
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import { InputType } from 'reactstrap/types/lib/Input';
|
|||||||
import { Button, FormGroup, Input, Row } from 'reactstrap';
|
import { Button, FormGroup, Input, Row } from 'reactstrap';
|
||||||
import { cond, isEmpty, pipe, replace, trim, T } from 'ramda';
|
import { cond, isEmpty, pipe, replace, trim, T } from 'ramda';
|
||||||
import { parseISO } from 'date-fns';
|
import { parseISO } from 'date-fns';
|
||||||
import DateInput, { DateInputProps } from '../utils/DateInput';
|
import { DateInput, DateInputProps } from '../utils/DateInput';
|
||||||
import { supportsCrawlableVisits, supportsForwardQuery } from '../utils/helpers/features';
|
import { supportsCrawlableVisits, supportsForwardQuery } from '../utils/helpers/features';
|
||||||
import { SimpleCard } from '../utils/SimpleCard';
|
import { SimpleCard } from '../utils/SimpleCard';
|
||||||
import { handleEventPreventingDefault, hasValue, OptionalString } from '../utils/utils';
|
import { handleEventPreventingDefault, hasValue, OptionalString } from '../utils/utils';
|
||||||
import Checkbox from '../utils/Checkbox';
|
import { Checkbox } from '../utils/Checkbox';
|
||||||
import { SelectedServer } from '../servers/data';
|
import { SelectedServer } from '../servers/data';
|
||||||
import { TagsSelectorProps } from '../tags/helpers/TagsSelector';
|
import { TagsSelectorProps } from '../tags/helpers/TagsSelector';
|
||||||
import { DomainSelectorProps } from '../domains/DomainSelector';
|
import { DomainSelectorProps } from '../domains/DomainSelector';
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { ShlinkShortUrlsListParams } from '../api/types';
|
|||||||
import { DEFAULT_SHORT_URLS_ORDERING, Settings } from '../settings/reducers/settings';
|
import { DEFAULT_SHORT_URLS_ORDERING, Settings } from '../settings/reducers/settings';
|
||||||
import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList';
|
import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList';
|
||||||
import { ShortUrlsTableProps } from './ShortUrlsTable';
|
import { ShortUrlsTableProps } from './ShortUrlsTable';
|
||||||
import Paginator from './Paginator';
|
import { Paginator } from './Paginator';
|
||||||
import { useShortUrlsQuery } from './helpers/hooks';
|
import { useShortUrlsQuery } from './helpers/hooks';
|
||||||
import { ShortUrlsOrderableFields } from './data';
|
import { ShortUrlsOrderableFields } from './data';
|
||||||
import { ShortUrlsFilteringProps } from './ShortUrlsFilteringBar';
|
import { ShortUrlsFilteringProps } from './ShortUrlsFilteringBar';
|
||||||
@@ -23,7 +23,7 @@ interface ShortUrlsListProps {
|
|||||||
settings: Settings;
|
settings: Settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShortUrlsList = (
|
export const ShortUrlsList = (
|
||||||
ShortUrlsTable: FC<ShortUrlsTableProps>,
|
ShortUrlsTable: FC<ShortUrlsTableProps>,
|
||||||
ShortUrlsFilteringBar: FC<ShortUrlsFilteringProps>,
|
ShortUrlsFilteringBar: FC<ShortUrlsFilteringProps>,
|
||||||
) => boundToMercureHub(({ listShortUrls, shortUrlsList, selectedServer, settings }: ShortUrlsListProps) => {
|
) => boundToMercureHub(({ listShortUrls, shortUrlsList, selectedServer, settings }: ShortUrlsListProps) => {
|
||||||
@@ -83,5 +83,3 @@ const ShortUrlsList = (
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, () => [Topics.visits]);
|
}, () => [Topics.visits]);
|
||||||
|
|
||||||
export default ShortUrlsList;
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export interface CreateShortUrlResultProps extends ShortUrlCreation {
|
|||||||
canBeClosed?: boolean;
|
canBeClosed?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreateShortUrlResult = (useStateFlagTimeout: StateFlagTimeout) => (
|
export const CreateShortUrlResult = (useStateFlagTimeout: StateFlagTimeout) => (
|
||||||
{ error, errorData, result, resetCreateShortUrl, canBeClosed = false }: CreateShortUrlResultProps,
|
{ error, errorData, result, resetCreateShortUrl, canBeClosed = false }: CreateShortUrlResultProps,
|
||||||
) => {
|
) => {
|
||||||
const [showCopyTooltip, setShowCopyTooltip] = useStateFlagTimeout();
|
const [showCopyTooltip, setShowCopyTooltip] = useStateFlagTimeout();
|
||||||
@@ -61,5 +61,3 @@ const CreateShortUrlResult = (useStateFlagTimeout: StateFlagTimeout) => (
|
|||||||
</Result>
|
</Result>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CreateShortUrlResult;
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ interface DeleteShortUrlModalConnectProps extends ShortUrlModalProps {
|
|||||||
resetDeleteShortUrl: () => void;
|
resetDeleteShortUrl: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeleteShortUrlModal = (
|
export const DeleteShortUrlModal = (
|
||||||
{ shortUrl, toggle, isOpen, shortUrlDeletion, resetDeleteShortUrl, deleteShortUrl }: DeleteShortUrlModalConnectProps,
|
{ shortUrl, toggle, isOpen, shortUrlDeletion, resetDeleteShortUrl, deleteShortUrl }: DeleteShortUrlModalConnectProps,
|
||||||
) => {
|
) => {
|
||||||
const [inputValue, setInputValue] = useState('');
|
const [inputValue, setInputValue] = useState('');
|
||||||
@@ -70,5 +70,3 @@ const DeleteShortUrlModal = (
|
|||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DeleteShortUrlModal;
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ interface QrCodeModalConnectProps extends ShortUrlModalProps {
|
|||||||
selectedServer: SelectedServer;
|
selectedServer: SelectedServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QrCodeModal = (imageDownloader: ImageDownloader) => (
|
export const QrCodeModal = (imageDownloader: ImageDownloader) => (
|
||||||
{ shortUrl: { shortUrl, shortCode }, toggle, isOpen, selectedServer }: QrCodeModalConnectProps,
|
{ shortUrl: { shortUrl, shortCode }, toggle, isOpen, selectedServer }: QrCodeModalConnectProps,
|
||||||
) => {
|
) => {
|
||||||
const [size, setSize] = useState(300);
|
const [size, setSize] = useState(300);
|
||||||
@@ -107,5 +107,3 @@ const QrCodeModal = (imageDownloader: ImageDownloader) => (
|
|||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default QrCodeModal;
|
|
||||||
|
|||||||
@@ -13,11 +13,10 @@ export interface ShortUrlDetailLinkProps {
|
|||||||
|
|
||||||
const buildUrl = ({ id }: ServerWithId, { shortCode, domain }: ShortUrl, suffix: LinkSuffix) => {
|
const buildUrl = ({ id }: ServerWithId, { shortCode, domain }: ShortUrl, suffix: LinkSuffix) => {
|
||||||
const query = domain ? `?domain=${domain}` : '';
|
const query = domain ? `?domain=${domain}` : '';
|
||||||
|
|
||||||
return `/server/${id}/short-code/${shortCode}/${suffix}${query}`;
|
return `/server/${id}/short-code/${shortCode}/${suffix}${query}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ShortUrlDetailLink: FC<ShortUrlDetailLinkProps & Record<string | number, any>> = (
|
export const ShortUrlDetailLink: FC<ShortUrlDetailLinkProps & Record<string | number, any>> = (
|
||||||
{ selectedServer, shortUrl, suffix, children, ...rest },
|
{ selectedServer, shortUrl, suffix, children, ...rest },
|
||||||
) => {
|
) => {
|
||||||
if (!selectedServer || !isServerWithId(selectedServer) || !shortUrl) {
|
if (!selectedServer || !isServerWithId(selectedServer) || !shortUrl) {
|
||||||
@@ -26,5 +25,3 @@ const ShortUrlDetailLink: FC<ShortUrlDetailLinkProps & Record<string | number, a
|
|||||||
|
|
||||||
return <Link to={buildUrl(selectedServer, shortUrl, suffix)} {...rest}>{children}</Link>;
|
return <Link to={buildUrl(selectedServer, shortUrl, suffix)} {...rest}>{children}</Link>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShortUrlDetailLink;
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ChangeEvent, FC, PropsWithChildren } from 'react';
|
import { ChangeEvent, FC, PropsWithChildren } from 'react';
|
||||||
import Checkbox from '../../utils/Checkbox';
|
import { Checkbox } from '../../utils/Checkbox';
|
||||||
import { InfoTooltip } from '../../utils/InfoTooltip';
|
import { InfoTooltip } from '../../utils/InfoTooltip';
|
||||||
|
|
||||||
type ShortUrlFormCheckboxGroupProps = PropsWithChildren<{
|
type ShortUrlFormCheckboxGroupProps = PropsWithChildren<{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import classNames from 'classnames';
|
|||||||
import { prettify } from '../../utils/helpers/numbers';
|
import { prettify } from '../../utils/helpers/numbers';
|
||||||
import { ShortUrl } from '../data';
|
import { ShortUrl } from '../data';
|
||||||
import { SelectedServer } from '../../servers/data';
|
import { SelectedServer } from '../../servers/data';
|
||||||
import ShortUrlDetailLink from './ShortUrlDetailLink';
|
import { ShortUrlDetailLink } from './ShortUrlDetailLink';
|
||||||
import './ShortUrlVisitsCount.scss';
|
import './ShortUrlVisitsCount.scss';
|
||||||
|
|
||||||
interface ShortUrlVisitsCountProps {
|
interface ShortUrlVisitsCountProps {
|
||||||
@@ -16,7 +16,9 @@ interface ShortUrlVisitsCountProps {
|
|||||||
active?: boolean;
|
active?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShortUrlVisitsCount = ({ visitsCount, shortUrl, selectedServer, active = false }: ShortUrlVisitsCountProps) => {
|
export const ShortUrlVisitsCount = (
|
||||||
|
{ visitsCount, shortUrl, selectedServer, active = false }: ShortUrlVisitsCountProps,
|
||||||
|
) => {
|
||||||
const maxVisits = shortUrl?.meta?.maxVisits;
|
const maxVisits = shortUrl?.meta?.maxVisits;
|
||||||
const visitsLink = (
|
const visitsLink = (
|
||||||
<ShortUrlDetailLink selectedServer={selectedServer} shortUrl={shortUrl} suffix="visits">
|
<ShortUrlDetailLink selectedServer={selectedServer} shortUrl={shortUrl} suffix="visits">
|
||||||
@@ -57,5 +59,3 @@ const ShortUrlVisitsCount = ({ visitsCount, shortUrl, selectedServer, active = f
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShortUrlVisitsCount;
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { FC, useEffect, useRef } from 'react';
|
import { FC, useEffect, useRef } from 'react';
|
||||||
import { isEmpty } from 'ramda';
|
import { isEmpty } from 'ramda';
|
||||||
import { ExternalLink } from 'react-external-link';
|
import { ExternalLink } from 'react-external-link';
|
||||||
import ColorGenerator from '../../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../../utils/services/ColorGenerator';
|
||||||
import { StateFlagTimeout } from '../../utils/helpers/hooks';
|
import { StateFlagTimeout } from '../../utils/helpers/hooks';
|
||||||
import Tag from '../../tags/helpers/Tag';
|
import { Tag } from '../../tags/helpers/Tag';
|
||||||
import { SelectedServer } from '../../servers/data';
|
import { SelectedServer } from '../../servers/data';
|
||||||
import { CopyToClipboardIcon } from '../../utils/CopyToClipboardIcon';
|
import { CopyToClipboardIcon } from '../../utils/CopyToClipboardIcon';
|
||||||
import { ShortUrl } from '../data';
|
import { ShortUrl } from '../data';
|
||||||
import { Time } from '../../utils/Time';
|
import { Time } from '../../utils/Time';
|
||||||
import ShortUrlVisitsCount from './ShortUrlVisitsCount';
|
import { ShortUrlVisitsCount } from './ShortUrlVisitsCount';
|
||||||
import { ShortUrlsRowMenuProps } from './ShortUrlsRowMenu';
|
import { ShortUrlsRowMenuProps } from './ShortUrlsRowMenu';
|
||||||
import './ShortUrlsRow.scss';
|
import './ShortUrlsRow.scss';
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ export interface ShortUrlsRowProps {
|
|||||||
shortUrl: ShortUrl;
|
shortUrl: ShortUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShortUrlsRow = (
|
export const ShortUrlsRow = (
|
||||||
ShortUrlsRowMenu: FC<ShortUrlsRowMenuProps>,
|
ShortUrlsRowMenu: FC<ShortUrlsRowMenuProps>,
|
||||||
colorGenerator: ColorGenerator,
|
colorGenerator: ColorGenerator,
|
||||||
useStateFlagTimeout: StateFlagTimeout,
|
useStateFlagTimeout: StateFlagTimeout,
|
||||||
@@ -87,5 +87,3 @@ const ShortUrlsRow = (
|
|||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShortUrlsRow;
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { useToggle } from '../../utils/helpers/hooks';
|
|||||||
import { ShortUrl, ShortUrlModalProps } from '../data';
|
import { ShortUrl, ShortUrlModalProps } from '../data';
|
||||||
import { SelectedServer } from '../../servers/data';
|
import { SelectedServer } from '../../servers/data';
|
||||||
import { DropdownBtnMenu } from '../../utils/DropdownBtnMenu';
|
import { DropdownBtnMenu } from '../../utils/DropdownBtnMenu';
|
||||||
import ShortUrlDetailLink from './ShortUrlDetailLink';
|
import { ShortUrlDetailLink } from './ShortUrlDetailLink';
|
||||||
|
|
||||||
export interface ShortUrlsRowMenuProps {
|
export interface ShortUrlsRowMenuProps {
|
||||||
selectedServer: SelectedServer;
|
selectedServer: SelectedServer;
|
||||||
@@ -19,7 +19,7 @@ export interface ShortUrlsRowMenuProps {
|
|||||||
}
|
}
|
||||||
type ShortUrlModal = FC<ShortUrlModalProps>;
|
type ShortUrlModal = FC<ShortUrlModalProps>;
|
||||||
|
|
||||||
const ShortUrlsRowMenu = (
|
export const ShortUrlsRowMenu = (
|
||||||
DeleteShortUrlModal: ShortUrlModal,
|
DeleteShortUrlModal: ShortUrlModal,
|
||||||
QrCodeModal: ShortUrlModal,
|
QrCodeModal: ShortUrlModal,
|
||||||
) => ({ shortUrl, selectedServer }: ShortUrlsRowMenuProps) => {
|
) => ({ shortUrl, selectedServer }: ShortUrlsRowMenuProps) => {
|
||||||
@@ -51,5 +51,3 @@ const ShortUrlsRowMenu = (
|
|||||||
</DropdownBtnMenu>
|
</DropdownBtnMenu>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShortUrlsRowMenu;
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import Bottle from 'bottlejs';
|
import Bottle from 'bottlejs';
|
||||||
import { ShortUrlsFilteringBar } from '../ShortUrlsFilteringBar';
|
import { ShortUrlsFilteringBar } from '../ShortUrlsFilteringBar';
|
||||||
import ShortUrlsList from '../ShortUrlsList';
|
import { ShortUrlsList } from '../ShortUrlsList';
|
||||||
import ShortUrlsRow from '../helpers/ShortUrlsRow';
|
import { ShortUrlsRow } from '../helpers/ShortUrlsRow';
|
||||||
import ShortUrlsRowMenu from '../helpers/ShortUrlsRowMenu';
|
import { ShortUrlsRowMenu } from '../helpers/ShortUrlsRowMenu';
|
||||||
import CreateShortUrl from '../CreateShortUrl';
|
import { CreateShortUrl } from '../CreateShortUrl';
|
||||||
import DeleteShortUrlModal from '../helpers/DeleteShortUrlModal';
|
import { DeleteShortUrlModal } from '../helpers/DeleteShortUrlModal';
|
||||||
import CreateShortUrlResult from '../helpers/CreateShortUrlResult';
|
import { CreateShortUrlResult } from '../helpers/CreateShortUrlResult';
|
||||||
import { listShortUrls } from '../reducers/shortUrlsList';
|
import { listShortUrls } from '../reducers/shortUrlsList';
|
||||||
import { createShortUrl, resetCreateShortUrl } from '../reducers/shortUrlCreation';
|
import { createShortUrl, resetCreateShortUrl } from '../reducers/shortUrlCreation';
|
||||||
import { deleteShortUrl, resetDeleteShortUrl } from '../reducers/shortUrlDeletion';
|
import { deleteShortUrl, resetDeleteShortUrl } from '../reducers/shortUrlDeletion';
|
||||||
import { editShortUrl } from '../reducers/shortUrlEdition';
|
import { editShortUrl } from '../reducers/shortUrlEdition';
|
||||||
import { ConnectDecorator } from '../../container/types';
|
import { ConnectDecorator } from '../../container/types';
|
||||||
import { ShortUrlsTable } from '../ShortUrlsTable';
|
import { ShortUrlsTable } from '../ShortUrlsTable';
|
||||||
import QrCodeModal from '../helpers/QrCodeModal';
|
import { QrCodeModal } from '../helpers/QrCodeModal';
|
||||||
import { ShortUrlForm } from '../ShortUrlForm';
|
import { ShortUrlForm } from '../ShortUrlForm';
|
||||||
import { EditShortUrl } from '../EditShortUrl';
|
import { EditShortUrl } from '../EditShortUrl';
|
||||||
import { getShortUrlDetail } from '../reducers/shortUrlDetail';
|
import { getShortUrlDetail } from '../reducers/shortUrlDetail';
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { FC, useEffect, useRef } from 'react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { prettify } from '../utils/helpers/numbers';
|
import { prettify } from '../utils/helpers/numbers';
|
||||||
import { useToggle } from '../utils/helpers/hooks';
|
import { useToggle } from '../utils/helpers/hooks';
|
||||||
import ColorGenerator from '../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../utils/services/ColorGenerator';
|
||||||
import { getServerId, SelectedServer } from '../servers/data';
|
import { getServerId, SelectedServer } from '../servers/data';
|
||||||
import TagBullet from './helpers/TagBullet';
|
import { TagBullet } from './helpers/TagBullet';
|
||||||
import { NormalizedTag, TagModalProps } from './data';
|
import { NormalizedTag, TagModalProps } from './data';
|
||||||
import './TagCard.scss';
|
import './TagCard.scss';
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export interface TagCardProps {
|
|||||||
|
|
||||||
const isTruncated = (el: HTMLElement | undefined): boolean => !!el && el.scrollWidth > el.clientWidth;
|
const isTruncated = (el: HTMLElement | undefined): boolean => !!el && el.scrollWidth > el.clientWidth;
|
||||||
|
|
||||||
const TagCard = (
|
export const TagCard = (
|
||||||
DeleteTagConfirmModal: FC<TagModalProps>,
|
DeleteTagConfirmModal: FC<TagModalProps>,
|
||||||
EditTagModal: FC<TagModalProps>,
|
EditTagModal: FC<TagModalProps>,
|
||||||
colorGenerator: ColorGenerator,
|
colorGenerator: ColorGenerator,
|
||||||
@@ -40,10 +40,16 @@ const TagCard = (
|
|||||||
return (
|
return (
|
||||||
<Card className="tag-card">
|
<Card className="tag-card">
|
||||||
<CardHeader className="tag-card__header">
|
<CardHeader className="tag-card__header">
|
||||||
<Button color="link" size="sm" className="tag-card__btn tag-card__btn--last" onClick={toggleDelete}>
|
<Button
|
||||||
|
aria-label="Delete tag"
|
||||||
|
color="link"
|
||||||
|
size="sm"
|
||||||
|
className="tag-card__btn tag-card__btn--last"
|
||||||
|
onClick={toggleDelete}
|
||||||
|
>
|
||||||
<FontAwesomeIcon icon={deleteIcon} />
|
<FontAwesomeIcon icon={deleteIcon} />
|
||||||
</Button>
|
</Button>
|
||||||
<Button color="link" size="sm" className="tag-card__btn" onClick={toggleEdit}>
|
<Button aria-label="Edit tag" color="link" size="sm" className="tag-card__btn" onClick={toggleEdit}>
|
||||||
<FontAwesomeIcon icon={editIcon} />
|
<FontAwesomeIcon icon={editIcon} />
|
||||||
</Button>
|
</Button>
|
||||||
<h5
|
<h5
|
||||||
@@ -82,5 +88,3 @@ const TagCard = (
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TagCard;
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { Row } from 'reactstrap';
|
import { Row } from 'reactstrap';
|
||||||
import { pipe } from 'ramda';
|
import { pipe } from 'ramda';
|
||||||
import Message from '../utils/Message';
|
import { Message } from '../utils/Message';
|
||||||
import { SearchField } from '../utils/SearchField';
|
import { SearchField } from '../utils/SearchField';
|
||||||
import { SelectedServer } from '../servers/data';
|
import { SelectedServer } from '../servers/data';
|
||||||
import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub';
|
import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub';
|
||||||
@@ -30,7 +30,7 @@ export interface TagsListProps {
|
|||||||
settings: Settings;
|
settings: Settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TagsList = (TagsCards: FC<TagsListChildrenProps>, TagsTable: FC<TagsTableProps>) => boundToMercureHub((
|
export const TagsList = (TagsCards: FC<TagsListChildrenProps>, TagsTable: FC<TagsTableProps>) => boundToMercureHub((
|
||||||
{ filterTags, forceListTags, tagsList, selectedServer, settings }: TagsListProps,
|
{ filterTags, forceListTags, tagsList, selectedServer, settings }: TagsListProps,
|
||||||
) => {
|
) => {
|
||||||
const [mode, setMode] = useState<TagsMode>(settings.tags?.defaultMode ?? 'cards');
|
const [mode, setMode] = useState<TagsMode>(settings.tags?.defaultMode ?? 'cards');
|
||||||
@@ -104,5 +104,3 @@ const TagsList = (TagsCards: FC<TagsListChildrenProps>, TagsTable: FC<TagsTableP
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, () => [Topics.visits]);
|
}, () => [Topics.visits]);
|
||||||
|
|
||||||
export default TagsList;
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import { DropdownItem } from 'reactstrap';
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faTrash as deleteIcon, faPencilAlt as editIcon } from '@fortawesome/free-solid-svg-icons';
|
import { faTrash as deleteIcon, faPencilAlt as editIcon } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { getServerId, SelectedServer } from '../servers/data';
|
import { getServerId, SelectedServer } from '../servers/data';
|
||||||
import ColorGenerator from '../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../utils/services/ColorGenerator';
|
||||||
import { prettify } from '../utils/helpers/numbers';
|
import { prettify } from '../utils/helpers/numbers';
|
||||||
import { useToggle } from '../utils/helpers/hooks';
|
import { useToggle } from '../utils/helpers/hooks';
|
||||||
import { DropdownBtnMenu } from '../utils/DropdownBtnMenu';
|
import { DropdownBtnMenu } from '../utils/DropdownBtnMenu';
|
||||||
import TagBullet from './helpers/TagBullet';
|
import { TagBullet } from './helpers/TagBullet';
|
||||||
import { NormalizedTag, TagModalProps } from './data';
|
import { NormalizedTag, TagModalProps } from './data';
|
||||||
|
|
||||||
export interface TagsTableRowProps {
|
export interface TagsTableRowProps {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface DeleteTagConfirmModalProps extends TagModalProps {
|
|||||||
tagDelete: TagDeletion;
|
tagDelete: TagDeletion;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeleteTagConfirmModal = (
|
export const DeleteTagConfirmModal = (
|
||||||
{ tag, toggle, isOpen, deleteTag, tagDelete, tagDeleted }: DeleteTagConfirmModalProps,
|
{ tag, toggle, isOpen, deleteTag, tagDelete, tagDeleted }: DeleteTagConfirmModalProps,
|
||||||
) => {
|
) => {
|
||||||
const { deleting, error, errorData } = tagDelete;
|
const { deleting, error, errorData } = tagDelete;
|
||||||
@@ -22,9 +22,7 @@ const DeleteTagConfirmModal = (
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal toggle={toggle} isOpen={isOpen} centered>
|
<Modal toggle={toggle} isOpen={isOpen} centered>
|
||||||
<ModalHeader toggle={toggle}>
|
<ModalHeader toggle={toggle} className="text-danger">Delete tag</ModalHeader>
|
||||||
<span className="text-danger">Delete tag</span>
|
|
||||||
</ModalHeader>
|
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
Are you sure you want to delete tag <b>{tag}</b>?
|
Are you sure you want to delete tag <b>{tag}</b>?
|
||||||
{error && (
|
{error && (
|
||||||
@@ -42,5 +40,3 @@ const DeleteTagConfirmModal = (
|
|||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DeleteTagConfirmModal;
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { faPalette as colorIcon } from '@fortawesome/free-solid-svg-icons';
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { useToggle } from '../../utils/helpers/hooks';
|
import { useToggle } from '../../utils/helpers/hooks';
|
||||||
import { handleEventPreventingDefault } from '../../utils/utils';
|
import { handleEventPreventingDefault } from '../../utils/utils';
|
||||||
import ColorGenerator from '../../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../../utils/services/ColorGenerator';
|
||||||
import { TagModalProps } from '../data';
|
import { TagModalProps } from '../data';
|
||||||
import { TagEdition } from '../reducers/tagEdit';
|
import { TagEdition } from '../reducers/tagEdit';
|
||||||
import { Result } from '../../utils/Result';
|
import { Result } from '../../utils/Result';
|
||||||
@@ -18,7 +18,7 @@ interface EditTagModalProps extends TagModalProps {
|
|||||||
tagEdited: (oldName: string, newName: string, color: string) => void;
|
tagEdited: (oldName: string, newName: string, color: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditTagModal = ({ getColorForKey }: ColorGenerator) => (
|
export const EditTagModal = ({ getColorForKey }: ColorGenerator) => (
|
||||||
{ tag, editTag, toggle, tagEdited, isOpen, tagEdit }: EditTagModalProps,
|
{ tag, editTag, toggle, tagEdited, isOpen, tagEdit }: EditTagModalProps,
|
||||||
) => {
|
) => {
|
||||||
const [newTagName, setNewTagName] = useState(tag);
|
const [newTagName, setNewTagName] = useState(tag);
|
||||||
@@ -78,5 +78,3 @@ const EditTagModal = ({ getColorForKey }: ColorGenerator) => (
|
|||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default EditTagModal;
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FC, MouseEventHandler, PropsWithChildren } from 'react';
|
import { FC, MouseEventHandler, PropsWithChildren } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import ColorGenerator from '../../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../../utils/services/ColorGenerator';
|
||||||
import './Tag.scss';
|
import './Tag.scss';
|
||||||
|
|
||||||
type TagProps = PropsWithChildren<{
|
type TagProps = PropsWithChildren<{
|
||||||
@@ -12,7 +12,7 @@ type TagProps = PropsWithChildren<{
|
|||||||
onClose?: MouseEventHandler;
|
onClose?: MouseEventHandler;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const Tag: FC<TagProps> = ({ text, children, clearable, className = '', colorGenerator, onClick, onClose }) => (
|
export const Tag: FC<TagProps> = ({ text, children, clearable, className = '', colorGenerator, onClick, onClose }) => (
|
||||||
<span
|
<span
|
||||||
className={classNames('badge tag', className, { 'tag--light-bg': colorGenerator.isColorLightForKey(text) })}
|
className={classNames('badge tag', className, { 'tag--light-bg': colorGenerator.isColorLightForKey(text) })}
|
||||||
style={{ backgroundColor: colorGenerator.getColorForKey(text), cursor: clearable || !onClick ? 'auto' : 'pointer' }}
|
style={{ backgroundColor: colorGenerator.getColorForKey(text), cursor: clearable || !onClick ? 'auto' : 'pointer' }}
|
||||||
@@ -22,5 +22,3 @@ const Tag: FC<TagProps> = ({ text, children, clearable, className = '', colorGen
|
|||||||
{clearable && <span className="close tag__close-selected-tag" onClick={onClose}>×</span>}
|
{clearable && <span className="close tag__close-selected-tag" onClick={onClose}>×</span>}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default Tag;
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import ColorGenerator from '../../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../../utils/services/ColorGenerator';
|
||||||
import './TagBullet.scss';
|
import './TagBullet.scss';
|
||||||
|
|
||||||
interface TagBulletProps {
|
interface TagBulletProps {
|
||||||
@@ -6,11 +6,9 @@ interface TagBulletProps {
|
|||||||
colorGenerator: ColorGenerator;
|
colorGenerator: ColorGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TagBullet = ({ tag, colorGenerator }: TagBulletProps) => (
|
export const TagBullet = ({ tag, colorGenerator }: TagBulletProps) => (
|
||||||
<div
|
<div
|
||||||
style={{ backgroundColor: colorGenerator.getColorForKey(tag) }}
|
style={{ backgroundColor: colorGenerator.getColorForKey(tag) }}
|
||||||
className="tag-bullet"
|
className="tag-bullet"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default TagBullet;
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import ReactTags, { SuggestionComponentProps, TagComponentProps } from 'react-tag-autocomplete';
|
import ReactTags, { SuggestionComponentProps, TagComponentProps } from 'react-tag-autocomplete';
|
||||||
import ColorGenerator from '../../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../../utils/services/ColorGenerator';
|
||||||
import { Settings } from '../../settings/reducers/settings';
|
import { Settings } from '../../settings/reducers/settings';
|
||||||
import { TagsList } from '../reducers/tagsList';
|
import { TagsList } from '../reducers/tagsList';
|
||||||
import TagBullet from './TagBullet';
|
import { TagBullet } from './TagBullet';
|
||||||
import Tag from './Tag';
|
import { Tag } from './Tag';
|
||||||
|
|
||||||
export interface TagsSelectorProps {
|
export interface TagsSelectorProps {
|
||||||
selectedTags: string[];
|
selectedTags: string[];
|
||||||
@@ -21,7 +21,7 @@ interface TagsSelectorConnectProps extends TagsSelectorProps {
|
|||||||
|
|
||||||
const toComponentTag = (tag: string) => ({ id: tag, name: tag });
|
const toComponentTag = (tag: string) => ({ id: tag, name: tag });
|
||||||
|
|
||||||
const TagsSelector = (colorGenerator: ColorGenerator) => (
|
export const TagsSelector = (colorGenerator: ColorGenerator) => (
|
||||||
{ selectedTags, onChange, placeholder, listTags, tagsList, settings, allowNew = true }: TagsSelectorConnectProps,
|
{ selectedTags, onChange, placeholder, listTags, tagsList, settings, allowNew = true }: TagsSelectorConnectProps,
|
||||||
) => {
|
) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -68,5 +68,3 @@ const TagsSelector = (colorGenerator: ColorGenerator) => (
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TagsSelector;
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { pick } from 'ramda';
|
|||||||
import { Action, Dispatch } from 'redux';
|
import { Action, Dispatch } from 'redux';
|
||||||
import { buildReducer } from '../../utils/helpers/redux';
|
import { buildReducer } from '../../utils/helpers/redux';
|
||||||
import { GetState } from '../../container/types';
|
import { GetState } from '../../container/types';
|
||||||
import ColorGenerator from '../../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../../utils/services/ColorGenerator';
|
||||||
import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder';
|
import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder';
|
||||||
import { ProblemDetailsError } from '../../api/types';
|
import { ProblemDetailsError } from '../../api/types';
|
||||||
import { parseApiError } from '../../api/utils';
|
import { parseApiError } from '../../api/utils';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import Bottle, { IContainer } from 'bottlejs';
|
import Bottle, { IContainer } from 'bottlejs';
|
||||||
import TagsSelector from '../helpers/TagsSelector';
|
import { TagsSelector } from '../helpers/TagsSelector';
|
||||||
import TagCard from '../TagCard';
|
import { TagCard } from '../TagCard';
|
||||||
import DeleteTagConfirmModal from '../helpers/DeleteTagConfirmModal';
|
import { DeleteTagConfirmModal } from '../helpers/DeleteTagConfirmModal';
|
||||||
import EditTagModal from '../helpers/EditTagModal';
|
import { EditTagModal } from '../helpers/EditTagModal';
|
||||||
import TagsList from '../TagsList';
|
import { TagsList } from '../TagsList';
|
||||||
import { filterTags, listTags } from '../reducers/tagsList';
|
import { filterTags, listTags } from '../reducers/tagsList';
|
||||||
import { deleteTag, tagDeleted } from '../reducers/tagDelete';
|
import { deleteTag, tagDeleted } from '../reducers/tagDelete';
|
||||||
import { editTag, tagEdited } from '../reducers/tagEdit';
|
import { editTag, tagEdited } from '../reducers/tagEdit';
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ interface BooleanControlWithTypeProps extends BooleanControlProps {
|
|||||||
type: 'switch' | 'checkbox';
|
type: 'switch' | 'checkbox';
|
||||||
}
|
}
|
||||||
|
|
||||||
const BooleanControl: FC<BooleanControlWithTypeProps> = (
|
export const BooleanControl: FC<BooleanControlWithTypeProps> = (
|
||||||
{ checked = false, onChange = identity, className, children, type, inline = false },
|
{ checked = false, onChange = identity, className, children, type, inline = false },
|
||||||
) => {
|
) => {
|
||||||
const id = useDomId();
|
const id = useDomId();
|
||||||
@@ -32,5 +32,3 @@ const BooleanControl: FC<BooleanControlWithTypeProps> = (
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BooleanControl;
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import BooleanControl, { BooleanControlProps } from './BooleanControl';
|
import { BooleanControl, BooleanControlProps } from './BooleanControl';
|
||||||
|
|
||||||
const Checkbox: FC<BooleanControlProps> = (props) => <BooleanControl type="checkbox" {...props} />;
|
export const Checkbox: FC<BooleanControlProps> = (props) => <BooleanControl type="checkbox" {...props} />;
|
||||||
|
|
||||||
export default Checkbox;
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import './DateInput.scss';
|
|||||||
|
|
||||||
export type DateInputProps = ReactDatePickerProps;
|
export type DateInputProps = ReactDatePickerProps;
|
||||||
|
|
||||||
const DateInput = (props: DateInputProps) => {
|
export const DateInput = (props: DateInputProps) => {
|
||||||
const { className, isClearable, selected } = props;
|
const { className, isClearable, selected } = props;
|
||||||
const showCalendarIcon = !isClearable || isNil(selected);
|
const showCalendarIcon = !isClearable || isNil(selected);
|
||||||
const ref = useRef<{ input: HTMLInputElement }>();
|
const ref = useRef<{ input: HTMLInputElement }>();
|
||||||
@@ -32,5 +32,3 @@ const DateInput = (props: DateInputProps) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DateInput;
|
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ export type MessageProps = PropsWithChildren<{
|
|||||||
type?: MessageType;
|
type?: MessageType;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const Message: FC<MessageProps> = ({ className, children, loading = false, type = 'default', fullWidth = false }) => {
|
export const Message: FC<MessageProps> = (
|
||||||
|
{ className, children, loading = false, type = 'default', fullWidth = false },
|
||||||
|
) => {
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
'col-md-12': fullWidth,
|
'col-md-12': fullWidth,
|
||||||
'col-md-10 offset-md-1': !fullWidth,
|
'col-md-10 offset-md-1': !fullWidth,
|
||||||
@@ -50,5 +52,3 @@ const Message: FC<MessageProps> = ({ className, children, loading = false, type
|
|||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Message;
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ interface PaginationDropdownProps {
|
|||||||
toggleClassName?: string;
|
toggleClassName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PaginationDropdown = ({ toggleClassName, ranges, value, setValue }: PaginationDropdownProps) => (
|
export const PaginationDropdown = ({ toggleClassName, ranges, value, setValue }: PaginationDropdownProps) => (
|
||||||
<UncontrolledDropdown>
|
<UncontrolledDropdown>
|
||||||
<DropdownToggle caret color="link" className={toggleClassName}>Paginate</DropdownToggle>
|
<DropdownToggle caret color="link" className={toggleClassName}>Paginate</DropdownToggle>
|
||||||
<DropdownMenu end>
|
<DropdownMenu end>
|
||||||
@@ -23,5 +23,3 @@ const PaginationDropdown = ({ toggleClassName, ranges, value, setValue }: Pagina
|
|||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</UncontrolledDropdown>
|
</UncontrolledDropdown>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default PaginationDropdown;
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import BooleanControl, { BooleanControlProps } from './BooleanControl';
|
import { BooleanControl, BooleanControlProps } from './BooleanControl';
|
||||||
|
|
||||||
const ToggleSwitch: FC<BooleanControlProps> = (props) => <BooleanControl type="switch" {...props} />;
|
export const ToggleSwitch: FC<BooleanControlProps> = (props) => <BooleanControl type="switch" {...props} />;
|
||||||
|
|
||||||
export default ToggleSwitch;
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { endOfDay } from 'date-fns';
|
import { endOfDay } from 'date-fns';
|
||||||
import DateInput from '../DateInput';
|
import { DateInput } from '../DateInput';
|
||||||
import { DateRange } from './types';
|
import { DateRange } from './types';
|
||||||
|
|
||||||
interface DateRangeRowProps extends DateRange {
|
interface DateRangeRowProps extends DateRange {
|
||||||
@@ -8,7 +8,7 @@ interface DateRangeRowProps extends DateRange {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DateRangeRow = (
|
export const DateRangeRow = (
|
||||||
{ startDate = null, endDate = null, disabled = false, onStartDateChange, onEndDateChange }: DateRangeRowProps,
|
{ startDate = null, endDate = null, disabled = false, onStartDateChange, onEndDateChange }: DateRangeRowProps,
|
||||||
) => (
|
) => (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@@ -35,5 +35,3 @@ const DateRangeRow = (
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default DateRangeRow;
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
rangeIsInterval,
|
rangeIsInterval,
|
||||||
dateRangeIsEmpty,
|
dateRangeIsEmpty,
|
||||||
} from './types';
|
} from './types';
|
||||||
import DateRangeRow from './DateRangeRow';
|
import { DateRangeRow } from './DateRangeRow';
|
||||||
import { DateIntervalDropdownItems } from './DateIntervalDropdownItems';
|
import { DateIntervalDropdownItems } from './DateIntervalDropdownItems';
|
||||||
|
|
||||||
export interface DateRangeSelectorProps {
|
export interface DateRangeSelectorProps {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { isNil } from 'ramda';
|
import { isNil } from 'ramda';
|
||||||
import { rangeOf } from '../utils';
|
import { rangeOf } from '../utils';
|
||||||
import LocalStorage from './LocalStorage';
|
import { LocalStorage } from './LocalStorage';
|
||||||
|
|
||||||
const HEX_COLOR_LENGTH = 6;
|
const HEX_COLOR_LENGTH = 6;
|
||||||
const HEX_DIGITS = '0123456789ABCDEF';
|
const HEX_DIGITS = '0123456789ABCDEF';
|
||||||
@@ -15,7 +15,7 @@ const hexColorToRgbArray = (colorHex: string): number[] =>
|
|||||||
// HSP by Darel Rex Finley https://alienryderflex.com/hsp.html
|
// HSP by Darel Rex Finley https://alienryderflex.com/hsp.html
|
||||||
const perceivedLightness = (r = 0, g = 0, b = 0) => round(sqrt(0.299 * r ** 2 + 0.587 * g ** 2 + 0.114 * b ** 2));
|
const perceivedLightness = (r = 0, g = 0, b = 0) => round(sqrt(0.299 * r ** 2 + 0.587 * g ** 2 + 0.114 * b ** 2));
|
||||||
|
|
||||||
export default class ColorGenerator {
|
export class ColorGenerator {
|
||||||
private readonly colors: Record<string, string>;
|
private readonly colors: Record<string, string>;
|
||||||
private readonly lights: Record<string, boolean>;
|
private readonly lights: Record<string, boolean>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const PREFIX = 'shlink';
|
const PREFIX = 'shlink';
|
||||||
const buildPath = (path: string) => `${PREFIX}.${path}`;
|
const buildPath = (path: string) => `${PREFIX}.${path}`;
|
||||||
|
|
||||||
export default class LocalStorage {
|
export class LocalStorage {
|
||||||
public constructor(private readonly localStorage: Storage) {}
|
public constructor(private readonly localStorage: Storage) {}
|
||||||
|
|
||||||
public readonly get = <T>(key: string): T | undefined => {
|
public readonly get = <T>(key: string): T | undefined => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Bottle from 'bottlejs';
|
import Bottle from 'bottlejs';
|
||||||
import { useStateFlagTimeout } from '../helpers/hooks';
|
import { useStateFlagTimeout } from '../helpers/hooks';
|
||||||
import LocalStorage from './LocalStorage';
|
import { LocalStorage } from './LocalStorage';
|
||||||
import ColorGenerator from './ColorGenerator';
|
import { ColorGenerator } from './ColorGenerator';
|
||||||
import { csvToJson, jsonToCsv } from '../helpers/csvjson';
|
import { csvToJson, jsonToCsv } from '../helpers/csvjson';
|
||||||
|
|
||||||
const provideServices = (bottle: Bottle) => {
|
const provideServices = (bottle: Bottle) => {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { Topics } from '../mercure/helpers/Topics';
|
|||||||
import { useGoBack } from '../utils/helpers/hooks';
|
import { useGoBack } from '../utils/helpers/hooks';
|
||||||
import { toApiParams } from './types/helpers';
|
import { toApiParams } from './types/helpers';
|
||||||
import { NormalizedVisit } from './types';
|
import { NormalizedVisit } from './types';
|
||||||
import VisitsStats from './VisitsStats';
|
import { VisitsStats } from './VisitsStats';
|
||||||
import VisitsHeader from './VisitsHeader';
|
import { VisitsHeader } from './VisitsHeader';
|
||||||
|
|
||||||
export interface DomainVisitsProps extends CommonVisitsProps {
|
export interface DomainVisitsProps extends CommonVisitsProps {
|
||||||
getDomainVisits: (domain: string, query?: ShlinkVisitsParams, doIntervalFallback?: boolean) => void;
|
getDomainVisits: (domain: string, query?: ShlinkVisitsParams, doIntervalFallback?: boolean) => void;
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import { ShlinkVisitsParams } from '../api/types';
|
|||||||
import { Topics } from '../mercure/helpers/Topics';
|
import { Topics } from '../mercure/helpers/Topics';
|
||||||
import { useGoBack } from '../utils/helpers/hooks';
|
import { useGoBack } from '../utils/helpers/hooks';
|
||||||
import { ReportExporter } from '../common/services/ReportExporter';
|
import { ReportExporter } from '../common/services/ReportExporter';
|
||||||
import VisitsStats from './VisitsStats';
|
import { VisitsStats } from './VisitsStats';
|
||||||
import { NormalizedVisit, VisitsInfo, VisitsParams } from './types';
|
import { NormalizedVisit, VisitsInfo, VisitsParams } from './types';
|
||||||
import { CommonVisitsProps } from './types/CommonVisitsProps';
|
import { CommonVisitsProps } from './types/CommonVisitsProps';
|
||||||
import { toApiParams } from './types/helpers';
|
import { toApiParams } from './types/helpers';
|
||||||
import VisitsHeader from './VisitsHeader';
|
import { VisitsHeader } from './VisitsHeader';
|
||||||
|
|
||||||
export interface NonOrphanVisitsProps extends CommonVisitsProps {
|
export interface NonOrphanVisitsProps extends CommonVisitsProps {
|
||||||
getNonOrphanVisits: (params?: ShlinkVisitsParams, doIntervalFallback?: boolean) => void;
|
getNonOrphanVisits: (params?: ShlinkVisitsParams, doIntervalFallback?: boolean) => void;
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import { ShlinkVisitsParams } from '../api/types';
|
|||||||
import { Topics } from '../mercure/helpers/Topics';
|
import { Topics } from '../mercure/helpers/Topics';
|
||||||
import { useGoBack } from '../utils/helpers/hooks';
|
import { useGoBack } from '../utils/helpers/hooks';
|
||||||
import { ReportExporter } from '../common/services/ReportExporter';
|
import { ReportExporter } from '../common/services/ReportExporter';
|
||||||
import VisitsStats from './VisitsStats';
|
import { VisitsStats } from './VisitsStats';
|
||||||
import { NormalizedVisit, OrphanVisitType, VisitsInfo, VisitsParams } from './types';
|
import { NormalizedVisit, OrphanVisitType, VisitsInfo, VisitsParams } from './types';
|
||||||
import { CommonVisitsProps } from './types/CommonVisitsProps';
|
import { CommonVisitsProps } from './types/CommonVisitsProps';
|
||||||
import { toApiParams } from './types/helpers';
|
import { toApiParams } from './types/helpers';
|
||||||
import VisitsHeader from './VisitsHeader';
|
import { VisitsHeader } from './VisitsHeader';
|
||||||
|
|
||||||
export interface OrphanVisitsProps extends CommonVisitsProps {
|
export interface OrphanVisitsProps extends CommonVisitsProps {
|
||||||
getOrphanVisits: (
|
getOrphanVisits: (
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { ShortUrlDetail } from '../short-urls/reducers/shortUrlDetail';
|
|||||||
import { useGoBack } from '../utils/helpers/hooks';
|
import { useGoBack } from '../utils/helpers/hooks';
|
||||||
import { ReportExporter } from '../common/services/ReportExporter';
|
import { ReportExporter } from '../common/services/ReportExporter';
|
||||||
import { ShortUrlVisits as ShortUrlVisitsState } from './reducers/shortUrlVisits';
|
import { ShortUrlVisits as ShortUrlVisitsState } from './reducers/shortUrlVisits';
|
||||||
import ShortUrlVisitsHeader from './ShortUrlVisitsHeader';
|
import { ShortUrlVisitsHeader } from './ShortUrlVisitsHeader';
|
||||||
import VisitsStats from './VisitsStats';
|
import { VisitsStats } from './VisitsStats';
|
||||||
import { NormalizedVisit, VisitsParams } from './types';
|
import { NormalizedVisit, VisitsParams } from './types';
|
||||||
import { CommonVisitsProps } from './types/CommonVisitsProps';
|
import { CommonVisitsProps } from './types/CommonVisitsProps';
|
||||||
import { toApiParams } from './types/helpers';
|
import { toApiParams } from './types/helpers';
|
||||||
@@ -22,7 +22,7 @@ export interface ShortUrlVisitsProps extends CommonVisitsProps {
|
|||||||
cancelGetShortUrlVisits: () => void;
|
cancelGetShortUrlVisits: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShortUrlVisits = ({ exportVisits }: ReportExporter) => boundToMercureHub(({
|
export const ShortUrlVisits = ({ exportVisits }: ReportExporter) => boundToMercureHub(({
|
||||||
shortUrlVisits,
|
shortUrlVisits,
|
||||||
shortUrlDetail,
|
shortUrlDetail,
|
||||||
getShortUrlVisits,
|
getShortUrlVisits,
|
||||||
@@ -60,5 +60,3 @@ const ShortUrlVisits = ({ exportVisits }: ReportExporter) => boundToMercureHub((
|
|||||||
</VisitsStats>
|
</VisitsStats>
|
||||||
);
|
);
|
||||||
}, (_, params) => [Topics.shortUrlVisits(params.shortCode)]);
|
}, (_, params) => [Topics.shortUrlVisits(params.shortCode)]);
|
||||||
|
|
||||||
export default ShortUrlVisits;
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ExternalLink } from 'react-external-link';
|
|||||||
import { ShortUrlDetail } from '../short-urls/reducers/shortUrlDetail';
|
import { ShortUrlDetail } from '../short-urls/reducers/shortUrlDetail';
|
||||||
import { Time } from '../utils/Time';
|
import { Time } from '../utils/Time';
|
||||||
import { ShortUrlVisits } from './reducers/shortUrlVisits';
|
import { ShortUrlVisits } from './reducers/shortUrlVisits';
|
||||||
import VisitsHeader from './VisitsHeader';
|
import { VisitsHeader } from './VisitsHeader';
|
||||||
import './ShortUrlVisitsHeader.scss';
|
import './ShortUrlVisitsHeader.scss';
|
||||||
|
|
||||||
interface ShortUrlVisitsHeaderProps {
|
interface ShortUrlVisitsHeaderProps {
|
||||||
@@ -12,7 +12,7 @@ interface ShortUrlVisitsHeaderProps {
|
|||||||
goBack: () => void;
|
goBack: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShortUrlVisitsHeader = ({ shortUrlDetail, shortUrlVisits, goBack }: ShortUrlVisitsHeaderProps) => {
|
export const ShortUrlVisitsHeader = ({ shortUrlDetail, shortUrlVisits, goBack }: ShortUrlVisitsHeaderProps) => {
|
||||||
const { shortUrl, loading } = shortUrlDetail;
|
const { shortUrl, loading } = shortUrlDetail;
|
||||||
const { visits } = shortUrlVisits;
|
const { visits } = shortUrlVisits;
|
||||||
const shortLink = shortUrl?.shortUrl ?? '';
|
const shortLink = shortUrl?.shortUrl ?? '';
|
||||||
@@ -43,5 +43,3 @@ const ShortUrlVisitsHeader = ({ shortUrlDetail, shortUrlVisits, goBack }: ShortU
|
|||||||
</VisitsHeader>
|
</VisitsHeader>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShortUrlVisitsHeader;
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub';
|
import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub';
|
||||||
import ColorGenerator from '../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../utils/services/ColorGenerator';
|
||||||
import { ShlinkVisitsParams } from '../api/types';
|
import { ShlinkVisitsParams } from '../api/types';
|
||||||
import { Topics } from '../mercure/helpers/Topics';
|
import { Topics } from '../mercure/helpers/Topics';
|
||||||
import { useGoBack } from '../utils/helpers/hooks';
|
import { useGoBack } from '../utils/helpers/hooks';
|
||||||
import { ReportExporter } from '../common/services/ReportExporter';
|
import { ReportExporter } from '../common/services/ReportExporter';
|
||||||
import { TagVisits as TagVisitsState } from './reducers/tagVisits';
|
import { TagVisits as TagVisitsState } from './reducers/tagVisits';
|
||||||
import TagVisitsHeader from './TagVisitsHeader';
|
import { TagVisitsHeader } from './TagVisitsHeader';
|
||||||
import VisitsStats from './VisitsStats';
|
import { VisitsStats } from './VisitsStats';
|
||||||
import { NormalizedVisit } from './types';
|
import { NormalizedVisit } from './types';
|
||||||
import { CommonVisitsProps } from './types/CommonVisitsProps';
|
import { CommonVisitsProps } from './types/CommonVisitsProps';
|
||||||
import { toApiParams } from './types/helpers';
|
import { toApiParams } from './types/helpers';
|
||||||
@@ -18,7 +18,7 @@ export interface TagVisitsProps extends CommonVisitsProps {
|
|||||||
cancelGetTagVisits: () => void;
|
cancelGetTagVisits: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TagVisits = (colorGenerator: ColorGenerator, { exportVisits }: ReportExporter) => boundToMercureHub(({
|
export const TagVisits = (colorGenerator: ColorGenerator, { exportVisits }: ReportExporter) => boundToMercureHub(({
|
||||||
getTagVisits,
|
getTagVisits,
|
||||||
tagVisits,
|
tagVisits,
|
||||||
cancelGetTagVisits,
|
cancelGetTagVisits,
|
||||||
@@ -44,5 +44,3 @@ const TagVisits = (colorGenerator: ColorGenerator, { exportVisits }: ReportExpor
|
|||||||
</VisitsStats>
|
</VisitsStats>
|
||||||
);
|
);
|
||||||
}, () => [Topics.visits]);
|
}, () => [Topics.visits]);
|
||||||
|
|
||||||
export default TagVisits;
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Tag from '../tags/helpers/Tag';
|
import { Tag } from '../tags/helpers/Tag';
|
||||||
import ColorGenerator from '../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../utils/services/ColorGenerator';
|
||||||
import VisitsHeader from './VisitsHeader';
|
import { VisitsHeader } from './VisitsHeader';
|
||||||
import { TagVisits } from './reducers/tagVisits';
|
import { TagVisits } from './reducers/tagVisits';
|
||||||
import './ShortUrlVisitsHeader.scss';
|
import './ShortUrlVisitsHeader.scss';
|
||||||
|
|
||||||
@@ -10,9 +10,8 @@ interface TagVisitsHeaderProps {
|
|||||||
colorGenerator: ColorGenerator;
|
colorGenerator: ColorGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TagVisitsHeader = ({ tagVisits, goBack, colorGenerator }: TagVisitsHeaderProps) => {
|
export const TagVisitsHeader = ({ tagVisits, goBack, colorGenerator }: TagVisitsHeaderProps) => {
|
||||||
const { visits, tag } = tagVisits;
|
const { visits, tag } = tagVisits;
|
||||||
|
|
||||||
const visitsStatsTitle = (
|
const visitsStatsTitle = (
|
||||||
<span className="d-flex align-items-center justify-content-center">
|
<span className="d-flex align-items-center justify-content-center">
|
||||||
<span className="me-2">Visits for</span>
|
<span className="me-2">Visits for</span>
|
||||||
@@ -22,5 +21,3 @@ const TagVisitsHeader = ({ tagVisits, goBack, colorGenerator }: TagVisitsHeaderP
|
|||||||
|
|
||||||
return <VisitsHeader title={visitsStatsTitle} goBack={goBack} visits={visits} />;
|
return <VisitsHeader title={visitsStatsTitle} goBack={goBack} visits={visits} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TagVisitsHeader;
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Button, Card } from 'reactstrap';
|
|||||||
import { FC, PropsWithChildren, ReactNode } from 'react';
|
import { FC, PropsWithChildren, ReactNode } from 'react';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
|
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
|
||||||
import ShortUrlVisitsCount from '../short-urls/helpers/ShortUrlVisitsCount';
|
import { ShortUrlVisitsCount } from '../short-urls/helpers/ShortUrlVisitsCount';
|
||||||
import { ShortUrl } from '../short-urls/data';
|
import { ShortUrl } from '../short-urls/data';
|
||||||
import { Visit } from './types';
|
import { Visit } from './types';
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ type VisitsHeaderProps = PropsWithChildren<{
|
|||||||
shortUrl?: ShortUrl;
|
shortUrl?: ShortUrl;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const VisitsHeader: FC<VisitsHeaderProps> = ({ visits, goBack, shortUrl, children, title }) => (
|
export const VisitsHeader: FC<VisitsHeaderProps> = ({ visits, goBack, shortUrl, children, title }) => (
|
||||||
<header>
|
<header>
|
||||||
<Card body>
|
<Card body>
|
||||||
<h2 className="d-flex justify-content-between align-items-center mb-0">
|
<h2 className="d-flex justify-content-between align-items-center mb-0">
|
||||||
@@ -36,5 +36,3 @@ const VisitsHeader: FC<VisitsHeaderProps> = ({ visits, goBack, shortUrl, childre
|
|||||||
</Card>
|
</Card>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default VisitsHeader;
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { IconDefinition } from '@fortawesome/fontawesome-common-types';
|
|||||||
import { Route, Routes, Navigate } from 'react-router-dom';
|
import { Route, Routes, Navigate } from 'react-router-dom';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { DateRangeSelector } from '../utils/dates/DateRangeSelector';
|
import { DateRangeSelector } from '../utils/dates/DateRangeSelector';
|
||||||
import Message from '../utils/Message';
|
import { Message } from '../utils/Message';
|
||||||
import { DateInterval, DateRange, intervalToDateRange } from '../utils/dates/types';
|
import { DateInterval, DateRange, intervalToDateRange } from '../utils/dates/types';
|
||||||
import { Result } from '../utils/Result';
|
import { Result } from '../utils/Result';
|
||||||
import { ShlinkApiError } from '../api/ShlinkApiError';
|
import { ShlinkApiError } from '../api/ShlinkApiError';
|
||||||
@@ -17,10 +17,10 @@ import { supportsBotVisits } from '../utils/helpers/features';
|
|||||||
import { prettify } from '../utils/helpers/numbers';
|
import { prettify } from '../utils/helpers/numbers';
|
||||||
import { NavPillItem, NavPills } from '../utils/NavPills';
|
import { NavPillItem, NavPills } from '../utils/NavPills';
|
||||||
import { ExportBtn } from '../utils/ExportBtn';
|
import { ExportBtn } from '../utils/ExportBtn';
|
||||||
import LineChartCard from './charts/LineChartCard';
|
import { LineChartCard } from './charts/LineChartCard';
|
||||||
import VisitsTable from './VisitsTable';
|
import { VisitsTable } from './VisitsTable';
|
||||||
import { NormalizedOrphanVisit, NormalizedVisit, VisitsFilter, VisitsInfo, VisitsParams } from './types';
|
import { NormalizedOrphanVisit, NormalizedVisit, VisitsFilter, VisitsInfo, VisitsParams } from './types';
|
||||||
import OpenMapModalBtn from './helpers/OpenMapModalBtn';
|
import { OpenMapModalBtn } from './helpers/OpenMapModalBtn';
|
||||||
import { normalizeVisits, processStatsFromVisits } from './services/VisitsParser';
|
import { normalizeVisits, processStatsFromVisits } from './services/VisitsParser';
|
||||||
import { VisitsFilterDropdown } from './helpers/VisitsFilterDropdown';
|
import { VisitsFilterDropdown } from './helpers/VisitsFilterDropdown';
|
||||||
import { HighlightableProps, highlightedVisitsToStats } from './types/helpers';
|
import { HighlightableProps, highlightedVisitsToStats } from './types/helpers';
|
||||||
@@ -55,7 +55,7 @@ const sections: Record<Section, VisitsNavLinkProps> = {
|
|||||||
|
|
||||||
let selectedBar: string | undefined;
|
let selectedBar: string | undefined;
|
||||||
|
|
||||||
const VisitsStats: FC<VisitsStatsProps> = ({
|
export const VisitsStats: FC<VisitsStatsProps> = ({
|
||||||
children,
|
children,
|
||||||
visitsInfo,
|
visitsInfo,
|
||||||
getVisits,
|
getVisits,
|
||||||
@@ -325,5 +325,3 @@ const VisitsStats: FC<VisitsStatsProps> = ({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default VisitsStats;
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const calculateVisits = (allVisits: NormalizedVisit[], searchTerm: string | unde
|
|||||||
return { visitsGroups, total };
|
return { visitsGroups, total };
|
||||||
};
|
};
|
||||||
|
|
||||||
const VisitsTable = ({
|
export const VisitsTable = ({
|
||||||
visits,
|
visits,
|
||||||
selectedVisits = [],
|
selectedVisits = [],
|
||||||
setSelectedVisits,
|
setSelectedVisits,
|
||||||
@@ -222,5 +222,3 @@ const VisitsTable = ({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default VisitsTable;
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import { NormalizedVisit, Stats } from '../types';
|
|||||||
import { fillTheGaps } from '../../utils/helpers/visits';
|
import { fillTheGaps } from '../../utils/helpers/visits';
|
||||||
import { useToggle } from '../../utils/helpers/hooks';
|
import { useToggle } from '../../utils/helpers/hooks';
|
||||||
import { rangeOf } from '../../utils/utils';
|
import { rangeOf } from '../../utils/utils';
|
||||||
import ToggleSwitch from '../../utils/ToggleSwitch';
|
import { ToggleSwitch } from '../../utils/ToggleSwitch';
|
||||||
import { prettify } from '../../utils/helpers/numbers';
|
import { prettify } from '../../utils/helpers/numbers';
|
||||||
import { pointerOnHover, renderChartLabel } from '../../utils/helpers/charts';
|
import { pointerOnHover, renderChartLabel } from '../../utils/helpers/charts';
|
||||||
import { HIGHLIGHTED_COLOR, MAIN_COLOR } from '../../utils/theme';
|
import { HIGHLIGHTED_COLOR, MAIN_COLOR } from '../../utils/theme';
|
||||||
@@ -166,7 +166,7 @@ const chartElementAtEvent = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const LineChartCard = (
|
export const LineChartCard = (
|
||||||
{ title, visits, highlightedVisits, highlightedLabel = 'Selected', setSelectedVisits }: LineChartCardProps,
|
{ title, visits, highlightedVisits, highlightedLabel = 'Selected', setSelectedVisits }: LineChartCardProps,
|
||||||
) => {
|
) => {
|
||||||
const [step, setStep] = useState<Step>(
|
const [step, setStep] = useState<Step>(
|
||||||
@@ -235,7 +235,7 @@ const LineChartCard = (
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader role="heading">
|
||||||
{title}
|
{title}
|
||||||
<div className="float-end">
|
<div className="float-end">
|
||||||
<UncontrolledDropdown>
|
<UncontrolledDropdown>
|
||||||
@@ -266,5 +266,3 @@ const LineChartCard = (
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LineChartCard;
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Order } from '../../utils/helpers/ordering';
|
|||||||
import { SimplePaginator } from '../../common/SimplePaginator';
|
import { SimplePaginator } from '../../common/SimplePaginator';
|
||||||
import { roundTen } from '../../utils/helpers/numbers';
|
import { roundTen } from '../../utils/helpers/numbers';
|
||||||
import { OrderingDropdown } from '../../utils/OrderingDropdown';
|
import { OrderingDropdown } from '../../utils/OrderingDropdown';
|
||||||
import PaginationDropdown from '../../utils/PaginationDropdown';
|
import { PaginationDropdown } from '../../utils/PaginationDropdown';
|
||||||
import { Stats, StatsRow } from '../types';
|
import { Stats, StatsRow } from '../types';
|
||||||
import { HorizontalBarChart, HorizontalBarChartProps } from './HorizontalBarChart';
|
import { HorizontalBarChart, HorizontalBarChartProps } from './HorizontalBarChart';
|
||||||
import { ChartCard } from './ChartCard';
|
import { ChartCard } from './ChartCard';
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ const calculateMapProps = (locations: CityStats[]): MapContainerProps => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// When there's only one location, an error is thrown if trying to calculate the bounds.
|
// When there's only one location, an error is thrown if trying to calculate the bounds.
|
||||||
// When that happens, we use zoom and center as a workaround
|
// When that happens, we use "zoom" and "center" as a workaround
|
||||||
const [{ latLong: center }] = locations;
|
const [{ latLong: center }] = locations;
|
||||||
|
|
||||||
return { zoom: 10, center };
|
return { zoom: 10, center };
|
||||||
};
|
};
|
||||||
|
|
||||||
const MapModal = ({ toggle, isOpen, title, locations = [] }: MapModalProps) => (
|
export const MapModal = ({ toggle, isOpen, title, locations = [] }: MapModalProps) => (
|
||||||
<Modal toggle={toggle} isOpen={isOpen} className="map-modal__modal" contentClassName="map-modal__modal-content">
|
<Modal toggle={toggle} isOpen={isOpen} className="map-modal__modal" contentClassName="map-modal__modal-content">
|
||||||
<ModalBody className="map-modal__modal-body">
|
<ModalBody className="map-modal__modal-body">
|
||||||
<h3 className="map-modal__modal-title">
|
<h3 className="map-modal__modal-title">
|
||||||
@@ -53,5 +53,3 @@ const MapModal = ({ toggle, isOpen, title, locations = [] }: MapModalProps) => (
|
|||||||
</ModalBody>
|
</ModalBody>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default MapModal;
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { faMapMarkedAlt as mapIcon } from '@fortawesome/free-solid-svg-icons';
|
|||||||
import { Button, Dropdown, DropdownItem, DropdownMenu, UncontrolledTooltip } from 'reactstrap';
|
import { Button, Dropdown, DropdownItem, DropdownMenu, UncontrolledTooltip } from 'reactstrap';
|
||||||
import { useDomId, useToggle } from '../../utils/helpers/hooks';
|
import { useDomId, useToggle } from '../../utils/helpers/hooks';
|
||||||
import { CityStats } from '../types';
|
import { CityStats } from '../types';
|
||||||
import MapModal from './MapModal';
|
import { MapModal } from './MapModal';
|
||||||
import './OpenMapModalBtn.scss';
|
import './OpenMapModalBtn.scss';
|
||||||
|
|
||||||
interface OpenMapModalBtnProps {
|
interface OpenMapModalBtnProps {
|
||||||
@@ -13,7 +13,7 @@ interface OpenMapModalBtnProps {
|
|||||||
locations?: CityStats[];
|
locations?: CityStats[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const OpenMapModalBtn = ({ modalTitle, activeCities, locations = [] }: OpenMapModalBtnProps) => {
|
export const OpenMapModalBtn = ({ modalTitle, activeCities, locations = [] }: OpenMapModalBtnProps) => {
|
||||||
const [mapIsOpened, , openMap, closeMap] = useToggle();
|
const [mapIsOpened, , openMap, closeMap] = useToggle();
|
||||||
const [dropdownIsOpened, toggleDropdown, openDropdown] = useToggle();
|
const [dropdownIsOpened, toggleDropdown, openDropdown] = useToggle();
|
||||||
const [locationsToShow, setLocationsToShow] = useState<CityStats[]>([]);
|
const [locationsToShow, setLocationsToShow] = useState<CityStats[]>([]);
|
||||||
@@ -51,5 +51,3 @@ const OpenMapModalBtn = ({ modalTitle, activeCities, locations = [] }: OpenMapMo
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OpenMapModalBtn;
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import Bottle from 'bottlejs';
|
import Bottle from 'bottlejs';
|
||||||
import MapModal from '../helpers/MapModal';
|
import { MapModal } from '../helpers/MapModal';
|
||||||
import { createNewVisits } from '../reducers/visitCreation';
|
import { createNewVisits } from '../reducers/visitCreation';
|
||||||
import ShortUrlVisits from '../ShortUrlVisits';
|
import { ShortUrlVisits } from '../ShortUrlVisits';
|
||||||
import TagVisits from '../TagVisits';
|
import { TagVisits } from '../TagVisits';
|
||||||
import { OrphanVisits } from '../OrphanVisits';
|
import { OrphanVisits } from '../OrphanVisits';
|
||||||
import { NonOrphanVisits } from '../NonOrphanVisits';
|
import { NonOrphanVisits } from '../NonOrphanVisits';
|
||||||
import { cancelGetShortUrlVisits, getShortUrlVisits } from '../reducers/shortUrlVisits';
|
import { cancelGetShortUrlVisits, getShortUrlVisits } from '../reducers/shortUrlVisits';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { render } from '@testing-library/react';
|
|||||||
export const setUpCanvas = (element: ReactElement) => {
|
export const setUpCanvas = (element: ReactElement) => {
|
||||||
const result = render(element);
|
const result = render(element);
|
||||||
const { container } = result;
|
const { container } = result;
|
||||||
const events = container.querySelector('canvas')?.getContext('2d')?.__getEvents(); // eslint-disable-line no-underscore-dangle
|
const getEvents = () => container.querySelector('canvas')?.getContext('2d')?.__getEvents(); // eslint-disable-line no-underscore-dangle
|
||||||
|
|
||||||
return { ...result, events };
|
return { ...result, events: getEvents(), getEvents };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AxiosInstance, AxiosRequestConfig } from 'axios';
|
import { AxiosInstance, AxiosRequestConfig } from 'axios';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import ShlinkApiClient from '../../../src/api/services/ShlinkApiClient';
|
import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import { OptionalString } from '../../../src/utils/utils';
|
import { OptionalString } from '../../../src/utils/utils';
|
||||||
import { ShlinkDomain, ShlinkVisitsOverview } from '../../../src/api/types';
|
import { ShlinkDomain, ShlinkVisitsOverview } from '../../../src/api/types';
|
||||||
import { ShortUrl, ShortUrlsOrder } from '../../../src/short-urls/data';
|
import { ShortUrl, ShortUrlsOrder } from '../../../src/short-urls/data';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { AxiosInstance } from 'axios';
|
import { AxiosInstance } from 'axios';
|
||||||
import buildShlinkApiClient from '../../../src/api/services/ShlinkApiClientBuilder';
|
import { buildShlinkApiClient } from '../../../src/api/services/ShlinkApiClientBuilder';
|
||||||
import { ReachableServer, SelectedServer } from '../../../src/servers/data';
|
import { ReachableServer, SelectedServer } from '../../../src/servers/data';
|
||||||
import { ShlinkState } from '../../../src/container/types';
|
import { ShlinkState } from '../../../src/container/types';
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import asideMenuCreator from '../../src/common/AsideMenu';
|
import { AsideMenu as createAsideMenu } from '../../src/common/AsideMenu';
|
||||||
import { ReachableServer } from '../../src/servers/data';
|
import { ReachableServer } from '../../src/servers/data';
|
||||||
import { SemVer } from '../../src/utils/helpers/version';
|
import { SemVer } from '../../src/utils/helpers/version';
|
||||||
|
|
||||||
describe('<AsideMenu />', () => {
|
describe('<AsideMenu />', () => {
|
||||||
const AsideMenu = asideMenuCreator(() => <>DeleteServerButton</>);
|
const AsideMenu = createAsideMenu(() => <>DeleteServerButton</>);
|
||||||
const setUp = (version: SemVer, id: string | false = 'abc123') => render(
|
const setUp = (version: SemVer, id: string | false = 'abc123') => render(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<AsideMenu selectedServer={Mock.of<ReachableServer>({ id: id || undefined, version })} />
|
<AsideMenu selectedServer={Mock.of<ReachableServer>({ id: id || undefined, version })} />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import ShlinkVersions, { ShlinkVersionsProps } from '../../src/common/ShlinkVersions';
|
import { ShlinkVersions, ShlinkVersionsProps } from '../../src/common/ShlinkVersions';
|
||||||
import { NonReachableServer, NotFoundServer, ReachableServer } from '../../src/servers/data';
|
import { NonReachableServer, NotFoundServer, ReachableServer } from '../../src/servers/data';
|
||||||
|
|
||||||
describe('<ShlinkVersions />', () => {
|
describe('<ShlinkVersions />', () => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import ShlinkVersionsContainer from '../../src/common/ShlinkVersionsContainer';
|
import { ShlinkVersionsContainer } from '../../src/common/ShlinkVersionsContainer';
|
||||||
import { SelectedServer } from '../../src/servers/data';
|
import { SelectedServer } from '../../src/servers/data';
|
||||||
import { Sidebar } from '../../src/common/reducers/sidebar';
|
import { Sidebar } from '../../src/common/reducers/sidebar';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import ShlinkApiClient from '../../../src/api/services/ShlinkApiClient';
|
import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import {
|
import {
|
||||||
EDIT_DOMAIN_REDIRECTS,
|
EDIT_DOMAIN_REDIRECTS,
|
||||||
EDIT_DOMAIN_REDIRECTS_ERROR,
|
EDIT_DOMAIN_REDIRECTS_ERROR,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import reducer, {
|
|||||||
} from '../../../src/domains/reducers/domainsList';
|
} from '../../../src/domains/reducers/domainsList';
|
||||||
import { EDIT_DOMAIN_REDIRECTS } from '../../../src/domains/reducers/domainRedirects';
|
import { EDIT_DOMAIN_REDIRECTS } from '../../../src/domains/reducers/domainRedirects';
|
||||||
import { ShlinkDomainRedirects } from '../../../src/api/types';
|
import { ShlinkDomainRedirects } from '../../../src/api/types';
|
||||||
import ShlinkApiClient from '../../../src/api/services/ShlinkApiClient';
|
import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import { Domain } from '../../../src/domains/data';
|
import { Domain } from '../../../src/domains/data';
|
||||||
import { ShlinkState } from '../../../src/container/types';
|
import { ShlinkState } from '../../../src/container/types';
|
||||||
import { SelectedServer, ServerData } from '../../../src/servers/data';
|
import { SelectedServer, ServerData } from '../../../src/servers/data';
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import reducer, {
|
|||||||
GetMercureInfoAction,
|
GetMercureInfoAction,
|
||||||
} from '../../../src/mercure/reducers/mercureInfo';
|
} from '../../../src/mercure/reducers/mercureInfo';
|
||||||
import { ShlinkMercureInfo } from '../../../src/api/types';
|
import { ShlinkMercureInfo } from '../../../src/api/types';
|
||||||
import ShlinkApiClient from '../../../src/api/services/ShlinkApiClient';
|
import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import { GetState } from '../../../src/container/types';
|
import { GetState } from '../../../src/container/types';
|
||||||
|
|
||||||
describe('mercureInfoReducer', () => {
|
describe('mercureInfoReducer', () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import createServerConstruct from '../../src/servers/CreateServer';
|
import { CreateServer as createCreateServer } from '../../src/servers/CreateServer';
|
||||||
import { ServerForm } from '../../src/servers/helpers/ServerForm';
|
import { ServerForm } from '../../src/servers/helpers/ServerForm';
|
||||||
import { ServerWithId } from '../../src/servers/data';
|
import { ServerWithId } from '../../src/servers/data';
|
||||||
import { DuplicatedServersModal } from '../../src/servers/helpers/DuplicatedServersModal';
|
import { DuplicatedServersModal } from '../../src/servers/helpers/DuplicatedServersModal';
|
||||||
@@ -21,7 +21,7 @@ describe('<CreateServer />', () => {
|
|||||||
.mockReturnValueOnce([serversImported, () => ''])
|
.mockReturnValueOnce([serversImported, () => ''])
|
||||||
.mockReturnValueOnce([importFailed, () => ''])
|
.mockReturnValueOnce([importFailed, () => ''])
|
||||||
.mockReturnValue([]);
|
.mockReturnValue([]);
|
||||||
const CreateServer = createServerConstruct(ImportServersBtn, useStateFlagTimeout);
|
const CreateServer = createCreateServer(ImportServersBtn, useStateFlagTimeout);
|
||||||
|
|
||||||
wrapper = shallow(<CreateServer createServer={createServerMock} servers={servers} />);
|
wrapper = shallow(<CreateServer createServer={createServerMock} servers={servers} />);
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { ReactNode } from 'react';
|
|||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { render, screen, waitFor } from '@testing-library/react';
|
import { render, screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import deleteServerButtonConstruct from '../../src/servers/DeleteServerButton';
|
import { DeleteServerButton as createDeleteServerButton } from '../../src/servers/DeleteServerButton';
|
||||||
import { ServerWithId } from '../../src/servers/data';
|
import { ServerWithId } from '../../src/servers/data';
|
||||||
|
|
||||||
describe('<DeleteServerButton />', () => {
|
describe('<DeleteServerButton />', () => {
|
||||||
const DeleteServerButton = deleteServerButtonConstruct(
|
const DeleteServerButton = createDeleteServerButton(
|
||||||
({ isOpen }) => <>DeleteServerModal {isOpen ? '[Open]' : '[Closed]'}</>,
|
({ isOpen }) => <>DeleteServerModal {isOpen ? '[Open]' : '[Closed]'}</>,
|
||||||
);
|
);
|
||||||
const setUp = (children?: ReactNode) => ({
|
const setUp = (children?: ReactNode) => ({
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { shallow, ShallowWrapper } from 'enzyme';
|
|||||||
import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
|
import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import DeleteServerModal from '../../src/servers/DeleteServerModal';
|
import { DeleteServerModal } from '../../src/servers/DeleteServerModal';
|
||||||
import { ServerWithId } from '../../src/servers/data';
|
import { ServerWithId } from '../../src/servers/data';
|
||||||
|
|
||||||
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn() }));
|
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn() }));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { ListGroup } from 'reactstrap';
|
import { ListGroup } from 'reactstrap';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import ServersListGroup from '../../src/servers/ServersListGroup';
|
import { ServersListGroup } from '../../src/servers/ServersListGroup';
|
||||||
import { ServerWithId } from '../../src/servers/data';
|
import { ServerWithId } from '../../src/servers/data';
|
||||||
|
|
||||||
describe('<ServersListGroup />', () => {
|
describe('<ServersListGroup />', () => {
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ import { ReactNode } from 'react';
|
|||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { UncontrolledTooltip } from 'reactstrap';
|
import { UncontrolledTooltip } from 'reactstrap';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import importServersBtnConstruct, { ImportServersBtnProps } from '../../../src/servers/helpers/ImportServersBtn';
|
import {
|
||||||
|
ImportServersBtn as createImportServersBtn,
|
||||||
|
ImportServersBtnProps,
|
||||||
|
} from '../../../src/servers/helpers/ImportServersBtn';
|
||||||
import { ServersImporter } from '../../../src/servers/services/ServersImporter';
|
import { ServersImporter } from '../../../src/servers/services/ServersImporter';
|
||||||
import { DuplicatedServersModal } from '../../../src/servers/helpers/DuplicatedServersModal';
|
import { DuplicatedServersModal } from '../../../src/servers/helpers/DuplicatedServersModal';
|
||||||
|
|
||||||
@@ -14,7 +17,7 @@ describe('<ImportServersBtn />', () => {
|
|||||||
const serversImporterMock = Mock.of<ServersImporter>({ importServersFromFile });
|
const serversImporterMock = Mock.of<ServersImporter>({ importServersFromFile });
|
||||||
const click = jest.fn();
|
const click = jest.fn();
|
||||||
const fileRef = { current: Mock.of<HTMLInputElement>({ click }) };
|
const fileRef = { current: Mock.of<HTMLInputElement>({ click }) };
|
||||||
const ImportServersBtn = importServersBtnConstruct(serversImporterMock);
|
const ImportServersBtn = createImportServersBtn(serversImporterMock);
|
||||||
const createWrapper = (props: Partial<ImportServersBtnProps & { children: ReactNode }> = {}) => {
|
const createWrapper = (props: Partial<ImportServersBtnProps & { children: ReactNode }> = {}) => {
|
||||||
wrapper = shallow(
|
wrapper = shallow(
|
||||||
<ImportServersBtn
|
<ImportServersBtn
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import ServersExporter from '../../../src/servers/services/ServersExporter';
|
import ServersExporter from '../../../src/servers/services/ServersExporter';
|
||||||
import LocalStorage from '../../../src/utils/services/LocalStorage';
|
import { LocalStorage } from '../../../src/utils/services/LocalStorage';
|
||||||
import { appendChild, removeChild, windowMock } from '../../mocks/WindowMock';
|
import { appendChild, removeChild, windowMock } from '../../mocks/WindowMock';
|
||||||
|
|
||||||
describe('ServersExporter', () => {
|
describe('ServersExporter', () => {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import {
|
|||||||
RealTimeUpdatesSettings as RealTimeUpdatesSettingsOptions,
|
RealTimeUpdatesSettings as RealTimeUpdatesSettingsOptions,
|
||||||
Settings,
|
Settings,
|
||||||
} from '../../src/settings/reducers/settings';
|
} from '../../src/settings/reducers/settings';
|
||||||
import RealTimeUpdatesSettings from '../../src/settings/RealTimeUpdatesSettings';
|
import { RealTimeUpdatesSettings } from '../../src/settings/RealTimeUpdatesSettings';
|
||||||
import ToggleSwitch from '../../src/utils/ToggleSwitch';
|
import { ToggleSwitch } from '../../src/utils/ToggleSwitch';
|
||||||
import { LabeledFormGroup } from '../../src/utils/forms/LabeledFormGroup';
|
import { LabeledFormGroup } from '../../src/utils/forms/LabeledFormGroup';
|
||||||
|
|
||||||
describe('<RealTimeUpdatesSettings />', () => {
|
describe('<RealTimeUpdatesSettings />', () => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { Route } from 'react-router-dom';
|
import { Route } from 'react-router-dom';
|
||||||
import createSettings from '../../src/settings/Settings';
|
import { Settings as createSettings } from '../../src/settings/Settings';
|
||||||
import { NoMenuLayout } from '../../src/common/NoMenuLayout';
|
import { NoMenuLayout } from '../../src/common/NoMenuLayout';
|
||||||
import { NavPillItem } from '../../src/utils/NavPills';
|
import { NavPillItem } from '../../src/utils/NavPills';
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { faMoon, faSun } from '@fortawesome/free-solid-svg-icons';
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { Settings, UiSettings } from '../../src/settings/reducers/settings';
|
import { Settings, UiSettings } from '../../src/settings/reducers/settings';
|
||||||
import { UserInterfaceSettings } from '../../src/settings/UserInterfaceSettings';
|
import { UserInterfaceSettings } from '../../src/settings/UserInterfaceSettings';
|
||||||
import ToggleSwitch from '../../src/utils/ToggleSwitch';
|
import { ToggleSwitch } from '../../src/utils/ToggleSwitch';
|
||||||
import { Theme } from '../../src/utils/theme';
|
import { Theme } from '../../src/utils/theme';
|
||||||
|
|
||||||
describe('<UserInterfaceSettings />', () => {
|
describe('<UserInterfaceSettings />', () => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import createShortUrlsCreator from '../../src/short-urls/CreateShortUrl';
|
import { CreateShortUrl as createShortUrlsCreator } from '../../src/short-urls/CreateShortUrl';
|
||||||
import { ShortUrlCreation } from '../../src/short-urls/reducers/shortUrlCreation';
|
import { ShortUrlCreation } from '../../src/short-urls/reducers/shortUrlCreation';
|
||||||
import { Settings } from '../../src/settings/reducers/settings';
|
import { Settings } from '../../src/settings/reducers/settings';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { PaginationItem, PaginationLink } from 'reactstrap';
|
import { PaginationItem, PaginationLink } from 'reactstrap';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import Paginator from '../../src/short-urls/Paginator';
|
import { Paginator } from '../../src/short-urls/Paginator';
|
||||||
import { ShlinkPaginator } from '../../src/api/types';
|
import { ShlinkPaginator } from '../../src/api/types';
|
||||||
import { ELLIPSIS } from '../../src/utils/helpers/pagination';
|
import { ELLIPSIS } from '../../src/utils/helpers/pagination';
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { identity } from 'ramda';
|
|||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { Input } from 'reactstrap';
|
import { Input } from 'reactstrap';
|
||||||
import { ShortUrlForm as createShortUrlForm, Mode } from '../../src/short-urls/ShortUrlForm';
|
import { ShortUrlForm as createShortUrlForm, Mode } from '../../src/short-urls/ShortUrlForm';
|
||||||
import DateInput from '../../src/utils/DateInput';
|
import { DateInput } from '../../src/utils/DateInput';
|
||||||
import { ShortUrlData } from '../../src/short-urls/data';
|
import { ShortUrlData } from '../../src/short-urls/data';
|
||||||
import { ReachableServer, SelectedServer } from '../../src/servers/data';
|
import { ReachableServer, SelectedServer } from '../../src/servers/data';
|
||||||
import { SimpleCard } from '../../src/utils/SimpleCard';
|
import { SimpleCard } from '../../src/utils/SimpleCard';
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { shallow, ShallowWrapper } from 'enzyme';
|
|||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import shortUrlsListCreator from '../../src/short-urls/ShortUrlsList';
|
import { ShortUrlsList as createShortUrlsList } from '../../src/short-urls/ShortUrlsList';
|
||||||
import { ShortUrlsOrderableFields, ShortUrl, ShortUrlsOrder } from '../../src/short-urls/data';
|
import { ShortUrlsOrderableFields, ShortUrl, ShortUrlsOrder } from '../../src/short-urls/data';
|
||||||
import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import { ShortUrlsList as ShortUrlsListModel } from '../../src/short-urls/reducers/shortUrlsList';
|
import { ShortUrlsList as ShortUrlsListModel } from '../../src/short-urls/reducers/shortUrlsList';
|
||||||
import Paginator from '../../src/short-urls/Paginator';
|
import { Paginator } from '../../src/short-urls/Paginator';
|
||||||
import { ReachableServer } from '../../src/servers/data';
|
import { ReachableServer } from '../../src/servers/data';
|
||||||
import { Settings } from '../../src/settings/reducers/settings';
|
import { Settings } from '../../src/settings/reducers/settings';
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ describe('<ShortUrlsList />', () => {
|
|||||||
pagination: {},
|
pagination: {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const ShortUrlsList = shortUrlsListCreator(ShortUrlsTable, ShortUrlsFilteringBar);
|
const ShortUrlsList = createShortUrlsList(ShortUrlsTable, ShortUrlsFilteringBar);
|
||||||
const createWrapper = (defaultOrdering: ShortUrlsOrder = {}) => shallow(
|
const createWrapper = (defaultOrdering: ShortUrlsOrder = {}) => shallow(
|
||||||
<ShortUrlsList
|
<ShortUrlsList
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: { loading: true } })}
|
{...Mock.of<MercureBoundProps>({ mercureInfo: { loading: true } })}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { shallow, ShallowWrapper } from 'enzyme';
|
|||||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||||
import { Tooltip } from 'reactstrap';
|
import { Tooltip } from 'reactstrap';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import createCreateShortUrlResult from '../../../src/short-urls/helpers/CreateShortUrlResult';
|
import { CreateShortUrlResult as createResult } from '../../../src/short-urls/helpers/CreateShortUrlResult';
|
||||||
import { ShortUrl } from '../../../src/short-urls/data';
|
import { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import { StateFlagTimeout } from '../../../src/utils/helpers/hooks';
|
import { StateFlagTimeout } from '../../../src/utils/helpers/hooks';
|
||||||
import { Result } from '../../../src/utils/Result';
|
import { Result } from '../../../src/utils/Result';
|
||||||
@@ -11,7 +11,7 @@ describe('<CreateShortUrlResult />', () => {
|
|||||||
let wrapper: ShallowWrapper;
|
let wrapper: ShallowWrapper;
|
||||||
const copyToClipboard = jest.fn();
|
const copyToClipboard = jest.fn();
|
||||||
const useStateFlagTimeout = jest.fn(() => [false, copyToClipboard]) as StateFlagTimeout;
|
const useStateFlagTimeout = jest.fn(() => [false, copyToClipboard]) as StateFlagTimeout;
|
||||||
const CreateShortUrlResult = createCreateShortUrlResult(useStateFlagTimeout);
|
const CreateShortUrlResult = createResult(useStateFlagTimeout);
|
||||||
const createWrapper = (result: ShortUrl | null = null, error = false) => {
|
const createWrapper = (result: ShortUrl | null = null, error = false) => {
|
||||||
wrapper = shallow(
|
wrapper = shallow(
|
||||||
<CreateShortUrlResult resetCreateShortUrl={() => {}} result={result} error={error} saving={false} />,
|
<CreateShortUrlResult resetCreateShortUrl={() => {}} result={result} error={error} saving={false} />,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { identity } from 'ramda';
|
import { identity } from 'ramda';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import DeleteShortUrlModal from '../../../src/short-urls/helpers/DeleteShortUrlModal';
|
import { DeleteShortUrlModal } from '../../../src/short-urls/helpers/DeleteShortUrlModal';
|
||||||
import { ShortUrl } from '../../../src/short-urls/data';
|
import { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import { ShortUrlDeletion } from '../../../src/short-urls/reducers/shortUrlDeletion';
|
import { ShortUrlDeletion } from '../../../src/short-urls/reducers/shortUrlDeletion';
|
||||||
import { ProblemDetailsError } from '../../../src/api/types';
|
import { ProblemDetailsError } from '../../../src/api/types';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { shallow, ShallowWrapper } from 'enzyme';
|
|||||||
import { ExternalLink } from 'react-external-link';
|
import { ExternalLink } from 'react-external-link';
|
||||||
import { Button, FormGroup, Modal, ModalBody, ModalHeader, Row } from 'reactstrap';
|
import { Button, FormGroup, Modal, ModalBody, ModalHeader, Row } from 'reactstrap';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import createQrCodeModal from '../../../src/short-urls/helpers/QrCodeModal';
|
import { QrCodeModal as createQrCodeModal } from '../../../src/short-urls/helpers/QrCodeModal';
|
||||||
import { ShortUrl } from '../../../src/short-urls/data';
|
import { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import { ReachableServer } from '../../../src/servers/data';
|
import { ReachableServer } from '../../../src/servers/data';
|
||||||
import { CopyToClipboardIcon } from '../../../src/utils/CopyToClipboardIcon';
|
import { CopyToClipboardIcon } from '../../../src/utils/CopyToClipboardIcon';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import ShortUrlDetailLink, { LinkSuffix } from '../../../src/short-urls/helpers/ShortUrlDetailLink';
|
import { ShortUrlDetailLink, LinkSuffix } from '../../../src/short-urls/helpers/ShortUrlDetailLink';
|
||||||
import { NotFoundServer, ReachableServer } from '../../../src/servers/data';
|
import { NotFoundServer, ReachableServer } from '../../../src/servers/data';
|
||||||
import { ShortUrl } from '../../../src/short-urls/data';
|
import { ShortUrl } from '../../../src/short-urls/data';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { ShortUrlFormCheckboxGroup } from '../../../src/short-urls/helpers/ShortUrlFormCheckboxGroup';
|
import { ShortUrlFormCheckboxGroup } from '../../../src/short-urls/helpers/ShortUrlFormCheckboxGroup';
|
||||||
import Checkbox from '../../../src/utils/Checkbox';
|
import { Checkbox } from '../../../src/utils/Checkbox';
|
||||||
import { InfoTooltip } from '../../../src/utils/InfoTooltip';
|
import { InfoTooltip } from '../../../src/utils/InfoTooltip';
|
||||||
|
|
||||||
describe('<ShortUrlFormCheckboxGroup />', () => {
|
describe('<ShortUrlFormCheckboxGroup />', () => {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user