Skip to content

Commit

Permalink
Merge branch 'dev' into analytics
Browse files Browse the repository at this point in the history
  • Loading branch information
mikecao committed Nov 30, 2023
2 parents 047aad1 + 5acc1f0 commit 3e8d50d
Show file tree
Hide file tree
Showing 79 changed files with 571 additions and 417 deletions.
14 changes: 7 additions & 7 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
"es2020": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:import/recommended",
"plugin:@typescript-eslint/recommended",
"next"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
Expand All @@ -12,13 +19,6 @@
"ecmaVersion": 11,
"sourceType": "module"
},
"extends": [
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:import/recommended",
"plugin:@typescript-eslint/recommended",
"next"
],
"plugins": ["@typescript-eslint", "prettier"],
"settings": {
"import/resolver": {
Expand Down
50 changes: 34 additions & 16 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@ require('dotenv').config();
const path = require('path');
const pkg = require('./package.json');

const contentSecurityPolicy = `
default-src 'self';
img-src *;
script-src 'self' 'unsafe-eval' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
connect-src 'self' api.umami.is;
frame-ancestors 'self' ${process.env.ALLOWED_FRAME_URLS};
`;
const contentSecurityPolicy = [
`default-src 'self'`,
`img-src *`,
`script-src 'self' 'unsafe-eval' 'unsafe-inline'`,
`style-src 'self' 'unsafe-inline'`,
`connect-src 'self' api.umami.is`,
];

const cspHeader = (values = []) => ({
key: 'Content-Security-Policy',
value: values
.join(';')
.replace(/\s{2,}/g, ' ')
.trim(),
});

const headers = [
{
Expand All @@ -21,10 +28,18 @@ const headers = [
key: 'X-Frame-Options',
value: 'SAMEORIGIN',
},
cspHeader(contentSecurityPolicy),
];

const shareHeaders = [
{
key: 'Content-Security-Policy',
value: contentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(),
key: 'X-DNS-Prefetch-Control',
value: 'on',
},
cspHeader([
...contentSecurityPolicy,
`frame-ancestors 'self' ${process.env.ALLOWED_FRAME_URLS || ''}`,
]),
];

if (process.env.FORCE_SSL) {
Expand Down Expand Up @@ -81,14 +96,13 @@ const config = {
reactStrictMode: false,
env: {
basePath: basePath || '',
cloudMode: !!process.env.CLOUD_MODE,
cloudUrl: process.env.CLOUD_URL,
cloudMode: process.env.CLOUD_MODE || '',
cloudUrl: process.env.CLOUD_URL || '',
configUrl: '/config',
currentVersion: pkg.version,
defaultLocale: process.env.DEFAULT_LOCALE,
disableLogin: process.env.DISABLE_LOGIN,
disableUI: process.env.DISABLE_UI,
isProduction: process.env.NODE_ENV === 'production',
defaultLocale: process.env.DEFAULT_LOCALE || '',
disableLogin: process.env.DISABLE_LOGIN || '',
disableUI: process.env.DISABLE_UI || '',
},
basePath,
output: 'standalone',
Expand Down Expand Up @@ -127,6 +141,10 @@ const config = {
source: '/:path*',
headers,
},
{
source: '/share/:path*',
headers: shareHeaders,
},
];
},
async rewrites() {
Expand Down
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,11 @@
"@clickhouse/client": "^0.2.2",
"@fontsource/inter": "^4.5.15",
"@prisma/client": "5.4.2",
"@prisma/extension-read-replicas": "^0.3.0",
"@react-spring/web": "^9.7.3",
"@tanstack/react-query": "^4.33.0",
"@umami/prisma-client": "^0.3.0",
"@umami/redis-client": "^0.16.0",
"@umami/prisma-client": "^0.5.0",
"@umami/redis-client": "^0.18.0",
"chalk": "^4.1.1",
"chart.js": "^4.2.1",
"chartjs-adapter-date-fns": "^3.0.0",
Expand Down Expand Up @@ -98,11 +99,11 @@
"npm-run-all": "^4.1.5",
"prisma": "5.4.2",
"react": "^18.2.0",
"react-basics": "^0.105.0",
"react-basics": "^0.107.0",
"react-beautiful-dnd": "^13.1.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.4",
"react-intl": "^6.4.7",
"react-intl": "^6.5.5",
"react-simple-maps": "^2.3.0",
"react-use-measure": "^2.0.4",
"react-window": "^1.8.6",
Expand All @@ -125,9 +126,9 @@
"@rollup/plugin-replace": "^5.0.2",
"@svgr/rollup": "^8.1.0",
"@svgr/webpack": "^8.1.0",
"@types/node": "^18.11.9",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.8",
"@types/node": "^20.9.0",
"@types/react": "^18.2.37",
"@types/react-dom": "^18.2.15",
"@typescript-eslint/eslint-plugin": "^6.7.3",
"@typescript-eslint/parser": "^6.7.3",
"cross-env": "^7.0.3",
Expand Down
19 changes: 14 additions & 5 deletions src/app/(main)/Shell.tsx → src/app/(main)/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
'use client';
import { Loading } from 'react-basics';
import Script from 'next/script';
import { usePathname } from 'next/navigation';
import UpdateNotice from 'components/common/UpdateNotice';
import { useRequireLogin, useConfig } from 'components/hooks';
import { useLogin, useConfig } from 'components/hooks';
import UpdateNotice from './UpdateNotice';

export function Shell({ children }) {
const { user } = useRequireLogin();
export function App({ children }) {
const { user, isLoading, error } = useLogin();
const config = useConfig();
const pathname = usePathname();

if (isLoading) {
return <Loading />;
}

if (error) {
window.location.href = `${process.env.basePath || ''}/login`;
}

if (!user || !config) {
return null;
}
Expand All @@ -24,4 +33,4 @@ export function Shell({ children }) {
);
}

export default Shell;
export default App;
37 changes: 36 additions & 1 deletion src/app/(main)/NavBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import styles from './NavBar.module.css';
export function NavBar() {
const pathname = usePathname();
const { formatMessage, labels } = useMessages();
const cloudMode = Boolean(process.env.cloudMode);

const links = [
{ label: formatMessage(labels.dashboard), url: '/dashboard' },
Expand All @@ -22,6 +23,40 @@ export function NavBar() {
{ label: formatMessage(labels.settings), url: '/settings' },
].filter(n => n);

const menuItems = [
{
label: formatMessage(labels.dashboard),
url: '/dashboard',
},
!cloudMode && {
label: formatMessage(labels.settings),
url: '/settings',
children: [
{
label: formatMessage(labels.websites),
url: '/settings/websites',
},
{
label: formatMessage(labels.teams),
url: '/settings/teams',
},
{
label: formatMessage(labels.users),
url: '/settings/users',
},
{
label: formatMessage(labels.profile),
url: '/settings/profile',
},
],
},
cloudMode && {
label: formatMessage(labels.profile),
url: '/settings/profile',
},
!cloudMode && { label: formatMessage(labels.logout), url: '/logout' },
].filter(n => n);

return (
<div className={styles.navbar}>
<div className={styles.logo}>
Expand Down Expand Up @@ -49,7 +84,7 @@ export function NavBar() {
<ProfileButton />
</div>
<div className={styles.mobile}>
<HamburgerButton />
<HamburgerButton menuItems={menuItems} />
</div>
</div>
);
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/app/(main)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Dashboard from 'app/(main)/dashboard/Dashboard';
import { Metadata } from 'next';

export default function DashboardPage() {
export default function () {
return <Dashboard />;
}

Expand Down
8 changes: 4 additions & 4 deletions src/app/(main)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Shell from './Shell';
import App from './App';
import NavBar from './NavBar';
import Page from 'components/layout/Page';
import styles from './layout.module.css';

export default function AppLayout({ children }) {
export default function ({ children }) {
return (
<Shell>
<App>
<main className={styles.layout}>
<nav className={styles.nav}>
<NavBar />
Expand All @@ -14,6 +14,6 @@ export default function AppLayout({ children }) {
<Page>{children}</Page>
</section>
</main>
</Shell>
</App>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import useFilterQuery from 'components/hooks/useFilterQuery';
import DataTable from 'components/common/DataTable';
import useCache from 'store/cache';

export default function ReportsDataTable({ websiteId }) {
export default function ReportsDataTable({ websiteId }: { websiteId?: string }) {
const { get } = useApi();
const modified = useCache(state => state?.reports);
const modified = useCache(state => (state as any)?.reports);
const queryResult = useFilterQuery(['reports', { websiteId, modified }], params =>
get(websiteId ? `/websites/${websiteId}/reports` : `/reports`, params),
);
Expand Down
2 changes: 1 addition & 1 deletion src/app/(main)/reports/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ReportsHeader from './ReportsHeader';
import ReportsDataTable from './ReportsDataTable';

export default function ReportsPage() {
export default function () {
return (
<>
<ReportsHeader />
Expand Down
6 changes: 4 additions & 2 deletions src/app/(main)/settings/teams/[id]/TeamWebsiteAddForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ import useApi from 'components/hooks/useApi';
import { DOMAIN_REGEX } from 'lib/constants';
import useMessages from 'components/hooks/useMessages';

export function WebsiteAddForm({ onSave, onClose }) {
export function WebsiteAddForm({ onSave, onClose }: { onSave?: () => void; onClose?: () => void }) {
const { formatMessage, labels, messages } = useMessages();
const { post, useMutation } = useApi();
const { mutate, error, isLoading } = useMutation(data => post('/websites', data));

const handleSubmit = async data => {
const handleSubmit = async (data: any) => {
mutate(data, {
onSuccess: async () => {
onSave();
onClose();
onSave?.();
onClose?.();
},
});
};

return (
<Form onSubmit={handleSubmit} error={error}>
<Form onSubmit={handleSubmit} error={error as string}>
<FormRow label={formatMessage(labels.name)}>
<FormInput name="name" rules={{ required: formatMessage(labels.required) }}>
<TextField autoComplete="off" />
Expand All @@ -47,9 +47,11 @@ export function WebsiteAddForm({ onSave, onClose }) {
<SubmitButton variant="primary" disabled={false}>
{formatMessage(labels.save)}
</SubmitButton>
<Button disabled={isLoading} onClick={onClose}>
{formatMessage(labels.cancel)}
</Button>
{onClose && (
<Button disabled={isLoading} onClick={onClose}>
{formatMessage(labels.cancel)}
</Button>
)}
</FormButtons>
</Form>
);
Expand Down
15 changes: 15 additions & 0 deletions src/app/(main)/settings/websites/Websites.tsx
Original file line number Diff line number Diff line change
@@ -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} />
</>
);
}
Loading

2 comments on commit 3e8d50d

@vercel
Copy link

@vercel vercel bot commented on 3e8d50d Nov 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 3e8d50d Nov 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.