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

Deletable documents #131

Merged
merged 1 commit into from
Sep 5, 2024
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
13 changes: 12 additions & 1 deletion frontend/src/lib/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class AssetCache {
* @param path The key to store the entry under
* @param value The entry
*/
async set(path: string, value: CacheEntry) {
set(path: string, value: CacheEntry) {
// evict the least recently used item if necessary
if (this.values.size >= this.maxEntries) {
const keyToDelete = this.values.keys().next().value;
Expand All @@ -55,6 +55,17 @@ class AssetCache {
this.values.set(path, value);
}

/**
* Remove the specified item from cache.
*
* This operation is **not write-through**, so changes
* are not synced to the backend.
* @param path
*/
delete(path: string) {
this.values.delete(path)
}

/**
* Completely empty the cache of all entries.
*/
Expand Down
87 changes: 87 additions & 0 deletions frontend/src/lib/components/ConfirmationDialogue.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<!-- A generic confirmation dialogue -->
<script lang="ts">
/**
* If defined, the code that runs when a user hits "Confirm".
*/
export let confirmHandler = () => {};
/**
* If defined, the code that runs when the user hits "Deny" or
* clicks out of the widget.
*/
export let cancelHandler = () => {};
export let confirmText = 'Confirm';
export let cancelText = 'Cancel';
export let visible: boolean;
</script>

<div class="backdrop"></div>
<div class="container">
<div class="inserted-content">
<slot></slot>
</div>
<div class="control-buttons">
<button
on:click={() => {
visible = false;
cancelHandler();
}}
>
{cancelText}
</button>
<button
on:click={() => {
visible = false;
confirmHandler();
}}
>
{confirmText}
</button>
</div>
</div>

<style>
.backdrop {
position: absolute;
width: 100vw;
height: 100vh;
left: 0;
top: 0;
background-color: var(--background-0);
opacity: 0.4;
}

.container {
position: absolute;
z-index: 1;
background-color: var(--background-2);
border-radius: 2px;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
}

.inserted-content {
margin: 0.5rem;
}

.control-buttons {
display: flex;
justify-content: right;
margin: 0.3rem;
}

.control-buttons button {
cursor: pointer;
margin: 0.1rem;
font-size: 0.9rem;
background-color: transparent;
color: var(--foreground-0);
border: 1px solid var(--foreground-0);
border-radius: 2px;
}

.control-buttons button:hover {
color: var(--background-2);
background-color: var(--foreground-1);
}
</style>
4 changes: 3 additions & 1 deletion frontend/src/lib/components/Editor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@
}

currentFile.subscribe(async (v) => {
editorText = (await cache.get(v)) ?? '';
if (v !== '') {
editorText = (await cache.get(v)) ?? '';
}
});

const unsubscribe = currentFile.subscribe(async (file) => {
Expand Down
72 changes: 66 additions & 6 deletions frontend/src/lib/components/FileNavigation.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { currentFile } from '$lib/main';
import { cache } from '$lib/cache';
import { get } from 'svelte/store';
import ConfirmationDialogue from './ConfirmationDialogue.svelte';
interface INode {
name: string;
children: INode[];
Expand All @@ -13,12 +14,15 @@
export let children: INode[] = [];
export let indent = 1;
export let path = name;
export let siblings: INode[] | undefined = undefined;
let self: HTMLElement;
let selected = false;
let open = false;
let showOptionsMenu = false;
let optionsMenu: HTMLDivElement;
let showNewFileInput = false;
let newFileInput: HTMLInputElement;
let showDeleteFileDialogue = false;

const dispatch = createEventDispatcher();

Expand Down Expand Up @@ -51,9 +55,28 @@
newFileInput.setSelectionRange(0, 0);
newFileInput.focus();
}
</script>

<span class={'container' + (selected ? ' selected' : '')}>
async function deleteDocumentHandler() {
showOptionsMenu = false;
if (get(currentFile) === path) {
currentFile.set('');
}
if (siblings !== undefined) {
// siblings.filter((n) => n.name !== name);
const entryToRemove = siblings.findIndex(n => n.name === name);
console.log(siblings.splice(entryToRemove, 1));
}
// TODO: requisite backend work, eg create DELETE
// handler for documents.

// While a re-render would happen when the directory
// is closed and re-opened, I nuke the current element here
// because I don't know how else to make it happen immediately
self.remove();
console.log(`Document "${path}" would be deleted`);
}
</script>
<span bind:this={self} class={'container' + (selected ? ' selected' : '')}>
<button on:click={fileClickHandler} style="padding-left: {indent}rem" class="entry-button">
{#if children.length > 0}
<!-- Rendering if the navigation item is a directory -->
Expand Down Expand Up @@ -95,7 +118,6 @@
>
</button>
</span>

{#if showNewFileInput}
<span>
<input
Expand Down Expand Up @@ -151,7 +173,7 @@ last_modified_date: ${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}
<div tabindex="-1" bind:this={optionsMenu} class="options-menu">
{#if children.length > 0}
<!-- Options for if the entry is a directory -->
<button on:click={createDocumentHandler}>
<button on:click={createDocumentHandler} title="Create New Document">
<svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
Expand All @@ -163,18 +185,56 @@ last_modified_date: ${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}
</button>
{:else}
<!-- Options for if the entry is a file -->
<button
on:click={() => {
showDeleteFileDialogue = true;
}}
title="Delete Document"
>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
><path
d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"
/></svg
>
Delete Document
</button>
{/if}
</div>
{/if}

{#if showDeleteFileDialogue}
<ConfirmationDialogue
confirmHandler={() => {
deleteDocumentHandler();
}}
bind:visible={showDeleteFileDialogue}
>
Are you sure you want to delete the file "{name}"?
</ConfirmationDialogue>
{/if}

{#if open}
{#each children as child}
{#if child.children.length === 0}
<!-- Treat path like file -->
<svelte:self on:fileselect {...child} indent={indent + 1.5} path={path + child.name} />
<svelte:self
on:fileselect
name={child.name}
children={child.children}
siblings={children}
indent={indent + 1.5}
path={path + child.name}
/>
{:else}
<!-- Treat path like directory -->
<svelte:self on:fileselect {...child} indent={indent + 1} path={path + child.name + '/'} />
<svelte:self
on:fileselect
name={child.name}
children={child.children}
siblings={children}
indent={indent + 1}
path={path + child.name + '/'}
/>
{/if}
{/each}
{/if}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
(await cache.get(e.detail.path)) ??
'Something went wrong, the file tree reported by the backend references a nonexistent file.';
renderMarkdown(editorText, previewWindow);
} else if (e.detail.path === currentFile) {
} else if (e.detail.path === get(currentFile)) {
// Do nothing
} else {
// Unsaved changes
Expand Down
Loading