mirror of
https://github.com/kremalicious/umami.git
synced 2025-02-01 12:29:35 +01:00
Updated clients.
This commit is contained in:
parent
a78d11e352
commit
4dedc57d0a
@ -4,14 +4,6 @@
|
|||||||
"es2020": true,
|
"es2020": true,
|
||||||
"node": true
|
"node": true
|
||||||
},
|
},
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"jsx": true
|
|
||||||
},
|
|
||||||
"ecmaVersion": 11,
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
"plugin:prettier/recommended",
|
"plugin:prettier/recommended",
|
||||||
@ -19,6 +11,14 @@
|
|||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
"next"
|
"next"
|
||||||
],
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"ecmaVersion": 11,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
"plugins": ["@typescript-eslint", "prettier"],
|
"plugins": ["@typescript-eslint", "prettier"],
|
||||||
"settings": {
|
"settings": {
|
||||||
"import/resolver": {
|
"import/resolver": {
|
||||||
|
@ -66,8 +66,8 @@
|
|||||||
"@prisma/client": "5.4.2",
|
"@prisma/client": "5.4.2",
|
||||||
"@react-spring/web": "^9.7.3",
|
"@react-spring/web": "^9.7.3",
|
||||||
"@tanstack/react-query": "^4.33.0",
|
"@tanstack/react-query": "^4.33.0",
|
||||||
"@umami/prisma-client": "^0.3.0",
|
"@umami/prisma-client": "^0.5.0",
|
||||||
"@umami/redis-client": "^0.16.0",
|
"@umami/redis-client": "^0.17.0",
|
||||||
"chalk": "^4.1.1",
|
"chalk": "^4.1.1",
|
||||||
"chart.js": "^4.2.1",
|
"chart.js": "^4.2.1",
|
||||||
"chartjs-adapter-date-fns": "^3.0.0",
|
"chartjs-adapter-date-fns": "^3.0.0",
|
||||||
|
@ -2,11 +2,13 @@ import useApi from 'components/hooks/useApi';
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Button, Form, FormButtons, GridColumn, Loading, SubmitButton, Toggle } from 'react-basics';
|
import { Button, Form, FormButtons, GridColumn, Loading, SubmitButton, Toggle } from 'react-basics';
|
||||||
import useMessages from 'components/hooks/useMessages';
|
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 Empty from 'components/common/Empty';
|
||||||
import { setValue } from 'store/cache';
|
import { setValue } from 'store/cache';
|
||||||
|
import { useUser } from 'components/hooks';
|
||||||
|
|
||||||
export function TeamWebsiteAddForm({ teamId, onSave, onClose }) {
|
export function TeamWebsiteAddForm({ teamId, onSave, onClose }) {
|
||||||
|
const { user } = useUser();
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
const { get, post, useQuery, useMutation } = useApi();
|
const { get, post, useQuery, useMutation } = useApi();
|
||||||
const { mutate, error } = useMutation(data => post(`/teams/${teamId}/websites`, data));
|
const { mutate, error } = useMutation(data => post(`/teams/${teamId}/websites`, data));
|
||||||
@ -37,7 +39,7 @@ export function TeamWebsiteAddForm({ teamId, onSave, onClose }) {
|
|||||||
{!isLoading && !hasData && <Empty />}
|
{!isLoading && !hasData && <Empty />}
|
||||||
{hasData && (
|
{hasData && (
|
||||||
<Form onSubmit={handleSubmit} error={error}>
|
<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">
|
<GridColumn name="select" label={formatMessage(labels.selectWebsite)} alignment="end">
|
||||||
{row => (
|
{row => (
|
||||||
<Toggle
|
<Toggle
|
||||||
|
15
src/app/(main)/settings/websites/Websites.tsx
Normal file
15
src/app/(main)/settings/websites/Websites.tsx
Normal 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} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import WebsitesTable from 'app/(main)/settings/websites/WebsitesTable';
|
import WebsitesTable from 'app/(main)/settings/websites/WebsitesTable';
|
||||||
import useUser from 'components/hooks/useUser';
|
|
||||||
import useApi from 'components/hooks/useApi';
|
import useApi from 'components/hooks/useApi';
|
||||||
import DataTable from 'components/common/DataTable';
|
import DataTable from 'components/common/DataTable';
|
||||||
import useFilterQuery from 'components/hooks/useFilterQuery';
|
import useFilterQuery from 'components/hooks/useFilterQuery';
|
||||||
import useCache from 'store/cache';
|
import useCache from 'store/cache';
|
||||||
|
|
||||||
export interface WebsitesDataTableProps {
|
export interface WebsitesDataTableProps {
|
||||||
|
userId: string;
|
||||||
allowEdit?: boolean;
|
allowEdit?: boolean;
|
||||||
allowView?: boolean;
|
allowView?: boolean;
|
||||||
showActions?: boolean;
|
showActions?: boolean;
|
||||||
@ -17,25 +17,25 @@ export interface WebsitesDataTableProps {
|
|||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function useWebsites({ includeTeams, onlyTeams }) {
|
function useWebsites(userId: string, { includeTeams, onlyTeams }) {
|
||||||
const { user } = useUser();
|
|
||||||
const { get } = useApi();
|
const { get } = useApi();
|
||||||
const modified = useCache((state: any) => state?.websites);
|
const modified = useCache((state: any) => state?.websites);
|
||||||
|
|
||||||
return useFilterQuery(
|
return useFilterQuery(
|
||||||
['websites', { includeTeams, onlyTeams, modified }],
|
['websites', { includeTeams, onlyTeams, modified }],
|
||||||
(params: any) => {
|
(params: any) => {
|
||||||
return get(`/users/${user?.id}/websites`, {
|
return get(`/users/${userId}/websites`, {
|
||||||
includeTeams,
|
includeTeams,
|
||||||
onlyTeams,
|
onlyTeams,
|
||||||
...params,
|
...params,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ enabled: !!user },
|
{ enabled: !!userId },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function WebsitesDataTable({
|
export function WebsitesDataTable({
|
||||||
|
userId,
|
||||||
allowEdit = true,
|
allowEdit = true,
|
||||||
allowView = true,
|
allowView = true,
|
||||||
showActions = true,
|
showActions = true,
|
||||||
@ -44,7 +44,7 @@ export function WebsitesDataTable({
|
|||||||
onlyTeams,
|
onlyTeams,
|
||||||
children,
|
children,
|
||||||
}: WebsitesDataTableProps) {
|
}: WebsitesDataTableProps) {
|
||||||
const queryResult = useWebsites({ includeTeams, onlyTeams });
|
const queryResult = useWebsites(userId, { includeTeams, onlyTeams });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataTable queryResult={queryResult}>
|
<DataTable queryResult={queryResult}>
|
||||||
|
@ -1,14 +1,8 @@
|
|||||||
import WebsitesDataTable from './WebsitesDataTable';
|
|
||||||
import WebsitesHeader from './WebsitesHeader';
|
|
||||||
import { Metadata } from 'next';
|
import { Metadata } from 'next';
|
||||||
|
import Websites from './Websites';
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
return (
|
return <Websites />;
|
||||||
<>
|
|
||||||
<WebsitesHeader />
|
|
||||||
<WebsitesDataTable />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import WebsitesDataTable from '../settings/websites/WebsitesDataTable';
|
import WebsitesDataTable from '../settings/websites/WebsitesDataTable';
|
||||||
import { useMessages } from 'components/hooks';
|
import { useMessages, useUser } from 'components/hooks';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Item, Tabs } from 'react-basics';
|
import { Item, Tabs } from 'react-basics';
|
||||||
|
|
||||||
@ -10,6 +10,7 @@ const TABS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function WebsitesBrowse() {
|
export function WebsitesBrowse() {
|
||||||
|
const { user } = useUser();
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
const [tab, setTab] = useState(TABS.myWebsites);
|
const [tab, setTab] = useState(TABS.myWebsites);
|
||||||
const allowEdit = !process.env.cloudMode;
|
const allowEdit = !process.env.cloudMode;
|
||||||
@ -20,9 +21,14 @@ export function WebsitesBrowse() {
|
|||||||
<Item key={TABS.myWebsites}>{formatMessage(labels.myWebsites)}</Item>
|
<Item key={TABS.myWebsites}>{formatMessage(labels.myWebsites)}</Item>
|
||||||
<Item key={TABS.teamWebsites}>{formatMessage(labels.teamWebsites)}</Item>
|
<Item key={TABS.teamWebsites}>{formatMessage(labels.teamWebsites)}</Item>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
{tab === TABS.myWebsites && <WebsitesDataTable allowEdit={allowEdit} />}
|
{tab === TABS.myWebsites && <WebsitesDataTable userId={user.id} allowEdit={allowEdit} />}
|
||||||
{tab === TABS.teamWebsites && (
|
{tab === TABS.teamWebsites && (
|
||||||
<WebsitesDataTable showTeam={true} onlyTeams={true} allowEdit={allowEdit} />
|
<WebsitesDataTable
|
||||||
|
userId={user.id}
|
||||||
|
showTeam={true}
|
||||||
|
onlyTeams={true}
|
||||||
|
allowEdit={allowEdit}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@ import { useEffect } from 'react';
|
|||||||
import useApi from 'components/hooks/useApi';
|
import useApi from 'components/hooks/useApi';
|
||||||
import useUser from 'components/hooks/useUser';
|
import useUser from 'components/hooks/useUser';
|
||||||
|
|
||||||
export function useRequireLogin(handler?: (data?: object) => void) {
|
export function useRequireLogin() {
|
||||||
const { get } = useApi();
|
const { get } = useApi();
|
||||||
const { user, setUser } = useUser();
|
const { user, setUser } = useUser();
|
||||||
|
|
||||||
@ -11,9 +11,9 @@ export function useRequireLogin(handler?: (data?: object) => void) {
|
|||||||
try {
|
try {
|
||||||
const data = await get('/auth/verify');
|
const data = await get('/auth/verify');
|
||||||
|
|
||||||
setUser(typeof handler === 'function' ? handler(data) : (data as any)?.user);
|
setUser(data);
|
||||||
} catch {
|
} catch {
|
||||||
location.href = `${process.env.basePath || ''}/login`;
|
window.location.href = `${process.env.basePath || ''}/login`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
src/declaration.d.ts
vendored
Normal file
1
src/declaration.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
declare module 'debug';
|
@ -7,14 +7,15 @@ import { createSecureToken, ensureArray, getRandomChars, parseToken } from 'next
|
|||||||
import { findTeamWebsiteByUserId, getTeamUser, getTeamWebsite } from 'queries';
|
import { findTeamWebsiteByUserId, getTeamUser, getTeamWebsite } from 'queries';
|
||||||
import { loadWebsite } from './load';
|
import { loadWebsite } from './load';
|
||||||
import { Auth } from './types';
|
import { Auth } from './types';
|
||||||
|
import { NextApiRequest } from 'next';
|
||||||
|
|
||||||
const log = debug('umami:auth');
|
const log = debug('umami:auth');
|
||||||
const cloudMode = process.env.CLOUD_MODE;
|
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)}`;
|
const authKey = `auth:${getRandomChars(32)}`;
|
||||||
|
|
||||||
await redis.set(authKey, user);
|
await redis.set(authKey, data);
|
||||||
|
|
||||||
if (expire) {
|
if (expire) {
|
||||||
await redis.expire(authKey, expire);
|
await redis.expire(authKey, expire);
|
||||||
@ -23,7 +24,7 @@ export async function setAuthKey(user, expire = 0) {
|
|||||||
return createSecureToken({ authKey }, secret());
|
return createSecureToken({ authKey }, secret());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAuthToken(req) {
|
export function getAuthToken(req: NextApiRequest) {
|
||||||
try {
|
try {
|
||||||
return req.headers.authorization.split(' ')[1];
|
return req.headers.authorization.split(' ')[1];
|
||||||
} catch {
|
} catch {
|
||||||
@ -31,7 +32,7 @@ export function getAuthToken(req) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseShareToken(req) {
|
export function parseShareToken(req: Request) {
|
||||||
try {
|
try {
|
||||||
return parseToken(req.headers[SHARE_TOKEN_HEADER], secret());
|
return parseToken(req.headers[SHARE_TOKEN_HEADER], secret());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -5,7 +5,7 @@ export function getClientAuthToken() {
|
|||||||
return getItem(AUTH_TOKEN);
|
return getItem(AUTH_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setClientAuthToken(token) {
|
export function setClientAuthToken(token: string) {
|
||||||
setItem(AUTH_TOKEN, token);
|
setItem(AUTH_TOKEN, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 UPDATES_URL = 'https://api.umami.is/v1/updates';
|
||||||
export const TELEMETRY_PIXEL = 'https://i.umami.is/a.png';
|
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_THEME = 'light';
|
||||||
export const DEFAULT_ANIMATION_DURATION = 300;
|
export const DEFAULT_ANIMATION_DURATION = 300;
|
||||||
export const DEFAULT_DATE_RANGE = '24hour';
|
export const DEFAULT_DATE_RANGE = '24hour';
|
||||||
|
@ -6,5 +6,5 @@ import { ok } from 'next-basics';
|
|||||||
export default async (req: NextApiRequestAuth, res: NextApiResponse) => {
|
export default async (req: NextApiRequestAuth, res: NextApiResponse) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
|
|
||||||
return ok(res, req.auth);
|
return ok(res, req.auth.user);
|
||||||
};
|
};
|
||||||
|
16
yarn.lock
16
yarn.lock
@ -2596,18 +2596,18 @@
|
|||||||
"@typescript-eslint/types" "6.8.0"
|
"@typescript-eslint/types" "6.8.0"
|
||||||
eslint-visitor-keys "^3.4.1"
|
eslint-visitor-keys "^3.4.1"
|
||||||
|
|
||||||
"@umami/prisma-client@^0.3.0":
|
"@umami/prisma-client@^0.5.0":
|
||||||
version "0.3.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@umami/prisma-client/-/prisma-client-0.3.0.tgz#fea35a44c76af0e4ce58288107cda3ee76fc80ba"
|
resolved "https://registry.yarnpkg.com/@umami/prisma-client/-/prisma-client-0.5.0.tgz#e2287debbf21f9344c989b9e7192491df88513bf"
|
||||||
integrity sha512-88y/WJX2TEZaUfP+PTretGUL6YdwZCBbhaoeC87eTF3l1aG0Lv3TsmW0lJy5rbKpVqrFJ8zrtvCMP/vt7WeIjg==
|
integrity sha512-BkStMrvxYZQPwEIyy30JJPucTTsmQqb4jD8+ciSHxcBc7039cW0XyX3TL/u9ebZmANzIuNO0XiBArwjWulGIjg==
|
||||||
dependencies:
|
dependencies:
|
||||||
chalk "^4.1.2"
|
chalk "^4.1.2"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
|
|
||||||
"@umami/redis-client@^0.16.0":
|
"@umami/redis-client@^0.17.0":
|
||||||
version "0.16.0"
|
version "0.17.0"
|
||||||
resolved "https://registry.yarnpkg.com/@umami/redis-client/-/redis-client-0.16.0.tgz#0050d1f93338d88691c983f3c0cd4a62da20212b"
|
resolved "https://registry.yarnpkg.com/@umami/redis-client/-/redis-client-0.17.0.tgz#a24db0cb561a9c18b0ecaf6a3342c28525abe1e5"
|
||||||
integrity sha512-fE08lkMvhXbkXSdSRpG0R/9a3xIiTvwD6f+hKERFZrpfvJJlH3Uf4Jod8Ahg/+TmD03ihSQPooUT3T9Ig3dfaQ==
|
integrity sha512-rX0xB+QkhMoHnKcj8jzbp1CUMKB/qk2HaYWpNP0Stztkvw7wjFYXsLTLidW3t1a06H5qApx6mJvUjxefLUsX7w==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
redis "^4.5.1"
|
redis "^4.5.1"
|
||||||
|
Loading…
Reference in New Issue
Block a user