Move more non-shared components to shlink-web-component

This commit is contained in:
Alejandro Celaya 2023-07-31 20:24:04 +02:00
parent bc11e568b9
commit c73a592fd1
11 changed files with 28 additions and 43 deletions

View file

@ -9,10 +9,10 @@ import { useEffect, useState } from 'react';
import { Button, FormGroup, Input, Row } from 'reactstrap'; import { Button, FormGroup, Input, Row } from 'reactstrap';
import type { InputType } from 'reactstrap/types/lib/Input'; import type { InputType } from 'reactstrap/types/lib/Input';
import { Checkbox } from '../../src/utils/Checkbox'; import { Checkbox } from '../../src/utils/Checkbox';
import { IconInput } from '../../src/utils/IconInput';
import { SimpleCard } from '../../src/utils/SimpleCard'; import { SimpleCard } from '../../src/utils/SimpleCard';
import type { DomainSelectorProps } from '../domains/DomainSelector'; import type { DomainSelectorProps } from '../domains/DomainSelector';
import type { TagsSelectorProps } from '../tags/helpers/TagsSelector'; import type { TagsSelectorProps } from '../tags/helpers/TagsSelector';
import { IconInput } from '../utils/components/IconInput';
import type { DateTimeInputProps } from '../utils/dates/DateTimeInput'; import type { DateTimeInputProps } from '../utils/dates/DateTimeInput';
import { DateTimeInput } from '../utils/dates/DateTimeInput'; import { DateTimeInput } from '../utils/dates/DateTimeInput';
import { formatIsoDate } from '../utils/dates/helpers/date'; import { formatIsoDate } from '../utils/dates/helpers/date';

View file

@ -1,5 +1,5 @@
import { isEmpty, pipe } from 'ramda'; import { isEmpty, pipe } from 'ramda';
import { useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { useLocation, useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import { orderToString, stringToOrder } from '../../../src/utils/helpers/ordering'; import { orderToString, stringToOrder } from '../../../src/utils/helpers/ordering';
import type { TagsFilteringMode } from '../../api-contract'; import type { TagsFilteringMode } from '../../api-contract';
@ -57,7 +57,7 @@ export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
), ),
[search], [search],
); );
const toFirstPageWithExtra = (extra: Partial<ShortUrlsFiltering>) => { const toFirstPageWithExtra = useCallback((extra: Partial<ShortUrlsFiltering>) => {
const merged = { ...filtering, ...extra }; const merged = { ...filtering, ...extra };
const { orderBy, tags, excludeBots, excludeMaxVisitsReached, excludePastValidUntil, ...mergedFiltering } = merged; const { orderBy, tags, excludeBots, excludeMaxVisitsReached, excludePastValidUntil, ...mergedFiltering } = merged;
const query: ShortUrlsQuery = { const query: ShortUrlsQuery = {
@ -72,7 +72,7 @@ export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
const queryString = isEmpty(stringifiedQuery) ? '' : `?${stringifiedQuery}`; const queryString = isEmpty(stringifiedQuery) ? '' : `?${stringifiedQuery}`;
navigate(`${routesPrefix}/list-short-urls/1${queryString}`); navigate(`${routesPrefix}/list-short-urls/1${queryString}`);
}; }, [filtering, navigate, routesPrefix]);
return [filtering, toFirstPageWithExtra]; return [filtering, toFirstPageWithExtra];
}; };

View file

@ -1,5 +1,5 @@
@import './mixins/vertical-align'; @import '../../../src/utils/mixins/vertical-align';
@import './base'; @import '../../../src/utils/base';
.icon-input-container { .icon-input-container {
position: relative; position: relative;

View file

@ -4,7 +4,7 @@ import classNames from 'classnames';
import type { FC } from 'react'; import type { FC } from 'react';
import type { InputProps } from 'reactstrap'; import type { InputProps } from 'reactstrap';
import { Input } from 'reactstrap'; import { Input } from 'reactstrap';
import { useElementRef } from './helpers/hooks'; import { useElementRef } from '../../../src/utils/helpers/hooks';
import './IconInput.scss'; import './IconInput.scss';
type IconInputProps = InputProps & { type IconInputProps = InputProps & {

View file

@ -1,7 +1,7 @@
import { useState } from 'react'; import { useState } from 'react';
import { DropdownItem } from 'reactstrap'; import { DropdownItem } from 'reactstrap';
import { DropdownBtn } from '../../../src/utils/DropdownBtn'; import { DropdownBtn } from '../../../src/utils/DropdownBtn';
import { useEffectExceptFirstTime } from '../../../src/utils/helpers/hooks'; import { useEffectExceptFirstTime } from '../helpers/hooks';
import { DateIntervalDropdownItems } from './DateIntervalDropdownItems'; import { DateIntervalDropdownItems } from './DateIntervalDropdownItems';
import { DateRangeRow } from './DateRangeRow'; import { DateRangeRow } from './DateRangeRow';
import type { import type {

View file

@ -1,5 +1,4 @@
import { format, formatISO, isBefore, isEqual, isWithinInterval, parse, parseISO as stdParseISO } from 'date-fns'; import { format, formatISO, isBefore, isEqual, isWithinInterval, parse, parseISO as stdParseISO } from 'date-fns';
import type { OptionalString } from '../../../../src/utils/utils';
export const STANDARD_DATE_FORMAT = 'yyyy-MM-dd'; export const STANDARD_DATE_FORMAT = 'yyyy-MM-dd';
@ -13,7 +12,7 @@ export const now = () => new Date();
export const isDateObject = (date: DateOrString): date is Date => typeof date !== 'string'; export const isDateObject = (date: DateOrString): date is Date => typeof date !== 'string';
const formatDateFromFormat = (date?: NullableDate, theFormat?: string): OptionalString => { const formatDateFromFormat = (date?: NullableDate, theFormat?: string): string | null | undefined => {
if (!date || !isDateObject(date)) { if (!date || !isDateObject(date)) {
return date; return date;
} }

View file

@ -1,6 +1,6 @@
import type { DependencyList, EffectCallback } from 'react'; import type { DependencyList, EffectCallback } from 'react';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useSwipeable as useReactSwipeable } from 'react-swipeable'; import { useSwipeable as useReactSwipeable } from 'react-swipeable';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { parseQuery, stringifyQuery } from './query'; import { parseQuery, stringifyQuery } from './query';
@ -28,13 +28,6 @@ export const useTimeoutToggle = (
return [flag, callback]; return [flag, callback];
}; };
type ToggleResult = [boolean, () => void, () => void, () => void];
export const useToggle = (initialValue = false): ToggleResult => {
const [flag, setFlag] = useState<boolean>(initialValue);
return [flag, () => setFlag(!flag), () => setFlag(true), () => setFlag(false)];
};
export const useSwipeable = (showSidebar: () => void, hideSidebar: () => void) => { export const useSwipeable = (showSidebar: () => void, hideSidebar: () => void) => {
const swipeMenuIfNoModalExists = (callback: () => void) => (e: any) => { const swipeMenuIfNoModalExists = (callback: () => void) => (e: any) => {
const swippedOnVisitsTable = (e.event.composedPath() as HTMLElement[]).some( const swippedOnVisitsTable = (e.event.composedPath() as HTMLElement[]).some(
@ -83,9 +76,11 @@ export const useGoBack = () => {
return () => navigate(-1); return () => navigate(-1);
}; };
export const useParsedQuery = <T>(): T => { type ToggleResult = [boolean, () => void, () => void, () => void];
const { search } = useLocation();
return parseQuery<T>(search); export const useToggle = (initialValue = false): ToggleResult => {
const [flag, setFlag] = useState<boolean>(initialValue);
return [flag, () => setFlag(!flag), () => setFlag(true), () => setFlag(false)];
}; };
export const useDomId = (): string => { export const useDomId = (): string => {

View file

@ -1,8 +1,9 @@
import type { PayloadAction, PrepareAction } from '@reduxjs/toolkit'; import type { PayloadAction, PrepareAction } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit';
import { mergeDeepRight } from 'ramda'; import { mergeDeepRight } from 'ramda';
import type { ShortUrlsOrder } from '../../../shlink-web-component/short-urls/data'; import type { Settings } from '../../../shlink-web-component';
import type { Settings } from '../../../shlink-web-component/utils/settings';
type ShortUrlsOrder = Exclude<Exclude<Settings['shortUrlsList'], undefined>['defaultOrdering'], undefined>;
export const DEFAULT_SHORT_URLS_ORDERING: ShortUrlsOrder = { export const DEFAULT_SHORT_URLS_ORDERING: ShortUrlsOrder = {
field: 'dateCreated', field: 'dateCreated',

View file

@ -1,5 +1,4 @@
import type { DependencyList, EffectCallback } from 'react'; import { useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { parseQuery } from '../../../shlink-web-component/utils/helpers/query'; import { parseQuery } from '../../../shlink-web-component/utils/helpers/query';
@ -27,22 +26,6 @@ export const useTimeoutToggle = (
return [flag, callback]; return [flag, callback];
}; };
type ToggleResult = [boolean, () => void, () => void, () => void];
export const useToggle = (initialValue = false): ToggleResult => {
const [flag, setFlag] = useState<boolean>(initialValue);
return [flag, () => setFlag(!flag), () => setFlag(true), () => setFlag(false)];
};
export const useEffectExceptFirstTime = (callback: EffectCallback, deps: DependencyList): void => {
const isFirstLoad = useRef(true);
useEffect(() => {
!isFirstLoad.current && callback();
isFirstLoad.current = false;
}, deps);
};
export const useGoBack = () => { export const useGoBack = () => {
const navigate = useNavigate(); const navigate = useNavigate();
return () => navigate(-1); return () => navigate(-1);
@ -53,6 +36,13 @@ export const useParsedQuery = <T>(): T => {
return parseQuery<T>(search); return parseQuery<T>(search);
}; };
type ToggleResult = [boolean, () => void, () => void, () => void];
export const useToggle = (initialValue = false): ToggleResult => {
const [flag, setFlag] = useState<boolean>(initialValue);
return [flag, () => setFlag(!flag), () => setFlag(true), () => setFlag(false)];
};
export const useDomId = (): string => { export const useDomId = (): string => {
const { current: id } = useRef(`dom-${uuid()}`); const { current: id } = useRef(`dom-${uuid()}`);
return id; return id;

View file

@ -22,7 +22,7 @@ export const determineOrderDir = <T extends string = string>(
return currentOrderDir ? newOrderMap[currentOrderDir] : 'ASC'; return currentOrderDir ? newOrderMap[currentOrderDir] : 'ASC';
}; };
export const sortList = <List>(list: List[], { field, dir }: Order<Partial<keyof List>>) => ( export const sortList = <List>(list: List[], { field, dir }: Order<keyof List>) => (
!field || !dir ? list : list.sort((a, b) => { !field || !dir ? list : list.sort((a, b) => {
const greaterThan = dir === 'ASC' ? 1 : -1; const greaterThan = dir === 'ASC' ? 1 : -1;
const smallerThan = dir === 'ASC' ? -1 : 1; const smallerThan = dir === 'ASC' ? -1 : 1;

View file

@ -1,7 +1,7 @@
import type { IconProp } from '@fortawesome/fontawesome-svg-core'; import type { IconProp } from '@fortawesome/fontawesome-svg-core';
import { faAppleAlt, faCalendar, faTable } from '@fortawesome/free-solid-svg-icons'; import { faAppleAlt, faCalendar, faTable } from '@fortawesome/free-solid-svg-icons';
import { screen } from '@testing-library/react'; import { screen } from '@testing-library/react';
import { IconInput } from '../../src/utils/IconInput'; import { IconInput } from '../../shlink-web-component/utils/components/IconInput';
import { renderWithEvents } from '../__helpers__/setUpTest'; import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<IconInput />', () => { describe('<IconInput />', () => {