Skip to content

Commit 893bc73

Browse files
hahn-kevmyieye
andauthored
Add troubleshooting dialog copy version button (#1927)
* Add `CopyButton` to TroubleshootDialog for copying app version and OS information. * always show troubleshooting dialog option, hide ui which is unavailable without the service --------- Co-authored-by: Tim Haasdyk <tim_haasdyk@sil.org>
1 parent ffcbdae commit 893bc73

10 files changed

Lines changed: 201 additions & 51 deletions

File tree

frontend/viewer/src/home/HomeView.svelte

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import {
99
useImportFwdataService,
1010
useProjectsService,
11-
useTroubleshootingService,
1211
} from '$lib/services/service-provider';
1312
import TroubleshootDialog from '$lib/troubleshoot/TroubleshootDialog.svelte';
1413
import ServersList from './ServersList.svelte';
@@ -109,7 +108,6 @@
109108
projectsPromise = promise;
110109
}
111110
112-
const supportsTroubleshooting = useTroubleshootingService();
113111
let troubleshootDialog = $state<TroubleshootDialog>();
114112
115113
let clickCount = 0;
@@ -165,19 +163,15 @@
165163
<ResponsiveMenu.Item onSelect={() => feedbackOpen = true} icon="i-mdi-chat-question">
166164
{$t`Feedback`}
167165
</ResponsiveMenu.Item>
168-
{#if supportsTroubleshooting}
169-
<ResponsiveMenu.Item
170-
icon="i-mdi-face-agent"
171-
onSelect={() => troubleshootDialog?.open()}>
172-
{$t`Troubleshoot`}
173-
</ResponsiveMenu.Item>
174-
{/if}
166+
<ResponsiveMenu.Item
167+
icon="i-mdi-face-agent"
168+
onSelect={() => troubleshootDialog?.open()}>
169+
{$t`Troubleshoot`}
170+
</ResponsiveMenu.Item>
175171
</ResponsiveMenu.Content>
176172
</ResponsiveMenu.Root>
177173
<FeedbackDialog bind:open={feedbackOpen}/>
178-
{#if supportsTroubleshooting}
179-
<TroubleshootDialog bind:this={troubleshootDialog}/>
180-
{/if}
174+
<TroubleshootDialog bind:this={troubleshootDialog}/>
181175
</div>
182176
{/snippet}
183177
</AppBar>
@@ -224,11 +218,9 @@
224218
{/snippet}
225219
</ResponsiveMenu.Trigger>
226220
<ResponsiveMenu.Content>
227-
{#if supportsTroubleshooting}
228-
<ResponsiveMenu.Item icon="i-mdi-bug" onSelect={() => troubleshootDialog?.open(project.code)}>
229-
{$t`Troubleshoot`}
230-
</ResponsiveMenu.Item>
231-
{/if}
221+
<ResponsiveMenu.Item icon="i-mdi-bug" onSelect={() => troubleshootDialog?.open(project.code)}>
222+
{$t`Troubleshoot`}
223+
</ResponsiveMenu.Item>
232224
<ResponsiveMenu.Item icon="i-mdi-delete" onSelect={() => void deleteProject(project)}>
233225
{$t`Delete`}
234226
</ResponsiveMenu.Item>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<script lang="ts">
2+
import {Button, type ButtonProps} from '$lib/components/ui/button';
3+
import { AppNotification } from '$lib/notifications/notifications';
4+
import { t } from 'svelte-i18n-lingui';
5+
import type {Snippet} from 'svelte';
6+
import { onDestroy } from 'svelte';
7+
import {mergeProps} from 'bits-ui';
8+
import {cn} from '$lib/utils';
9+
10+
type Props = ButtonProps & {
11+
text?: string;
12+
notify?: boolean;
13+
children?: Snippet;
14+
};
15+
16+
const { text, notify = true, children, ...rest }: Props = $props();
17+
18+
let copied = $state(false);
19+
let resetTimer: ReturnType<typeof setTimeout> | undefined;
20+
21+
async function handleClick(_event: MouseEvent) {
22+
try {
23+
if (!text) {
24+
if (notify) AppNotification.display($t`Nothing to copy`, {
25+
type: 'warning',
26+
timeout: 'min',
27+
});
28+
return;
29+
}
30+
await navigator.clipboard.writeText(text);
31+
if (notify) AppNotification.display($t`Copied to clipboard`, {
32+
type: 'success',
33+
timeout: 'min',
34+
});
35+
copied = true;
36+
clearTimeout(resetTimer);
37+
resetTimer = setTimeout(reset, 1500);
38+
} catch (error) {
39+
const detail = error instanceof Error ? error.message : String(error);
40+
if (notify) AppNotification.error($t`Failed to copy to clipboard`, detail);
41+
}
42+
}
43+
44+
function reset() {
45+
copied = false;
46+
clearTimeout(resetTimer);
47+
resetTimer = undefined;
48+
}
49+
50+
onDestroy(() => {
51+
clearTimeout(resetTimer);
52+
});
53+
</script>
54+
55+
<!--
56+
todo: once we've updated to tailwind 4 maybe wrap:
57+
https://www.shadcn-svelte-extras.com/components/copy-button
58+
-->
59+
<Button
60+
disabled={copied}
61+
onclick={handleClick}
62+
icon={copied ? 'i-mdi-check' : 'i-mdi-content-copy'}
63+
{...rest}
64+
iconProps={mergeProps({ class: cn(copied && 'text-primary') }, rest.iconProps)}
65+
>
66+
{@render children?.()}
67+
</Button>

frontend/viewer/src/lib/components/ui/button/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import Root, {
66
} from './button.svelte';
77

88
import XButton from './x-button.svelte';
9+
import CopyButton from './copy-button.svelte';
910

1011
export {
1112
Root,
1213
XButton,
14+
CopyButton,
1315
type ButtonProps,
1416
type ButtonSize,
1517
type ButtonVariant,

frontend/viewer/src/lib/troubleshoot/TroubleshootDialog.svelte

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import {QueryParamStateBool} from '$lib/utils/url.svelte';
88
import InputShell from '$lib/components/ui/input/input-shell.svelte';
99
import Label from '$lib/components/ui/label/label.svelte';
10+
import {CopyButton} from '$lib/components/ui/button';
1011
1112
const openQueryParam = new QueryParamStateBool({
1213
key: 'troubleshootDialogOpen',
@@ -42,18 +43,29 @@
4243
<DialogTitle>{$t`Troubleshoot`}</DialogTitle>
4344
</DialogHeader>
4445
<div class="flex flex-col gap-4 items-start">
45-
<p>{$t`Application version`}: <span class="font-mono text-muted-foreground border-b">{config.appVersion}</span>
46+
<p class="flex items-baseline gap-2">
47+
{$t`Application version`}:
48+
<span class="font-mono text-muted-foreground border-b">{config.appVersion}</span>
49+
<CopyButton
50+
variant="ghost"
51+
size="xs-icon"
52+
iconProps={{class: 'size-4'}}
53+
title={$t`Copy version`}
54+
text={`${config.appVersion} on ${config.os}`}
55+
/>
4656
</p>
47-
<div class="w-full">
48-
<Label>{$t`Data Directory`}</Label>
49-
<InputShell class="ps-2 pe-1">
50-
{#await service?.getDataDirectory() then value}
51-
{value}
52-
{/await}
53-
<Button variant="ghost" icon="i-mdi-folder-search" size="xs-icon" title={$t`Open Data Directory`}
54-
onclick={() => tryOpenDataDirectory()}/>
55-
</InputShell>
56-
</div>
57+
{#if service}
58+
<div class="w-full">
59+
<Label>{$t`Data Directory`}</Label>
60+
<InputShell class="ps-2 pe-1">
61+
{#await service?.getDataDirectory() then value}
62+
{value}
63+
{/await}
64+
<Button variant="ghost" icon="i-mdi-folder-search" size="xs-icon" title={$t`Open Data Directory`}
65+
onclick={() => tryOpenDataDirectory()}/>
66+
</InputShell>
67+
</div>
68+
{/if}
5769
{#if projectCode}
5870
<div class="flex gap-2">
5971
<Button variant="outline" onclick={() => shareProject()}>
@@ -62,16 +74,18 @@
6274
</Button>
6375
</div>
6476
{/if}
65-
<div class="flex gap-2">
66-
<Button variant="outline" onclick={() => service?.openLogFile()}>
67-
<i class="i-mdi-file-eye"></i>
68-
{$t`Open Log file`}
69-
</Button>
70-
<Button variant="outline" onclick={() => service?.shareLogFile()}>
71-
<i class="i-mdi-file-export"></i>
72-
{$t`Share Log file`}
73-
</Button>
74-
</div>
77+
{#if service}
78+
<div class="flex gap-2">
79+
<Button variant="outline" onclick={() => service?.openLogFile()}>
80+
<i class="i-mdi-file-eye"></i>
81+
{$t`Open Log file`}
82+
</Button>
83+
<Button variant="outline" onclick={() => service?.shareLogFile()}>
84+
<i class="i-mdi-file-export"></i>
85+
{$t`Share Log file`}
86+
</Button>
87+
</div>
88+
{/if}
7589
</div>
7690
</DialogContent>
7791
</Dialog>

frontend/viewer/src/locales/en.po

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,14 @@ msgstr "Components"
237237
msgid "Contains"
238238
msgstr "Contains"
239239

240+
#: src/lib/components/ui/button/copy-button.svelte
241+
msgid "Copied to clipboard"
242+
msgstr "Copied to clipboard"
243+
244+
#: src/lib/troubleshoot/TroubleshootDialog.svelte
245+
msgid "Copy version"
246+
msgstr "Copy version"
247+
240248
#: src/lib/entry-editor/NewEntryDialog.svelte
241249
msgid "Create {0}"
242250
msgstr "Create {0}"
@@ -395,6 +403,10 @@ msgstr "Example"
395403
msgid "Example sentence"
396404
msgstr "Example sentence"
397405

406+
#: src/lib/components/ui/button/copy-button.svelte
407+
msgid "Failed to copy to clipboard"
408+
msgstr "Failed to copy to clipboard"
409+
398410
#: src/home/Server.svelte
399411
msgid "Failed to download {0}"
400412
msgstr "Failed to download {0}"
@@ -722,6 +734,10 @@ msgstr "Not logged in"
722734
msgid "Note"
723735
msgstr "Note"
724736

737+
#: src/lib/components/ui/button/copy-button.svelte
738+
msgid "Nothing to copy"
739+
msgstr "Nothing to copy"
740+
725741
#: src/lib/admin-dialogs/GetProjectByCodeDialog.svelte
726742
msgid "Observer"
727743
msgstr "Observer"

frontend/viewer/src/locales/es.po

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,14 @@ msgstr "Componentes"
242242
msgid "Contains"
243243
msgstr "Contiene"
244244

245+
#: src/lib/components/ui/button/copy-button.svelte
246+
msgid "Copied to clipboard"
247+
msgstr ""
248+
249+
#: src/lib/troubleshoot/TroubleshootDialog.svelte
250+
msgid "Copy version"
251+
msgstr ""
252+
245253
#: src/lib/entry-editor/NewEntryDialog.svelte
246254
msgid "Create {0}"
247255
msgstr "Cree {0}"
@@ -400,6 +408,10 @@ msgstr "Ejemplo"
400408
msgid "Example sentence"
401409
msgstr "Ejemplo de frase"
402410

411+
#: src/lib/components/ui/button/copy-button.svelte
412+
msgid "Failed to copy to clipboard"
413+
msgstr ""
414+
403415
#: src/home/Server.svelte
404416
msgid "Failed to download {0}"
405417
msgstr "Error al descargar {0}"
@@ -727,6 +739,10 @@ msgstr "No conectado"
727739
msgid "Note"
728740
msgstr "Nota"
729741

742+
#: src/lib/components/ui/button/copy-button.svelte
743+
msgid "Nothing to copy"
744+
msgstr ""
745+
730746
#: src/lib/admin-dialogs/GetProjectByCodeDialog.svelte
731747
msgid "Observer"
732748
msgstr "Observador"

frontend/viewer/src/locales/fr.po

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,14 @@ msgstr "Composants"
242242
msgid "Contains"
243243
msgstr "Contient"
244244

245+
#: src/lib/components/ui/button/copy-button.svelte
246+
msgid "Copied to clipboard"
247+
msgstr ""
248+
249+
#: src/lib/troubleshoot/TroubleshootDialog.svelte
250+
msgid "Copy version"
251+
msgstr ""
252+
245253
#: src/lib/entry-editor/NewEntryDialog.svelte
246254
msgid "Create {0}"
247255
msgstr "Créer {0}"
@@ -400,6 +408,10 @@ msgstr "Exemple"
400408
msgid "Example sentence"
401409
msgstr "Exemple de phrase"
402410

411+
#: src/lib/components/ui/button/copy-button.svelte
412+
msgid "Failed to copy to clipboard"
413+
msgstr ""
414+
403415
#: src/home/Server.svelte
404416
msgid "Failed to download {0}"
405417
msgstr "Échec du téléchargement de {0}"
@@ -727,6 +739,10 @@ msgstr "Non connecté"
727739
msgid "Note"
728740
msgstr "Note"
729741

742+
#: src/lib/components/ui/button/copy-button.svelte
743+
msgid "Nothing to copy"
744+
msgstr ""
745+
730746
#: src/lib/admin-dialogs/GetProjectByCodeDialog.svelte
731747
msgid "Observer"
732748
msgstr "Observateur"

frontend/viewer/src/locales/id.po

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,14 @@ msgstr "Komponen"
242242
msgid "Contains"
243243
msgstr "Berisi"
244244

245+
#: src/lib/components/ui/button/copy-button.svelte
246+
msgid "Copied to clipboard"
247+
msgstr ""
248+
249+
#: src/lib/troubleshoot/TroubleshootDialog.svelte
250+
msgid "Copy version"
251+
msgstr ""
252+
245253
#: src/lib/entry-editor/NewEntryDialog.svelte
246254
msgid "Create {0}"
247255
msgstr "Buat {0}"
@@ -400,6 +408,10 @@ msgstr "Contoh"
400408
msgid "Example sentence"
401409
msgstr "Contoh kalimat"
402410

411+
#: src/lib/components/ui/button/copy-button.svelte
412+
msgid "Failed to copy to clipboard"
413+
msgstr ""
414+
403415
#: src/home/Server.svelte
404416
msgid "Failed to download {0}"
405417
msgstr "Gagal mengunduh {0}"
@@ -727,6 +739,10 @@ msgstr "Tidak masuk"
727739
msgid "Note"
728740
msgstr "Catatan"
729741

742+
#: src/lib/components/ui/button/copy-button.svelte
743+
msgid "Nothing to copy"
744+
msgstr ""
745+
730746
#: src/lib/admin-dialogs/GetProjectByCodeDialog.svelte
731747
msgid "Observer"
732748
msgstr "Pengamat"

0 commit comments

Comments
 (0)