mirror of
https://github.com/umami-software/umami.git
synced 2026-02-18 11:35:37 +01:00
Merge 05cc18882c into 03adb6b7e1
This commit is contained in:
commit
e6458a383a
7 changed files with 593 additions and 307 deletions
|
|
@ -149,6 +149,21 @@ describe('Website API tests', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Updates a website with only shareId.', () => {
|
||||||
|
cy.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: `/api/websites/${websiteId}`,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: Cypress.env('authorization'),
|
||||||
|
},
|
||||||
|
body: { shareId: 'ABCDEF' },
|
||||||
|
}).then(response => {
|
||||||
|
expect(response.status).to.eq(200);
|
||||||
|
expect(response.body).to.have.property('shareId', 'ABCDEF');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Resets a website by removing all data related to the website.', () => {
|
it('Resets a website by removing all data related to the website.', () => {
|
||||||
cy.request({
|
cy.request({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ services:
|
||||||
umami:
|
umami:
|
||||||
image: ghcr.io/umami-software/umami:postgresql-latest
|
image: ghcr.io/umami-software/umami:postgresql-latest
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3001:3000"
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql://umami:umami@db:5432/umami
|
DATABASE_URL: postgresql://umami:umami@db:5432/umami
|
||||||
DATABASE_TYPE: postgresql
|
DATABASE_TYPE: postgresql
|
||||||
APP_SECRET: replace-me-with-a-random-string
|
APP_SECRET: umami-local-development-secret-key-2025
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,9 @@
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"kafkajs": "^2.1.0",
|
"kafkajs": "^2.1.0",
|
||||||
"lucide-react": "^0.543.0",
|
"maxmind": "^4.3.24",
|
||||||
"maxmind": "^5.0.0",
|
"md5": "^2.3.0",
|
||||||
"next": "15.5.3",
|
"next": "15.4.7",
|
||||||
"node-fetch": "^3.2.8",
|
"node-fetch": "^3.2.8",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"papaparse": "^5.5.3",
|
"papaparse": "^5.5.3",
|
||||||
|
|
|
||||||
811
pnpm-lock.yaml
generated
811
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -8,10 +8,40 @@ export function DashboardPage() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageBody>
|
<section style={{ marginBottom: 60 }}>
|
||||||
<Column margin="2">
|
<PageHeader title={formatMessage(labels.dashboard)}>
|
||||||
<PageHeader title={formatMessage(labels.dashboard)}></PageHeader>
|
{!editing && hasData && <DashboardSettingsButton />}
|
||||||
</Column>
|
</PageHeader>
|
||||||
</PageBody>
|
{!hasData && (
|
||||||
|
<EmptyPlaceholder message={formatMessage(messages.noWebsitesConfigured)}>
|
||||||
|
<LinkButton href={renderTeamUrl('/settings')}>
|
||||||
|
<Icon rotate={dir === 'rtl' ? 180 : 0}>
|
||||||
|
<Icons.ArrowRight />
|
||||||
|
</Icon>
|
||||||
|
<Text>{formatMessage(messages.goToSettings)}</Text>
|
||||||
|
</LinkButton>
|
||||||
|
</EmptyPlaceholder>
|
||||||
|
)}
|
||||||
|
{hasData && (
|
||||||
|
<>
|
||||||
|
{editing && <DashboardEdit teamId={teamId} />}
|
||||||
|
{!editing && (
|
||||||
|
<>
|
||||||
|
<WebsiteChartList
|
||||||
|
websites={result?.data as any}
|
||||||
|
showCharts={showCharts}
|
||||||
|
limit={pageSize}
|
||||||
|
/>
|
||||||
|
<Pager
|
||||||
|
page={Number(page) || 1}
|
||||||
|
pageSize={pageSize}
|
||||||
|
count={result?.count}
|
||||||
|
onPageChange={handlePageChange}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,18 +94,18 @@ export const DATE_FUNCTIONS = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DATE_FORMATS = {
|
const TIMEZONE_MAPPINGS: Record<string, string> = {
|
||||||
minute: 'yyyy-MM-dd HH:mm',
|
'Asia/Calcutta': 'Asia/Kolkata',
|
||||||
hour: 'yyyy-MM-dd HH',
|
|
||||||
day: 'yyyy-MM-dd',
|
|
||||||
week: "yyyy-'W'II",
|
|
||||||
month: 'yyyy-MM',
|
|
||||||
year: 'yyyy',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function normalizeTimezone(timezone: string): string {
|
||||||
|
return TIMEZONE_MAPPINGS[timezone] || timezone;
|
||||||
|
}
|
||||||
|
|
||||||
export function isValidTimezone(timezone: string) {
|
export function isValidTimezone(timezone: string) {
|
||||||
try {
|
try {
|
||||||
Intl.DateTimeFormat(undefined, { timeZone: timezone });
|
const normalizedTimezone = normalizeTimezone(timezone);
|
||||||
|
Intl.DateTimeFormat(undefined, { timeZone: normalizedTimezone });
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { isValidTimezone } from '@/lib/date';
|
import { isValidTimezone, normalizeTimezone } from '@/lib/date';
|
||||||
import { UNIT_TYPES } from './constants';
|
import { UNIT_TYPES } from './constants';
|
||||||
|
|
||||||
export const timezoneParam = z.string().refine(value => isValidTimezone(value), {
|
export const timezoneParam = z.string().refine(value => isValidTimezone(value), {
|
||||||
|
|
@ -49,9 +49,9 @@ export const pagingParams = {
|
||||||
pageSize: z.coerce.number().int().positive().optional(),
|
pageSize: z.coerce.number().int().positive().optional(),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sortingParams = {
|
export const timezoneParam = z.string().refine((value: string) => isValidTimezone(value), {
|
||||||
orderBy: z.string().optional(),
|
message: 'Invalid timezone',
|
||||||
};
|
}).transform((value: string) => normalizeTimezone(value));
|
||||||
|
|
||||||
export const userRoleParam = z.enum(['admin', 'user', 'view-only']);
|
export const userRoleParam = z.enum(['admin', 'user', 'view-only']);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue