Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent duplicte click events #1522

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 23 additions & 17 deletions frontend/viewer/src/home/HomeView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
useImportFwdataService,
useProjectsService, useTroubleshootingService
} from '$lib/services/service-provider';
import AnchorListItem from '$lib/utils/AnchorListItem.svelte';
import ButtonListItem from '$lib/utils/ButtonListItem.svelte';
import TroubleshootDialog from '$lib/troubleshoot/TroubleshootDialog.svelte';
import ServersList from './ServersList.svelte';

Expand Down Expand Up @@ -147,41 +147,47 @@
<div>
{#each projects.filter(p => p.crdt) as project, i (project.id ?? i)}
{@const server = project.server}
<AnchorListItem href={`/project/${project.name}`}>
{@const loading = deletingProject === project.name}
<ButtonListItem href={`/project/${project.name}`}>
<ListItem title={project.name}
icon={mdiBookEditOutline}
subheading={!server ? 'Local only' : ('Synced with ' + server.displayName)}
loading={deletingProject === project.name}>
{loading}>
<div slot="actions">
{#if $isDev}
<Button icon={mdiDelete} title="Delete" class="p-2" on:click={(e) => {
<Button icon={mdiDelete} title="Delete" class="p-2" disabled={loading} on:click={(e) => {
e.preventDefault();
void deleteProject(project.name);
}} />
{/if}
<Button icon={mdiChevronRight} class="p-2 pointer-events-none"/>
</div>
</ListItem>
</AnchorListItem>
</ButtonListItem>
{/each}
<DevContent>
<AnchorListItem href={`/testing/project-view`}>
<ButtonListItem href={`/testing/project-view`}>
<ListItem title="Test Project" icon={mdiTestTube}>
<div slot="actions" class="pointer-events-none">
<Button icon={mdiChevronRight} class="p-2"/>
</div>
</ListItem>
</AnchorListItem>
</ButtonListItem>
</DevContent>
{#if !projects.some(p => p.name === exampleProjectName) || $isDev}
<ListItem title="Create Example Project" on:click={() => createExampleProject()} loading={createProjectLoading}>
<div slot="actions" class="flex flex-nowrap gap-2">
{#if $isDev}
<TextField bind:value={customExampleProjectName} placeholder="Project name..." on:click={(e) => e.stopPropagation()} />
{/if}
<Button icon={mdiBookPlusOutline} class="pointer-events-none p-2"/>
</div>
</ListItem>
<ButtonListItem on:click={() => createExampleProject()} disabled={createProjectLoading}>
<ListItem
title="Create Example Project"
loading={createProjectLoading}
>
<div slot="actions" class="flex flex-nowrap gap-2">
{#if $isDev}
<TextField bind:value={customExampleProjectName} placeholder="Project name..." on:click={(e) => e.stopPropagation()} />
{/if}
<Button icon={mdiBookPlusOutline} class="pointer-events-none p-2"/>
</div>
</ListItem>
</ButtonListItem>
{/if}
</div>
</div>
Expand All @@ -191,7 +197,7 @@
<p class="sub-title">Classic FieldWorks Projects</p>
<div>
{#each projects.filter(p => p.fwdata) as project (project.id ?? project.name)}
<AnchorListItem href={`/fwdata/${project.name}`}>
<ButtonListItem href={`/fwdata/${project.name}`}>
<ListItem title={project.name}>
<img slot="avatar" src={flexLogo} alt="FieldWorks logo" class="h-6"/>
<div slot="actions">
Expand All @@ -210,7 +216,7 @@
</DevContent>
</div>
</ListItem>
</AnchorListItem>
</ButtonListItem>
{/each}
</div>
</div>
Expand Down
34 changes: 21 additions & 13 deletions frontend/viewer/src/home/Server.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import {mdiBookArrowDownOutline, mdiBookSyncOutline, mdiCloud, mdiRefresh} from '@mdi/js';
import LoginButton from '$lib/auth/LoginButton.svelte';
import {Button, ListItem, Settings} from 'svelte-ux';
import AnchorListItem from '$lib/utils/AnchorListItem.svelte';
import ButtonListItem from '$lib/utils/ButtonListItem.svelte';
import {useProjectsService} from '$lib/services/service-provider';

const projectsService = useProjectsService();
Expand All @@ -23,11 +23,17 @@

async function downloadCrdtProject(project: Project, server: ILexboxServer | undefined) {
if (!server) throw new Error('Server is undefined');
else if (matchesProject(localProjects, project)) return;

downloading = project.name;
if (project.id == null) throw new Error('Project id is null');
try {
await projectsService.downloadProject(project.id, project.name, server);
dispatch('refreshAll');
localProjects.push({ // the refresh will take a moment
...project,
server,
});
} finally {
downloading = '';
}
Expand Down Expand Up @@ -83,7 +89,7 @@
{#each projects as project}
{@const localProject = matchesProject(localProjects, project)}
{#if localProject?.crdt}
<AnchorListItem href={`/project/${project.name}`}>
<ButtonListItem href={`/project/${project.name}`}>
<ListItem icon={mdiCloud}
title={project.name}
loading={downloading === project.name}>
Expand All @@ -93,18 +99,20 @@
</Button>
</div>
</ListItem>
</AnchorListItem>
</ButtonListItem>
{:else}
<ListItem icon={mdiCloud}
title={project.name}
on:click={() => void downloadCrdtProject(project, server)}
loading={downloading === project.name}>
<div slot="actions" class="pointer-events-none">
<Button icon={mdiBookArrowDownOutline} class="p-2">
Download
</Button>
</div>
</ListItem>
{@const loading = downloading === project.name}
<ButtonListItem on:click={() => downloadCrdtProject(project, server)} disabled={loading}>
<ListItem icon={mdiCloud}
title={project.name}
{loading}>
<div slot="actions" class="pointer-events-none">
<Button icon={mdiBookArrowDownOutline} class="p-2">
Download
</Button>
</div>
</ListItem>
</ButtonListItem>
{/if}
{/each}
{/if}
Expand Down
26 changes: 26 additions & 0 deletions frontend/viewer/src/lib/sandbox/Sandbox.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import OverrideFields from '$lib/OverrideFields.svelte';
import type {FieldIds} from '$lib/entry-editor/field-data';
import {dndzone} from 'svelte-dnd-action';
import {delay} from '$lib/utils/time';
import ButtonListItem from '$lib/utils/ButtonListItem.svelte';


const crdtOptions: MenuOption[] = [
Expand Down Expand Up @@ -48,6 +50,14 @@
function updateFields(e: CustomEvent<{ items: ({ id: FieldIds })[] }>) {
senseFields = e.detail.items;
}
let count = 0;
let loading = false;
async function incrementAsync() {
loading = true;
await delay(1000);
count++;
loading = false;
}
</script>


Expand Down Expand Up @@ -88,6 +98,22 @@
</Button>
</div>
</div>
<div class="flex flex-col gap-2 border p-4 justify-between">
<div class="flex flex-col gap-2">
Button
<Button variant="fill" disabled={loading} {loading} on:click={incrementAsync}>
Increment Async
</Button>
click count: {count}
</div>
<div class="flex flex-col gap-2">
ButtonListItem
<ButtonListItem disabled={loading} on:click={incrementAsync}>
Increment Async
</ButtonListItem>
click count: {count}
</div>
</div>
<div class="border grid" style="grid-template-columns: auto 1fr">
<div class="col-span-2">
<h3>Override Fields</h3>
Expand Down
10 changes: 9 additions & 1 deletion frontend/viewer/src/lib/services/service-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
import type {ITestingService} from '$lib/dotnet-types/generated-types/FwLiteShared/Services/ITestingService';
import type {IMultiWindowService} from '$lib/dotnet-types/generated-types/FwLiteShared/Services/IMultiWindowService';
import type {IJsEventListener} from '$lib/dotnet-types/generated-types/FwLiteShared/Events/IJsEventListener';
import type {IFwEvent} from '$lib/dotnet-types/generated-types/FwLiteShared/Events/IFwEvent';

export type ServiceKey = keyof LexboxServiceRegistry;
export type LexboxServiceRegistry = {
Expand All @@ -37,7 +38,14 @@ export type LexboxServiceRegistry = {
export const SERVICE_KEYS = Object.values(DotnetService);

export class LexboxServiceProvider {
private services: LexboxServiceRegistry = {} as LexboxServiceRegistry;
private services: LexboxServiceRegistry = {
[DotnetService.JsEventListener]: {
nextEventAsync(): Promise<IFwEvent> {
console.warn('using default JsEvent listener which does nothing');
return new Promise<IFwEvent>(() => {});
}
}
} as LexboxServiceRegistry;

public setService<K extends ServiceKey>(key: K, service: LexboxServiceRegistry[K]): void {
this.validateServiceKey(key);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
<script lang="ts">
export let href: string;
export let href: string | undefined = undefined;
</script>

<a {href} class="anchor-list-item">
<svelte:element
this={href ? 'a' : 'button'}
on:click
{href}
{...$$restProps}
class="button-list-item w-full text-start"
role="button"
tabindex="0">
<div></div> <!-- avoid internal first: styles -->
<slot />
<div></div> <!-- avoid internal last: styles -->
</a>
</svelte:element>

<style lang="postcss">
.anchor-list-item {
.button-list-item {
&:first-child :global(.ListItem) {
@apply border-t-0 rounded-t;
}
Expand Down
Loading