feat: add umami analytics
This commit is contained in:
parent
8dab59f657
commit
8975df7437
7 changed files with 53 additions and 20 deletions
|
@ -6,6 +6,8 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<!-- <link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" /> -->
|
<!-- <link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" /> -->
|
||||||
|
<script defer src="https://umami.duskflower.dev/script.js" data-website-id="90772569-37b0-47af-9702-2ec2cfe0fe5f"
|
||||||
|
data-domains="signalstats.duskflower.dev"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
"@solidjs/router": "^0.15.3",
|
"@solidjs/router": "^0.15.3",
|
||||||
"@sqlite.org/sqlite-wasm": "3.48.0-build2",
|
"@sqlite.org/sqlite-wasm": "3.48.0-build2",
|
||||||
"@tanstack/solid-table": "^8.20.5",
|
"@tanstack/solid-table": "^8.20.5",
|
||||||
|
"@types/umami": "^2.10.0",
|
||||||
"chart.js": "^4.4.7",
|
"chart.js": "^4.4.7",
|
||||||
"chartjs-chart-wordcloud": "^4.4.4",
|
"chartjs-chart-wordcloud": "^4.4.4",
|
||||||
"chartjs-plugin-deferred": "^2.0.0",
|
"chartjs-plugin-deferred": "^2.0.0",
|
||||||
|
|
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
|
@ -41,6 +41,9 @@ importers:
|
||||||
'@tanstack/solid-table':
|
'@tanstack/solid-table':
|
||||||
specifier: ^8.20.5
|
specifier: ^8.20.5
|
||||||
version: 8.20.5(solid-js@1.9.4)
|
version: 8.20.5(solid-js@1.9.4)
|
||||||
|
'@types/umami':
|
||||||
|
specifier: ^2.10.0
|
||||||
|
version: 2.10.0
|
||||||
chart.js:
|
chart.js:
|
||||||
specifier: ^4.4.7
|
specifier: ^4.4.7
|
||||||
version: 4.4.7
|
version: 4.4.7
|
||||||
|
@ -800,6 +803,9 @@ packages:
|
||||||
'@types/node@22.10.7':
|
'@types/node@22.10.7':
|
||||||
resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==}
|
resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==}
|
||||||
|
|
||||||
|
'@types/umami@2.10.0':
|
||||||
|
resolution: {integrity: sha512-iWcs1KkcO3ooIi2rR9M5drmpQzlsT+sFiyWElIGmVwjdGlp+vQmy/VYIChYnF5ETqx7KrL80JfSkroS6dm37Hg==}
|
||||||
|
|
||||||
JSONStream@1.3.5:
|
JSONStream@1.3.5:
|
||||||
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
|
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
@ -2739,6 +2745,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.20.0
|
undici-types: 6.20.0
|
||||||
|
|
||||||
|
'@types/umami@2.10.0': {}
|
||||||
|
|
||||||
JSONStream@1.3.5:
|
JSONStream@1.3.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
jsonparse: 1.3.1
|
jsonparse: 1.3.1
|
||||||
|
|
|
@ -42,7 +42,14 @@ if (root) {
|
||||||
There is currently no backup database loaded, but you can watch statistics that have been
|
There is currently no backup database loaded, but you can watch statistics that have been
|
||||||
cached, meaning only chats you already opened or chats that were preloaded.
|
cached, meaning only chats you already opened or chats that were preloaded.
|
||||||
<br />
|
<br />
|
||||||
<A href="/overview">Watch cached statistics</A>
|
<A
|
||||||
|
href="/overview"
|
||||||
|
onClick={() => {
|
||||||
|
umami.track("Watch cached statistics");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Watch cached statistics
|
||||||
|
</A>
|
||||||
</Callout>
|
</Callout>
|
||||||
</Show>
|
</Show>
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ export const Home: Component<RouteSectionProps> = () => {
|
||||||
const [loadingProgress, setLoadingProgress] = createSignal<number>();
|
const [loadingProgress, setLoadingProgress] = createSignal<number>();
|
||||||
// const [isLoadingDatabase, setIsLoadingDatabase] = createSignal(false);
|
// const [isLoadingDatabase, setIsLoadingDatabase] = createSignal(false);
|
||||||
|
|
||||||
const onSubmit: JSX.EventHandler<HTMLFormElement, SubmitEvent> = async (event) => {
|
const onSubmit: JSX.EventHandler<HTMLFormElement, SubmitEvent> = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const currentBackupFile = backupFile();
|
const currentBackupFile = backupFile();
|
||||||
|
@ -53,22 +53,24 @@ export const Home: Component<RouteSectionProps> = () => {
|
||||||
|
|
||||||
// setDbHash(hash);
|
// setDbHash(hash);
|
||||||
|
|
||||||
try {
|
decryptBackup(currentBackupFile, currentPassphrase, setDecryptionProgress)
|
||||||
const decrypted = await decryptBackup(currentBackupFile, currentPassphrase, setDecryptionProgress);
|
.then(async (decrypted) => {
|
||||||
|
umami.track("Decrypt backup");
|
||||||
|
setDecryptionProgress(undefined);
|
||||||
|
// setIsLoadingDatabase(true);
|
||||||
|
setLoadingProgress(0);
|
||||||
|
|
||||||
setDecryptionProgress(undefined);
|
await loadDb(decrypted.database_statements, setLoadingProgress);
|
||||||
// setIsLoadingDatabase(true);
|
umami.track("Load database");
|
||||||
setLoadingProgress(0);
|
|
||||||
|
|
||||||
await loadDb(decrypted.database_statements, setLoadingProgress);
|
// setIsLoadingDatabase(false);
|
||||||
|
setLoadingProgress(undefined);
|
||||||
|
|
||||||
// setIsLoadingDatabase(false);
|
navigate("/overview");
|
||||||
setLoadingProgress(undefined);
|
})
|
||||||
|
.catch((error) => {
|
||||||
navigate("/overview");
|
console.error("Decryption failed:", error);
|
||||||
} catch (error) {
|
});
|
||||||
console.error("Decryption failed:", error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,7 @@ export const columns = [
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
umami.track("Sort overview table");
|
||||||
props.column.toggleSorting();
|
props.column.toggleSorting();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -144,6 +145,7 @@ export const columns = [
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
umami.track("Sort overview table");
|
||||||
props.column.toggleSorting();
|
props.column.toggleSorting();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -162,6 +164,7 @@ export const columns = [
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
umami.track("Sort overview table");
|
||||||
props.column.toggleSorting();
|
props.column.toggleSorting();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -269,7 +272,10 @@ export const OverviewTable = (props: OverviewTableProps) => {
|
||||||
<div class="flex items-center py-4">
|
<div class="flex items-center py-4">
|
||||||
<TextField
|
<TextField
|
||||||
value={(table.getColumn("name")?.getFilterValue() as string | undefined) ?? ""}
|
value={(table.getColumn("name")?.getFilterValue() as string | undefined) ?? ""}
|
||||||
onChange={(value) => table.getColumn("name")?.setFilterValue(value)}
|
onChange={(value) => {
|
||||||
|
umami.track("Filter overview table");
|
||||||
|
table.getColumn("name")?.setFilterValue(value);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<TextFieldInput placeholder="Filter by name..." class="max-w-sm" />
|
<TextFieldInput placeholder="Filter by name..." class="max-w-sm" />
|
||||||
</TextField>
|
</TextField>
|
||||||
|
@ -278,7 +284,10 @@ export const OverviewTable = (props: OverviewTableProps) => {
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="show-archived"
|
id="show-archived"
|
||||||
checked={(table.getColumn("archived")?.getFilterValue() as boolean | undefined) ?? false}
|
checked={(table.getColumn("archived")?.getFilterValue() as boolean | undefined) ?? false}
|
||||||
onChange={(value) => table.getColumn("archived")?.setFilterValue(value)}
|
onChange={(value) => {
|
||||||
|
umami.track("Filter overview table");
|
||||||
|
table.getColumn("archived")?.setFilterValue(value);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<div class="grid gap-1.5 leading-none">
|
<div class="grid gap-1.5 leading-none">
|
||||||
<Label for="show-archived">Show archived chats</Label>
|
<Label for="show-archived">Show archived chats</Label>
|
||||||
|
@ -288,7 +297,10 @@ export const OverviewTable = (props: OverviewTableProps) => {
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="show-groups"
|
id="show-groups"
|
||||||
checked={(table.getColumn("isGroup")?.getFilterValue() as boolean | undefined) ?? false}
|
checked={(table.getColumn("isGroup")?.getFilterValue() as boolean | undefined) ?? false}
|
||||||
onChange={(value) => table.getColumn("isGroup")?.setFilterValue(value)}
|
onChange={(value) => {
|
||||||
|
umami.track("Filter overview table");
|
||||||
|
table.getColumn("isGroup")?.setFilterValue(value);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<div class="grid gap-1.5 leading-none">
|
<div class="grid gap-1.5 leading-none">
|
||||||
<Label for="show-groups">Show group chats (detailed analysis not implemented)</Label>
|
<Label for="show-groups">Show group chats (detailed analysis not implemented)</Label>
|
||||||
|
@ -347,7 +359,7 @@ export const OverviewTable = (props: OverviewTableProps) => {
|
||||||
preload(`/${isGroup ? "group" : "dm"}/${threadId.toString()}`, {
|
preload(`/${isGroup ? "group" : "dm"}/${threadId.toString()}`, {
|
||||||
preloadData: true,
|
preloadData: true,
|
||||||
});
|
});
|
||||||
}, 20);
|
}, 50);
|
||||||
|
|
||||||
event.currentTarget.addEventListener(
|
event.currentTarget.addEventListener(
|
||||||
"pointerout",
|
"pointerout",
|
||||||
|
@ -365,6 +377,7 @@ export const OverviewTable = (props: OverviewTableProps) => {
|
||||||
const isGroup = row.original.isGroup;
|
const isGroup = row.original.isGroup;
|
||||||
|
|
||||||
if (rowIsAvailable(threadId)) {
|
if (rowIsAvailable(threadId)) {
|
||||||
|
umami.track("Load chat statistics");
|
||||||
navigate(`/${isGroup ? "group" : "dm"}/${threadId.toString()}`);
|
navigate(`/${isGroup ? "group" : "dm"}/${threadId.toString()}`);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"jsxImportSource": "solid-js",
|
"jsxImportSource": "solid-js",
|
||||||
"types": ["vite/client"],
|
"types": ["vite/client", "@types/umami"],
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue