2020-11-25 23:05:27 +03:00
|
|
|
import { Action, Dispatch } from 'redux';
|
2021-12-26 15:38:17 +03:00
|
|
|
import { ProblemDetailsError, ShlinkDomainRedirects } from '../../api/types';
|
2020-11-25 23:05:27 +03:00
|
|
|
import { buildReducer } from '../../utils/helpers/redux';
|
2020-12-22 11:55:39 +03:00
|
|
|
import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder';
|
2020-11-25 23:05:27 +03:00
|
|
|
import { GetState } from '../../container/types';
|
2021-08-21 18:53:06 +03:00
|
|
|
import { parseApiError } from '../../api/utils';
|
|
|
|
import { ApiErrorAction } from '../../api/types/actions';
|
2021-12-26 15:38:17 +03:00
|
|
|
import { Domain, DomainStatus } from '../data';
|
|
|
|
import { hasServerData } from '../../servers/data';
|
|
|
|
import { replaceAuthorityFromUri } from '../../utils/helpers/uri';
|
2021-08-21 18:53:06 +03:00
|
|
|
import { EDIT_DOMAIN_REDIRECTS, EditDomainRedirectsAction } from './domainRedirects';
|
2020-11-25 23:05:27 +03:00
|
|
|
|
|
|
|
export const LIST_DOMAINS_START = 'shlink/domainsList/LIST_DOMAINS_START';
|
|
|
|
export const LIST_DOMAINS_ERROR = 'shlink/domainsList/LIST_DOMAINS_ERROR';
|
|
|
|
export const LIST_DOMAINS = 'shlink/domainsList/LIST_DOMAINS';
|
2021-08-21 18:53:06 +03:00
|
|
|
export const FILTER_DOMAINS = 'shlink/domainsList/FILTER_DOMAINS';
|
2021-12-26 15:38:17 +03:00
|
|
|
export const VALIDATE_DOMAIN = 'shlink/domainsList/VALIDATE_DOMAIN';
|
2020-11-25 23:05:27 +03:00
|
|
|
|
|
|
|
export interface DomainsList {
|
2021-12-26 15:38:17 +03:00
|
|
|
domains: Domain[];
|
|
|
|
filteredDomains: Domain[];
|
2021-12-09 15:44:29 +03:00
|
|
|
defaultRedirects?: ShlinkDomainRedirects;
|
2020-11-25 23:05:27 +03:00
|
|
|
loading: boolean;
|
|
|
|
error: boolean;
|
2021-08-21 18:53:06 +03:00
|
|
|
errorData?: ProblemDetailsError;
|
2020-11-25 23:05:27 +03:00
|
|
|
}
|
|
|
|
|
2020-11-28 14:22:52 +03:00
|
|
|
export interface ListDomainsAction extends Action<string> {
|
2021-12-26 15:38:17 +03:00
|
|
|
domains: Domain[];
|
2021-12-09 15:44:29 +03:00
|
|
|
defaultRedirects?: ShlinkDomainRedirects;
|
2020-11-25 23:05:27 +03:00
|
|
|
}
|
|
|
|
|
2021-08-21 18:53:06 +03:00
|
|
|
interface FilterDomainsAction extends Action<string> {
|
|
|
|
searchTerm: string;
|
|
|
|
}
|
|
|
|
|
2021-12-26 15:38:17 +03:00
|
|
|
interface ValidateDomain extends Action<string> {
|
|
|
|
domain: string;
|
|
|
|
status: DomainStatus;
|
|
|
|
}
|
|
|
|
|
2020-11-25 23:05:27 +03:00
|
|
|
const initialState: DomainsList = {
|
|
|
|
domains: [],
|
2021-08-21 18:53:06 +03:00
|
|
|
filteredDomains: [],
|
2020-11-25 23:05:27 +03:00
|
|
|
loading: false,
|
|
|
|
error: false,
|
|
|
|
};
|
|
|
|
|
2021-08-22 10:00:58 +03:00
|
|
|
export type DomainsCombinedAction = ListDomainsAction
|
2021-08-21 18:53:06 +03:00
|
|
|
& ApiErrorAction
|
|
|
|
& FilterDomainsAction
|
2021-12-26 15:38:17 +03:00
|
|
|
& EditDomainRedirectsAction
|
|
|
|
& ValidateDomain;
|
2021-08-21 18:53:06 +03:00
|
|
|
|
2021-08-22 10:00:58 +03:00
|
|
|
export const replaceRedirectsOnDomain = (domain: string, redirects: ShlinkDomainRedirects) =>
|
2022-03-26 14:17:42 +03:00
|
|
|
(d: Domain): Domain => (d.domain !== domain ? d : { ...d, redirects });
|
2021-12-26 15:38:17 +03:00
|
|
|
|
|
|
|
export const replaceStatusOnDomain = (domain: string, status: DomainStatus) =>
|
2022-03-26 14:17:42 +03:00
|
|
|
(d: Domain): Domain => (d.domain !== domain ? d : { ...d, status });
|
2021-08-21 18:53:06 +03:00
|
|
|
|
|
|
|
export default buildReducer<DomainsList, DomainsCombinedAction>({
|
2020-11-25 23:05:27 +03:00
|
|
|
[LIST_DOMAINS_START]: () => ({ ...initialState, loading: true }),
|
2021-08-21 18:53:06 +03:00
|
|
|
[LIST_DOMAINS_ERROR]: ({ errorData }) => ({ ...initialState, error: true, errorData }),
|
2021-12-09 15:44:29 +03:00
|
|
|
[LIST_DOMAINS]: (_, { domains, defaultRedirects }) =>
|
|
|
|
({ ...initialState, domains, filteredDomains: domains, defaultRedirects }),
|
2021-08-21 18:53:06 +03:00
|
|
|
[FILTER_DOMAINS]: (state, { searchTerm }) => ({
|
|
|
|
...state,
|
2022-08-07 14:26:26 +03:00
|
|
|
filteredDomains: state.domains.filter(({ domain }) => domain.toLowerCase().match(searchTerm.toLowerCase())),
|
2021-08-21 18:53:06 +03:00
|
|
|
}),
|
|
|
|
[EDIT_DOMAIN_REDIRECTS]: (state, { domain, redirects }) => ({
|
|
|
|
...state,
|
|
|
|
domains: state.domains.map(replaceRedirectsOnDomain(domain, redirects)),
|
|
|
|
filteredDomains: state.filteredDomains.map(replaceRedirectsOnDomain(domain, redirects)),
|
|
|
|
}),
|
2021-12-26 15:38:17 +03:00
|
|
|
[VALIDATE_DOMAIN]: (state, { domain, status }) => ({
|
|
|
|
...state,
|
|
|
|
domains: state.domains.map(replaceStatusOnDomain(domain, status)),
|
|
|
|
filteredDomains: state.filteredDomains.map(replaceStatusOnDomain(domain, status)),
|
|
|
|
}),
|
2020-11-25 23:05:27 +03:00
|
|
|
}, initialState);
|
|
|
|
|
|
|
|
export const listDomains = (buildShlinkApiClient: ShlinkApiClientBuilder) => () => async (
|
|
|
|
dispatch: Dispatch,
|
|
|
|
getState: GetState,
|
|
|
|
) => {
|
|
|
|
dispatch({ type: LIST_DOMAINS_START });
|
2022-03-26 14:17:42 +03:00
|
|
|
const { listDomains: shlinkListDomains } = buildShlinkApiClient(getState);
|
2020-11-25 23:05:27 +03:00
|
|
|
|
|
|
|
try {
|
2022-03-26 14:17:42 +03:00
|
|
|
const resp = await shlinkListDomains().then(({ data, defaultRedirects }) => ({
|
2021-12-26 15:38:17 +03:00
|
|
|
domains: data.map((domain): Domain => ({ ...domain, status: 'validating' })),
|
|
|
|
defaultRedirects,
|
|
|
|
}));
|
2020-11-25 23:05:27 +03:00
|
|
|
|
2022-03-26 14:17:42 +03:00
|
|
|
dispatch<ListDomainsAction>({ type: LIST_DOMAINS, ...resp });
|
2021-10-31 14:38:42 +03:00
|
|
|
} catch (e: any) {
|
2021-08-21 18:53:06 +03:00
|
|
|
dispatch<ApiErrorAction>({ type: LIST_DOMAINS_ERROR, errorData: parseApiError(e) });
|
2020-11-25 23:05:27 +03:00
|
|
|
}
|
|
|
|
};
|
2021-08-21 18:53:06 +03:00
|
|
|
|
|
|
|
export const filterDomains = (searchTerm: string): FilterDomainsAction => ({ type: FILTER_DOMAINS, searchTerm });
|
2021-12-26 15:38:17 +03:00
|
|
|
|
|
|
|
export const checkDomainHealth = (buildShlinkApiClient: ShlinkApiClientBuilder) => (domain: string) => async (
|
|
|
|
dispatch: Dispatch,
|
|
|
|
getState: GetState,
|
|
|
|
) => {
|
|
|
|
const { selectedServer } = getState();
|
|
|
|
|
|
|
|
if (!hasServerData(selectedServer)) {
|
|
|
|
dispatch<ValidateDomain>({ type: VALIDATE_DOMAIN, domain, status: 'invalid' });
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { url, ...rest } = selectedServer;
|
|
|
|
const { health } = buildShlinkApiClient({
|
|
|
|
...rest,
|
|
|
|
url: replaceAuthorityFromUri(url, domain),
|
|
|
|
});
|
|
|
|
|
|
|
|
const { status } = await health();
|
|
|
|
|
|
|
|
dispatch<ValidateDomain>({ type: VALIDATE_DOMAIN, domain, status: status === 'pass' ? 'valid' : 'invalid' });
|
|
|
|
} catch (e) {
|
|
|
|
dispatch<ValidateDomain>({ type: VALIDATE_DOMAIN, domain, status: 'invalid' });
|
|
|
|
}
|
|
|
|
};
|