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

confirm deleting fwlite entries #1337

Merged
merged 8 commits into from
Jan 6, 2025
Merged
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
3 changes: 3 additions & 0 deletions backend/FwLite/FwLiteShared/Pages/TestingProject.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@page "/testing/project-view"
@using FwLiteShared.Layout
@layout SvelteLayout;
4 changes: 2 additions & 2 deletions backend/FwLite/FwLiteWeb/Components/App.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<base href="/"/>
<link rel="icon" type="image/png" href="_content/FwLiteShared/favicon.png"/>
<HeadOutlet @rendermode="InteractiveServer"/>
<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)"/>
<script>
window.invokeOnWindow = function (methodName, args) {
if (!(methodName in window)) {
Expand All @@ -20,7 +20,7 @@
</head>

<body>
<Routes @rendermode="InteractiveServer"/>
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)"/>
<script src="_framework/blazor.web.js"></script>
</body>

Expand Down
2 changes: 1 addition & 1 deletion backend/FwLite/FwLiteWeb/FwLiteWebServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static WebApplication SetupAppServer(WebApplicationOptions options, Actio
config.LexboxServers = [new(new("https://staging.languagedepot.org"), "Lexbox Staging")]);
builder.Services.Configure<AuthConfig>(c => c.ClientId = "becf2856-0690-434b-b192-a4032b72067f");
builder.Logging.AddDebug();
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
builder.Services.AddRazorComponents().AddInteractiveServerComponents(circuitOptions => circuitOptions.DetailedErrors = true);
if (builder.Configuration.GetValue<string>("FwLiteWeb:LogFileName") is { Length: > 0 } logFileName)
{
builder.Logging.AddFile(logFileName);
Expand Down
7 changes: 7 additions & 0 deletions frontend/viewer/src/ProjectView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import {initProjectCommands, type NewEntryDialogOptions} from './lib/commands';
import throttle from 'just-throttle';
import {SortField} from '$lib/dotnet-types/generated-types/MiniLcm/SortField';
import DeleteDialog from '$lib/entry-editor/DeleteDialog.svelte';
import {initDialogService} from '$lib/entry-editor/dialog-service';

export let loading = false;
export let about: string | undefined = undefined;
Expand Down Expand Up @@ -268,6 +270,10 @@
if (entry) onEntryCreated(entry, options);
return entry;
}
let deleteDialog: DeleteDialog;
$: dialogHolder.dialog = deleteDialog;
const dialogHolder: {dialog?: DeleteDialog} = {};
initDialogService(() => dialogHolder.dialog);

initProjectCommands({
createNewEntry: openNewEntryDialog,
Expand Down Expand Up @@ -427,3 +433,4 @@
<ViewOptionsDrawer bind:open={showOptionsDialog} bind:activeView={$currentView} bind:viewSettings={$viewSettings} bind:features={$features} />
</div>
{/if}
<DeleteDialog bind:this={deleteDialog} />
43 changes: 43 additions & 0 deletions frontend/viewer/src/lib/entry-editor/DeleteDialog.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script lang="ts">
import {Button, Dialog} from 'svelte-ux';
import {mdiTrashCanOutline} from '@mdi/js';
let subject: string;
let open = false;
let loading = false;
let requester: {
resolve: (result: boolean) => void
} | undefined = undefined;

function confirm() {
resolve(true);
}

function cancel() {
resolve(false);
}

function resolve(shouldDelete: boolean) {
requester?.resolve(shouldDelete);
requester = undefined;
open = false;
}

export function prompt(promptSubject: string): Promise<boolean> {
if (requester) throw new Error('already prompting for a delete');
return new Promise((resolve) => {
requester = { resolve };
subject = promptSubject;
open = true;
});
}
</script>
<Dialog {open} on:close={cancel} {loading} persistent={loading} style="height: auto">
<div slot="title">Delete {subject}</div>
<div class="m-6">
<p>Are you sure you want to delete {subject}?</p>
</div>
<div slot="actions">
<Button on:click={() => cancel()}>Don't delete</Button>
<Button variant="fill-light" color="danger" icon={mdiTrashCanOutline} on:click={_ => confirm()}>Delete {subject}</Button>
</div>
</Dialog>
28 changes: 28 additions & 0 deletions frontend/viewer/src/lib/entry-editor/dialog-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type DeleteDialog from '$lib/entry-editor/DeleteDialog.svelte';
import {getContext, setContext} from 'svelte';

export function initDialogService(rootDialog: () => DeleteDialog | undefined): DialogService {
const dialogService = new DialogService(rootDialog);
setContext('DialogService', dialogService);
return dialogService;
}

export function useDialogService(): DialogService {
const rootDialog = getContext('DialogService');
if (!rootDialog) {
throw new Error('DialogService not found');
}
return rootDialog as DialogService;
}

export class DialogService {

constructor(private deleteDialog: () => DeleteDialog | undefined) {
}

promptDelete(subject: string): Promise<boolean> {
const deleteDialog = this.deleteDialog();
if (!deleteDialog) throw new Error('no deleted dialog found');
return deleteDialog.prompt(subject);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
import ComplexFormComponents from '../field-editors/ComplexFormComponents.svelte';
import ComplexForms from '../field-editors/ComplexForms.svelte';
import ComplexFormTypes from '../field-editors/ComplexFormTypes.svelte';

import {useDialogService} from '$lib/entry-editor/dialog-service';
const dialogService = useDialogService();
const dispatch = createEventDispatcher<{
change: { entry: IEntry, sense?: ISense, example?: IExampleSentence};
delete: { entry: IEntry, sense?: ISense, example?: IExampleSentence};
Expand All @@ -36,11 +37,13 @@
sense.exampleSentences = [...sense.exampleSentences, sentence];
entry = entry; // examples counts are not updated without this
}
function deleteEntry() {
async function deleteEntry() {
if (!await dialogService.promptDelete('Entry')) return;
dispatch('delete', {entry});
}

function deleteSense(sense: ISense) {
async function deleteSense(sense: ISense) {
if (!await dialogService.promptDelete('Sense')) return;
entry.senses = entry.senses.filter(s => s !== sense);
dispatch('delete', {entry, sense});
}
Expand All @@ -50,7 +53,8 @@
dispatch('change', {entry, sense});
highlightedEntity = sense;
}
function deleteExample(sense: ISense, example: IExampleSentence) {
async function deleteExample(sense: ISense, example: IExampleSentence) {
if (!await dialogService.promptDelete('Example sentence')) return;
sense.exampleSentences = sense.exampleSentences.filter(e => e !== example);
dispatch('delete', {entry, sense, example});
entry = entry; // examples are not updated without this
Expand Down
Loading