mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-03-13 11:03:50 +00:00
Created section to display orphan visits stats
This commit is contained in:
69
src/visits/reducers/orphanVisits.ts
Normal file
69
src/visits/reducers/orphanVisits.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Action, Dispatch } from 'redux';
|
||||
import { Visit, VisitsInfo, VisitsLoadFailedAction, VisitsLoadProgressChangedAction } from '../types';
|
||||
import { buildActionCreator, buildReducer } from '../../utils/helpers/redux';
|
||||
import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder';
|
||||
import { GetState } from '../../container/types';
|
||||
import { getVisitsWithLoader } from './common';
|
||||
import { CREATE_VISITS, CreateVisitsAction } from './visitCreation';
|
||||
|
||||
/* eslint-disable padding-line-between-statements */
|
||||
export const GET_ORPHAN_VISITS_START = 'shlink/orphanVisits/GET_ORPHAN_VISITS_START';
|
||||
export const GET_ORPHAN_VISITS_ERROR = 'shlink/orphanVisits/GET_ORPHAN_VISITS_ERROR';
|
||||
export const GET_ORPHAN_VISITS = 'shlink/orphanVisits/GET_ORPHAN_VISITS';
|
||||
export const GET_ORPHAN_VISITS_LARGE = 'shlink/orphanVisits/GET_ORPHAN_VISITS_LARGE';
|
||||
export const GET_ORPHAN_VISITS_CANCEL = 'shlink/orphanVisits/GET_ORPHAN_VISITS_CANCEL';
|
||||
export const GET_ORPHAN_VISITS_PROGRESS_CHANGED = 'shlink/orphanVisits/GET_ORPHAN_VISITS_PROGRESS_CHANGED';
|
||||
/* eslint-enable padding-line-between-statements */
|
||||
|
||||
export interface OrphanVisitsAction extends Action<string> {
|
||||
visits: Visit[];
|
||||
}
|
||||
|
||||
type OrphanVisitsCombinedAction = OrphanVisitsAction
|
||||
& VisitsLoadProgressChangedAction
|
||||
& CreateVisitsAction
|
||||
& VisitsLoadFailedAction;
|
||||
|
||||
const initialState: VisitsInfo = {
|
||||
visits: [],
|
||||
loading: false,
|
||||
loadingLarge: false,
|
||||
error: false,
|
||||
cancelLoad: false,
|
||||
progress: 0,
|
||||
};
|
||||
|
||||
export default buildReducer<VisitsInfo, OrphanVisitsCombinedAction>({
|
||||
[GET_ORPHAN_VISITS_START]: () => ({ ...initialState, loading: true }),
|
||||
[GET_ORPHAN_VISITS_ERROR]: (_, { errorData }) => ({ ...initialState, error: true, errorData }),
|
||||
[GET_ORPHAN_VISITS]: (_, { visits }) => ({ ...initialState, visits }),
|
||||
[GET_ORPHAN_VISITS_LARGE]: (state) => ({ ...state, loadingLarge: true }),
|
||||
[GET_ORPHAN_VISITS_CANCEL]: (state) => ({ ...state, cancelLoad: true }),
|
||||
[GET_ORPHAN_VISITS_PROGRESS_CHANGED]: (state, { progress }) => ({ ...state, progress }),
|
||||
[CREATE_VISITS]: (state, { createdVisits }) => {
|
||||
const { visits } = state;
|
||||
const newVisits = createdVisits.map(({ visit }) => visit);
|
||||
|
||||
return { ...state, visits: [ ...visits, ...newVisits ] };
|
||||
},
|
||||
}, initialState);
|
||||
|
||||
export const getOrphanVisits = (buildShlinkApiClient: ShlinkApiClientBuilder) => (query = {}) => async (
|
||||
dispatch: Dispatch,
|
||||
getState: GetState,
|
||||
) => {
|
||||
const { getOrphanVisits } = buildShlinkApiClient(getState);
|
||||
const visitsLoader = async (page: number, itemsPerPage: number) => getOrphanVisits({ ...query, page, itemsPerPage });
|
||||
const shouldCancel = () => getState().orphanVisits.cancelLoad;
|
||||
const actionMap = {
|
||||
start: GET_ORPHAN_VISITS_START,
|
||||
large: GET_ORPHAN_VISITS_LARGE,
|
||||
finish: GET_ORPHAN_VISITS,
|
||||
error: GET_ORPHAN_VISITS_ERROR,
|
||||
progress: GET_ORPHAN_VISITS_PROGRESS_CHANGED,
|
||||
};
|
||||
|
||||
return getVisitsWithLoader(visitsLoader, {}, actionMap, dispatch, shouldCancel);
|
||||
};
|
||||
|
||||
export const cancelGetOrphanVisits = buildActionCreator(GET_ORPHAN_VISITS_CANCEL);
|
||||
@@ -52,11 +52,10 @@ export default buildReducer<ShortUrlVisits, ShortUrlVisitsCombinedAction>({
|
||||
[GET_SHORT_URL_VISITS_LARGE]: (state) => ({ ...state, loadingLarge: true }),
|
||||
[GET_SHORT_URL_VISITS_CANCEL]: (state) => ({ ...state, cancelLoad: true }),
|
||||
[GET_SHORT_URL_VISITS_PROGRESS_CHANGED]: (state, { progress }) => ({ ...state, progress }),
|
||||
[CREATE_VISITS]: (state, { createdVisits }) => { // eslint-disable-line object-shorthand
|
||||
[CREATE_VISITS]: (state, { createdVisits }) => {
|
||||
const { shortCode, domain, visits } = state;
|
||||
|
||||
const newVisits = createdVisits
|
||||
.filter(({ shortUrl }) => shortUrlMatches(shortUrl, shortCode, domain))
|
||||
.filter(({ shortUrl }) => shortUrl && shortUrlMatches(shortUrl, shortCode, domain))
|
||||
.map(({ visit }) => visit);
|
||||
|
||||
return { ...state, visits: [ ...visits, ...newVisits ] };
|
||||
|
||||
@@ -46,10 +46,10 @@ export default buildReducer<TagVisits, TagsVisitsCombinedAction>({
|
||||
[GET_TAG_VISITS_LARGE]: (state) => ({ ...state, loadingLarge: true }),
|
||||
[GET_TAG_VISITS_CANCEL]: (state) => ({ ...state, cancelLoad: true }),
|
||||
[GET_TAG_VISITS_PROGRESS_CHANGED]: (state, { progress }) => ({ ...state, progress }),
|
||||
[CREATE_VISITS]: (state, { createdVisits }) => { // eslint-disable-line object-shorthand
|
||||
[CREATE_VISITS]: (state, { createdVisits }) => {
|
||||
const { tag, visits } = state;
|
||||
const newVisits = createdVisits
|
||||
.filter(({ shortUrl }) => shortUrl.tags.includes(tag))
|
||||
.filter(({ shortUrl }) => shortUrl?.tags.includes(tag))
|
||||
.map(({ visit }) => visit);
|
||||
|
||||
return { ...state, visits: [ ...visits, ...newVisits ] };
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ShlinkVisitsOverview } from '../../api/types';
|
||||
import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder';
|
||||
import { GetState } from '../../container/types';
|
||||
import { buildReducer } from '../../utils/helpers/redux';
|
||||
import { groupNewVisitsByType } from '../types/helpers';
|
||||
import { CREATE_VISITS, CreateVisitsAction } from './visitCreation';
|
||||
|
||||
/* eslint-disable padding-line-between-statements */
|
||||
@@ -31,10 +32,15 @@ export default buildReducer<VisitsOverview, GetVisitsOverviewAction & CreateVisi
|
||||
[GET_OVERVIEW_START]: () => ({ ...initialState, loading: true }),
|
||||
[GET_OVERVIEW_ERROR]: () => ({ ...initialState, error: true }),
|
||||
[GET_OVERVIEW]: (_, { visitsCount, orphanVisitsCount }) => ({ ...initialState, visitsCount, orphanVisitsCount }),
|
||||
[CREATE_VISITS]: ({ visitsCount, ...rest }, { createdVisits }) => ({
|
||||
...rest,
|
||||
visitsCount: visitsCount + createdVisits.length,
|
||||
}),
|
||||
[CREATE_VISITS]: ({ visitsCount, orphanVisitsCount = 0, ...rest }, { createdVisits }) => {
|
||||
const { regularVisits, orphanVisits } = groupNewVisitsByType(createdVisits);
|
||||
|
||||
return {
|
||||
...rest,
|
||||
visitsCount: visitsCount + regularVisits.length,
|
||||
orphanVisitsCount: orphanVisitsCount + orphanVisits.length,
|
||||
};
|
||||
},
|
||||
}, initialState);
|
||||
|
||||
export const loadVisitsOverview = (buildShlinkApiClient: ShlinkApiClientBuilder) => () => async (
|
||||
|
||||
Reference in New Issue
Block a user