mirror of
https://github.com/umami-software/umami.git
synced 2026-02-08 06:37:18 +01:00
Added teams pages. Refactored hooks.
This commit is contained in:
parent
a2c202fa36
commit
9448aa3ab5
136 changed files with 387 additions and 287 deletions
20
src/components/hooks/queries/useApi.ts
Normal file
20
src/components/hooks/queries/useApi.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import * as reactQuery from '@tanstack/react-query';
|
||||
import { useApi as nextUseApi } from 'next-basics';
|
||||
import { getClientAuthToken } from 'lib/client';
|
||||
import { SHARE_TOKEN_HEADER } from 'lib/constants';
|
||||
import useStore from 'store/app';
|
||||
|
||||
const selector = (state: { shareToken: { token?: string } }) => state.shareToken;
|
||||
|
||||
export function useApi() {
|
||||
const shareToken = useStore(selector);
|
||||
|
||||
const { get, post, put, del } = nextUseApi(
|
||||
{ authorization: `Bearer ${getClientAuthToken()}`, [SHARE_TOKEN_HEADER]: shareToken?.token },
|
||||
process.env.basePath,
|
||||
);
|
||||
|
||||
return { get, post, put, del, ...reactQuery };
|
||||
}
|
||||
|
||||
export default useApi;
|
||||
28
src/components/hooks/queries/useConfig.ts
Normal file
28
src/components/hooks/queries/useConfig.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { useEffect } from 'react';
|
||||
import useStore, { setConfig } from 'store/app';
|
||||
import { useApi } from './useApi';
|
||||
|
||||
let loading = false;
|
||||
|
||||
export function useConfig() {
|
||||
const { config } = useStore();
|
||||
const { get } = useApi();
|
||||
const configUrl = process.env.configUrl;
|
||||
|
||||
async function loadConfig() {
|
||||
const data = await get(configUrl);
|
||||
loading = false;
|
||||
setConfig(data);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!config && !loading && configUrl) {
|
||||
loading = true;
|
||||
loadConfig();
|
||||
}
|
||||
}, []);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
export default useConfig;
|
||||
38
src/components/hooks/queries/useFilterQuery.ts
Normal file
38
src/components/hooks/queries/useFilterQuery.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { UseQueryOptions } from '@tanstack/react-query';
|
||||
import { useState, Dispatch, SetStateAction } from 'react';
|
||||
import { useApi } from './useApi';
|
||||
import { FilterResult, SearchFilter } from 'lib/types';
|
||||
|
||||
export interface FilterQueryResult<T> {
|
||||
result: FilterResult<T>;
|
||||
query: any;
|
||||
params: SearchFilter;
|
||||
setParams: Dispatch<SetStateAction<T | SearchFilter>>;
|
||||
}
|
||||
|
||||
export function useFilterQuery<T>({
|
||||
queryKey,
|
||||
queryFn,
|
||||
...options
|
||||
}: UseQueryOptions): FilterQueryResult<T> {
|
||||
const [params, setParams] = useState<T | SearchFilter>({
|
||||
query: '',
|
||||
page: 1,
|
||||
});
|
||||
|
||||
const { useQuery } = useApi();
|
||||
const { data, ...query } = useQuery({
|
||||
queryKey: [{ ...queryKey, ...params }],
|
||||
queryFn: () => queryFn(params as any),
|
||||
...options,
|
||||
});
|
||||
|
||||
return {
|
||||
result: data as FilterResult<any>,
|
||||
query,
|
||||
params,
|
||||
setParams,
|
||||
};
|
||||
}
|
||||
|
||||
export default useFilterQuery;
|
||||
22
src/components/hooks/queries/useLogin.ts
Normal file
22
src/components/hooks/queries/useLogin.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import useApi from './useApi';
|
||||
import useUser from './useUser';
|
||||
|
||||
export function useLogin() {
|
||||
const { get, useQuery } = useApi();
|
||||
const { user, setUser } = useUser();
|
||||
|
||||
const query = useQuery({
|
||||
queryKey: ['login'],
|
||||
queryFn: async () => {
|
||||
const data = await get('/auth/verify');
|
||||
|
||||
setUser(data);
|
||||
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
||||
return { user, ...query };
|
||||
}
|
||||
|
||||
export default useLogin;
|
||||
88
src/components/hooks/queries/useReport.ts
Normal file
88
src/components/hooks/queries/useReport.ts
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import { produce } from 'immer';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useApi } from './useApi';
|
||||
import { useTimezone } from '../useTimezone';
|
||||
import { useMessages } from '../useMessages';
|
||||
|
||||
export function useReport(reportId: string, defaultParameters: { [key: string]: any }) {
|
||||
const [report, setReport] = useState(null);
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
const { get, post } = useApi();
|
||||
const [timezone] = useTimezone();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
const baseParameters = {
|
||||
name: formatMessage(labels.untitled),
|
||||
description: '',
|
||||
parameters: {},
|
||||
};
|
||||
|
||||
const loadReport = async (id: string) => {
|
||||
const data: any = await get(`/reports/${id}`);
|
||||
|
||||
const { dateRange } = data?.parameters || {};
|
||||
const { startDate, endDate } = dateRange || {};
|
||||
|
||||
if (startDate && endDate) {
|
||||
dateRange.startDate = new Date(startDate);
|
||||
dateRange.endDate = new Date(endDate);
|
||||
}
|
||||
|
||||
setReport(data);
|
||||
};
|
||||
|
||||
const runReport = useCallback(
|
||||
async (parameters: { [key: string]: any }) => {
|
||||
setIsRunning(true);
|
||||
|
||||
const { type } = report;
|
||||
|
||||
const data = await post(`/reports/${type}`, { ...parameters, timezone });
|
||||
|
||||
setReport(
|
||||
produce((state: any) => {
|
||||
state.parameters = parameters;
|
||||
state.data = data;
|
||||
|
||||
return state;
|
||||
}),
|
||||
);
|
||||
|
||||
setIsRunning(false);
|
||||
},
|
||||
[report, timezone],
|
||||
);
|
||||
|
||||
const updateReport = useCallback(
|
||||
async (data: { [x: string]: any; parameters: any }) => {
|
||||
setReport(
|
||||
produce((state: any) => {
|
||||
const { parameters, ...rest } = data;
|
||||
|
||||
if (parameters) {
|
||||
state.parameters = { ...state.parameters, ...parameters };
|
||||
}
|
||||
|
||||
for (const key in rest) {
|
||||
state[key] = rest[key];
|
||||
}
|
||||
|
||||
return state;
|
||||
}),
|
||||
);
|
||||
},
|
||||
[report],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!reportId) {
|
||||
setReport({ ...baseParameters, ...defaultParameters });
|
||||
} else {
|
||||
loadReport(reportId);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return { report, runReport, updateReport, isRunning };
|
||||
}
|
||||
|
||||
export default useReport;
|
||||
30
src/components/hooks/queries/useReports.ts
Normal file
30
src/components/hooks/queries/useReports.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { useState } from 'react';
|
||||
import useApi from './useApi';
|
||||
import useFilterQuery from './useFilterQuery';
|
||||
|
||||
export function useReports(websiteId?: string) {
|
||||
const [modified, setModified] = useState(Date.now());
|
||||
const { get, del, useMutation } = useApi();
|
||||
const { mutate } = useMutation({ mutationFn: (reportId: string) => del(`/reports/${reportId}`) });
|
||||
const queryResult = useFilterQuery({
|
||||
queryKey: ['reports', { websiteId, modified }],
|
||||
queryFn: (params: any) => {
|
||||
return get(websiteId ? `/websites/${websiteId}/reports` : `/reports`, params);
|
||||
},
|
||||
});
|
||||
|
||||
const deleteReport = (id: any) => {
|
||||
mutate(id, {
|
||||
onSuccess: () => {
|
||||
setModified(Date.now());
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
...queryResult,
|
||||
deleteReport,
|
||||
};
|
||||
}
|
||||
|
||||
export default useReports;
|
||||
27
src/components/hooks/queries/useShareToken.ts
Normal file
27
src/components/hooks/queries/useShareToken.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import useStore, { setShareToken } from 'store/app';
|
||||
import useApi from './useApi';
|
||||
|
||||
const selector = (state: { shareToken: string }) => state.shareToken;
|
||||
|
||||
export function useShareToken(shareId: string): {
|
||||
shareToken: any;
|
||||
isLoading?: boolean;
|
||||
error?: Error;
|
||||
} {
|
||||
const shareToken = useStore(selector);
|
||||
const { get, useQuery } = useApi();
|
||||
const { isLoading, error } = useQuery({
|
||||
queryKey: ['share', shareId],
|
||||
queryFn: async () => {
|
||||
const data = await get(`/share/${shareId}`);
|
||||
|
||||
setShareToken(data);
|
||||
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
||||
return { shareToken, isLoading, error };
|
||||
}
|
||||
|
||||
export default useShareToken;
|
||||
12
src/components/hooks/queries/useTeam.ts
Normal file
12
src/components/hooks/queries/useTeam.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import useApi from './useApi';
|
||||
|
||||
export function useTeam(teamId: string) {
|
||||
const { get, useQuery } = useApi();
|
||||
return useQuery({
|
||||
queryKey: ['teams', teamId],
|
||||
queryFn: () => get(`/teams/${teamId}`),
|
||||
enabled: !!teamId,
|
||||
});
|
||||
}
|
||||
|
||||
export default useTeam;
|
||||
15
src/components/hooks/queries/useTeamWebsites.ts
Normal file
15
src/components/hooks/queries/useTeamWebsites.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import useApi from './useApi';
|
||||
import useFilterQuery from './useFilterQuery';
|
||||
|
||||
export function useTeamWebsites(teamId: string) {
|
||||
const { get } = useApi();
|
||||
|
||||
return useFilterQuery({
|
||||
queryKey: ['teams:websites', { teamId }],
|
||||
queryFn: (params: any) => {
|
||||
return get(`/teams/${teamId}/websites`, params);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export default useTeamWebsites;
|
||||
11
src/components/hooks/queries/useUser.ts
Normal file
11
src/components/hooks/queries/useUser.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import useStore, { setUser } from 'store/app';
|
||||
|
||||
const selector = (state: { user: any }) => state.user;
|
||||
|
||||
export function useUser() {
|
||||
const user = useStore(selector);
|
||||
|
||||
return { user, setUser };
|
||||
}
|
||||
|
||||
export default useUser;
|
||||
12
src/components/hooks/queries/useWebsite.ts
Normal file
12
src/components/hooks/queries/useWebsite.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import useApi from './useApi';
|
||||
|
||||
export function useWebsite(websiteId: string) {
|
||||
const { get, useQuery } = useApi();
|
||||
return useQuery({
|
||||
queryKey: ['websites', websiteId],
|
||||
queryFn: () => get(`/websites/${websiteId}`),
|
||||
enabled: !!websiteId,
|
||||
});
|
||||
}
|
||||
|
||||
export default useWebsite;
|
||||
20
src/components/hooks/queries/useWebsites.ts
Normal file
20
src/components/hooks/queries/useWebsites.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import useApi from './useApi';
|
||||
import useFilterQuery from './useFilterQuery';
|
||||
import useCache from 'store/cache';
|
||||
|
||||
export function useWebsites({ userId, teamId }: { userId?: string; teamId?: string }) {
|
||||
const { get } = useApi();
|
||||
const modified = useCache((state: any) => state?.websites);
|
||||
|
||||
return useFilterQuery({
|
||||
queryKey: ['websites', { userId, teamId, modified }],
|
||||
queryFn: (params: any) => {
|
||||
return get(teamId ? `/teams/${teamId}/websites` : '/websites', {
|
||||
...params,
|
||||
});
|
||||
},
|
||||
enabled: !!(userId || teamId),
|
||||
});
|
||||
}
|
||||
|
||||
export default useWebsites;
|
||||
Loading…
Add table
Add a link
Reference in a new issue