Updated clients.

This commit is contained in:
Mike Cao 2023-11-22 18:03:48 -08:00
parent a78d11e352
commit 4dedc57d0a
14 changed files with 66 additions and 47 deletions

View file

@ -2,11 +2,13 @@ import useApi from 'components/hooks/useApi';
import { useState } from 'react';
import { Button, Form, FormButtons, GridColumn, Loading, SubmitButton, Toggle } from 'react-basics';
import useMessages from 'components/hooks/useMessages';
import WebsitesDataTable from '../../websites/WebsitesDataTable';
import WebsitesDataTable from 'app/(main)/settings/websites/WebsitesDataTable';
import Empty from 'components/common/Empty';
import { setValue } from 'store/cache';
import { useUser } from 'components/hooks';
export function TeamWebsiteAddForm({ teamId, onSave, onClose }) {
const { user } = useUser();
const { formatMessage, labels } = useMessages();
const { get, post, useQuery, useMutation } = useApi();
const { mutate, error } = useMutation(data => post(`/teams/${teamId}/websites`, data));
@ -37,7 +39,7 @@ export function TeamWebsiteAddForm({ teamId, onSave, onClose }) {
{!isLoading && !hasData && <Empty />}
{hasData && (
<Form onSubmit={handleSubmit} error={error}>
<WebsitesDataTable showHeader={false} showActions={false}>
<WebsitesDataTable userId={user.id} showHeader={false} showActions={false}>
<GridColumn name="select" label={formatMessage(labels.selectWebsite)} alignment="end">
{row => (
<Toggle

View file

@ -0,0 +1,15 @@
'use client';
import { useUser } from 'components/hooks';
import WebsitesDataTable from './WebsitesDataTable';
import WebsitesHeader from './WebsitesHeader';
export default function Websites() {
const { user } = useUser();
return (
<>
<WebsitesHeader />
<WebsitesDataTable userId={user.id} />
</>
);
}

View file

@ -1,13 +1,13 @@
'use client';
import { ReactNode } from 'react';
import WebsitesTable from 'app/(main)/settings/websites/WebsitesTable';
import useUser from 'components/hooks/useUser';
import useApi from 'components/hooks/useApi';
import DataTable from 'components/common/DataTable';
import useFilterQuery from 'components/hooks/useFilterQuery';
import useCache from 'store/cache';
export interface WebsitesDataTableProps {
userId: string;
allowEdit?: boolean;
allowView?: boolean;
showActions?: boolean;
@ -17,25 +17,25 @@ export interface WebsitesDataTableProps {
children?: ReactNode;
}
function useWebsites({ includeTeams, onlyTeams }) {
const { user } = useUser();
function useWebsites(userId: string, { includeTeams, onlyTeams }) {
const { get } = useApi();
const modified = useCache((state: any) => state?.websites);
return useFilterQuery(
['websites', { includeTeams, onlyTeams, modified }],
(params: any) => {
return get(`/users/${user?.id}/websites`, {
return get(`/users/${userId}/websites`, {
includeTeams,
onlyTeams,
...params,
});
},
{ enabled: !!user },
{ enabled: !!userId },
);
}
export function WebsitesDataTable({
userId,
allowEdit = true,
allowView = true,
showActions = true,
@ -44,7 +44,7 @@ export function WebsitesDataTable({
onlyTeams,
children,
}: WebsitesDataTableProps) {
const queryResult = useWebsites({ includeTeams, onlyTeams });
const queryResult = useWebsites(userId, { includeTeams, onlyTeams });
return (
<DataTable queryResult={queryResult}>

View file

@ -1,14 +1,8 @@
import WebsitesDataTable from './WebsitesDataTable';
import WebsitesHeader from './WebsitesHeader';
import { Metadata } from 'next';
import Websites from './Websites';
export default function () {
return (
<>
<WebsitesHeader />
<WebsitesDataTable />
</>
);
return <Websites />;
}
export const metadata: Metadata = {

View file

@ -1,6 +1,6 @@
'use client';
import WebsitesDataTable from '../settings/websites/WebsitesDataTable';
import { useMessages } from 'components/hooks';
import { useMessages, useUser } from 'components/hooks';
import { useState } from 'react';
import { Item, Tabs } from 'react-basics';
@ -10,6 +10,7 @@ const TABS = {
};
export function WebsitesBrowse() {
const { user } = useUser();
const { formatMessage, labels } = useMessages();
const [tab, setTab] = useState(TABS.myWebsites);
const allowEdit = !process.env.cloudMode;
@ -20,9 +21,14 @@ export function WebsitesBrowse() {
<Item key={TABS.myWebsites}>{formatMessage(labels.myWebsites)}</Item>
<Item key={TABS.teamWebsites}>{formatMessage(labels.teamWebsites)}</Item>
</Tabs>
{tab === TABS.myWebsites && <WebsitesDataTable allowEdit={allowEdit} />}
{tab === TABS.myWebsites && <WebsitesDataTable userId={user.id} allowEdit={allowEdit} />}
{tab === TABS.teamWebsites && (
<WebsitesDataTable showTeam={true} onlyTeams={true} allowEdit={allowEdit} />
<WebsitesDataTable
userId={user.id}
showTeam={true}
onlyTeams={true}
allowEdit={allowEdit}
/>
)}
</>
);

View file

@ -2,7 +2,7 @@ import { useEffect } from 'react';
import useApi from 'components/hooks/useApi';
import useUser from 'components/hooks/useUser';
export function useRequireLogin(handler?: (data?: object) => void) {
export function useRequireLogin() {
const { get } = useApi();
const { user, setUser } = useUser();
@ -11,9 +11,9 @@ export function useRequireLogin(handler?: (data?: object) => void) {
try {
const data = await get('/auth/verify');
setUser(typeof handler === 'function' ? handler(data) : (data as any)?.user);
setUser(data);
} catch {
location.href = `${process.env.basePath || ''}/login`;
window.location.href = `${process.env.basePath || ''}/login`;
}
}

1
src/declaration.d.ts vendored Normal file
View file

@ -0,0 +1 @@
declare module 'debug';

View file

@ -7,14 +7,15 @@ import { createSecureToken, ensureArray, getRandomChars, parseToken } from 'next
import { findTeamWebsiteByUserId, getTeamUser, getTeamWebsite } from 'queries';
import { loadWebsite } from './load';
import { Auth } from './types';
import { NextApiRequest } from 'next';
const log = debug('umami:auth');
const cloudMode = process.env.CLOUD_MODE;
export async function setAuthKey(user, expire = 0) {
export async function setAuthKey(data: any, expire = 0) {
const authKey = `auth:${getRandomChars(32)}`;
await redis.set(authKey, user);
await redis.set(authKey, data);
if (expire) {
await redis.expire(authKey, expire);
@ -23,7 +24,7 @@ export async function setAuthKey(user, expire = 0) {
return createSecureToken({ authKey }, secret());
}
export function getAuthToken(req) {
export function getAuthToken(req: NextApiRequest) {
try {
return req.headers.authorization.split(' ')[1];
} catch {
@ -31,7 +32,7 @@ export function getAuthToken(req) {
}
}
export function parseShareToken(req) {
export function parseShareToken(req: Request) {
try {
return parseToken(req.headers[SHARE_TOKEN_HEADER], secret());
} catch (e) {

View file

@ -5,7 +5,7 @@ export function getClientAuthToken() {
return getItem(AUTH_TOKEN);
}
export function setClientAuthToken(token) {
export function setClientAuthToken(token: string) {
setItem(AUTH_TOKEN, token);
}

View file

@ -13,7 +13,7 @@ export const REPO_URL = 'https://github.com/umami-software/umami';
export const UPDATES_URL = 'https://api.umami.is/v1/updates';
export const TELEMETRY_PIXEL = 'https://i.umami.is/a.png';
export const DEFAULT_LOCALE = process.env.defaultLocale ?? 'en-US';
export const DEFAULT_LOCALE = process.env.defaultLocale || 'en-US';
export const DEFAULT_THEME = 'light';
export const DEFAULT_ANIMATION_DURATION = 300;
export const DEFAULT_DATE_RANGE = '24hour';

View file

@ -6,5 +6,5 @@ import { ok } from 'next-basics';
export default async (req: NextApiRequestAuth, res: NextApiResponse) => {
await useAuth(req, res);
return ok(res, req.auth);
return ok(res, req.auth.user);
};