Convert multiple pages into SPA
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { fs_encode_path, fs_node_icon, node_is_shared } from "filesystem/FilesystemAPI"
|
||||
import { fs_encode_path, fs_node_icon, node_is_shared } from "lib/FilesystemAPI"
|
||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
||||
import { FileAction } from "./FileManagerLib";
|
||||
|
||||
@@ -36,21 +36,14 @@ export let hide_edit = false
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
{#if $nav.permissions.write && !hide_edit}
|
||||
<button
|
||||
class="action_button flat"
|
||||
on:click={e => dispatch("file", {index: index, action: FileAction.Edit, original: e})}
|
||||
>
|
||||
<i class="icon">edit</i>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if !hide_edit}
|
||||
<button
|
||||
class="action_button flat"
|
||||
on:click={e => dispatch("file", {index: index, action: FileAction.Download, original: e})}
|
||||
on:click={e => dispatch("file", {index: index, action: FileAction.Menu, original: e})}
|
||||
>
|
||||
<i class="icon">save</i>
|
||||
<i class="icon">menu</i>
|
||||
</button>
|
||||
{/if}
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -71,9 +64,9 @@ export let hide_edit = false
|
||||
color: var(--body_text-color);
|
||||
padding: 2px;
|
||||
align-items: center;
|
||||
background: var(--input_background);
|
||||
background: var(--shaded_background);
|
||||
backdrop-filter: blur(4px);
|
||||
border-radius: 4px;
|
||||
box-shadow: 1px 1px 8px 0px var(--shadow_color);
|
||||
gap: 6px;
|
||||
}
|
||||
.node:hover:not(.node_selected) {
|
||||
@@ -92,7 +85,6 @@ export let hide_edit = false
|
||||
height: 2em;
|
||||
width: 2em;
|
||||
vertical-align: middle;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.node_name {
|
||||
flex: 1 1 content;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { fs_mkdir } from "filesystem/FilesystemAPI";
|
||||
import { fs_mkdir } from "lib/FilesystemAPI";
|
||||
import Button from "layout/Button.svelte";
|
||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
||||
import { loading_finish, loading_start } from "lib/Loading";
|
||||
|
||||
export let nav: FSNavigator
|
||||
|
||||
@@ -14,7 +15,7 @@ let create_dir = async () => {
|
||||
form.append("type", "dir")
|
||||
|
||||
try {
|
||||
nav.set_loading(true)
|
||||
loading_start()
|
||||
await fs_mkdir(nav.base.path+"/"+new_dir_name)
|
||||
new_dir_name = "" // Clear input field
|
||||
error_msg = "" // Clear error msg
|
||||
@@ -26,7 +27,7 @@ let create_dir = async () => {
|
||||
error_msg = "Server returned an error: code: '"+err.value+"' message: "+err.message
|
||||
}
|
||||
} finally {
|
||||
nav.set_loading(false)
|
||||
loading_finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { fs_delete_all, fs_download, fs_rename, type FSNode } from "filesystem/FilesystemAPI"
|
||||
import { fs_delete_all, fs_download, fs_rename, type FSNode } from "lib/FilesystemAPI"
|
||||
import { onMount } from "svelte"
|
||||
import CreateDirectory from "./CreateDirectory.svelte"
|
||||
import ListView from "./ListView.svelte"
|
||||
@@ -13,6 +13,7 @@ import type { FSNavigator } from "filesystem/FSNavigator";
|
||||
import FsUploadWidget from "filesystem/upload_widget/FSUploadWidget.svelte";
|
||||
import EditWindow from "filesystem/edit_window/EditWindow.svelte";
|
||||
import { FileAction, type FileEvent } from "./FileManagerLib";
|
||||
import FileMenu from "./FileMenu.svelte";
|
||||
|
||||
export let nav: FSNavigator
|
||||
export let upload_widget: FsUploadWidget
|
||||
@@ -23,6 +24,7 @@ let uploader: FsUploadWidget
|
||||
let mode = "viewing"
|
||||
let creating_dir = false
|
||||
let show_hidden = false
|
||||
let file_menu: FileMenu
|
||||
|
||||
export const upload = (files: File[]) => {
|
||||
return uploader.upload(files)
|
||||
@@ -84,6 +86,11 @@ const file_event = (e: CustomEvent<FileEvent>) => {
|
||||
e.detail.original.stopPropagation()
|
||||
fs_download(nav.children[index])
|
||||
break
|
||||
case FileAction.Menu:
|
||||
e.detail.original.preventDefault()
|
||||
e.detail.original.stopPropagation()
|
||||
file_menu.open(nav.children[index], e.detail.original.target)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,10 +417,10 @@ onMount(() => {
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<FileMenu bind:this={file_menu} bind:nav bind:edit_window />
|
||||
|
||||
<style>
|
||||
.container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
display: block;
|
||||
|
||||
@@ -3,4 +3,4 @@ export type FileEvent = {
|
||||
action: FileAction,
|
||||
original: MouseEvent,
|
||||
}
|
||||
export enum FileAction { Click, Context, Edit, Share, Branding, Select, Download }
|
||||
export enum FileAction { Click, Context, Edit, Share, Branding, Select, Download, Menu }
|
||||
|
||||
64
svelte/src/filesystem/filemanager/FileMenu.svelte
Normal file
64
svelte/src/filesystem/filemanager/FileMenu.svelte
Normal file
@@ -0,0 +1,64 @@
|
||||
<script lang="ts">
|
||||
import EditWindow from "filesystem/edit_window/EditWindow.svelte";
|
||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
||||
import Button from "layout/Button.svelte";
|
||||
import Dialog from "layout/Dialog.svelte";
|
||||
import { bookmark_add, bookmark_del, bookmarks_store } from "lib/Bookmarks";
|
||||
import { fs_download, type FSNode } from "lib/FilesystemAPI";
|
||||
import { tick } from "svelte";
|
||||
|
||||
export let nav: FSNavigator
|
||||
export let edit_window: EditWindow
|
||||
let dialog: Dialog
|
||||
let node: FSNode
|
||||
let is_bookmark: boolean = false
|
||||
|
||||
export const open = async (n: FSNode, target: EventTarget) => {
|
||||
node = n
|
||||
|
||||
is_bookmark = false
|
||||
for (const bm of $bookmarks_store) {
|
||||
console.log(bm)
|
||||
if (bm.id === n.id) {
|
||||
is_bookmark = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the view to update, so the dialog gets the proper measurements
|
||||
await tick()
|
||||
dialog.open((target as Element).closest("button").getBoundingClientRect())
|
||||
}
|
||||
|
||||
const bookmark = () => {
|
||||
bookmark_add({
|
||||
id: node.id,
|
||||
icon: "folder_shared",
|
||||
label: node.name,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<Dialog bind:this={dialog}>
|
||||
<div class="menu">
|
||||
<Button click={() => {dialog.close(); fs_download(node)}} icon="save" label="Download"/>
|
||||
{#if is_bookmark}
|
||||
<Button click={() => {dialog.close(); bookmark_del(node.id)}} icon="bookmark_remove" label="Remove bookmark"/>
|
||||
{:else}
|
||||
<Button click={() => {dialog.close(); bookmark()}} icon="bookmark_add" label="Add bookmark"/>
|
||||
{/if}
|
||||
{#if $nav.permissions.write}
|
||||
<Button click={() => {dialog.close(); edit_window.edit(node, false, "file")}} icon="edit" label="Edit"/>
|
||||
<Button click={() => {dialog.close(); edit_window.edit(node, false, "share")}} icon="share" label="Share"/>
|
||||
<Button click={() => {dialog.close(); edit_window.edit(node, false, "branding")}} icon="palette" label="Branding"/>
|
||||
{/if}
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
<style>
|
||||
.menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 20em;
|
||||
}
|
||||
</style>
|
||||
@@ -4,17 +4,15 @@ import ListView from "./ListView.svelte"
|
||||
import GalleryView from "./GalleryView.svelte"
|
||||
import CompactView from "./CompactView.svelte"
|
||||
import Modal from "util/Modal.svelte";
|
||||
import LoadingIndicator from "util/LoadingIndicator.svelte";
|
||||
import Breadcrumbs from "filesystem/Breadcrumbs.svelte"
|
||||
import { FSNavigator } from "filesystem/FSNavigator";
|
||||
import type { FSNode } from "filesystem/FilesystemAPI";
|
||||
import type { FSNode } from "lib/FilesystemAPI";
|
||||
import { FileAction, type FileEvent } from "./FileManagerLib";
|
||||
|
||||
let nav = new FSNavigator(false)
|
||||
let modal: Modal
|
||||
let dispatch = createEventDispatcher()
|
||||
let directory_view = ""
|
||||
let loading = false
|
||||
let large_icons = false
|
||||
let show_hidden = false
|
||||
export let select_multiple = false
|
||||
@@ -194,8 +192,6 @@ onMount(() => {
|
||||
on:file={file_event}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<LoadingIndicator loading={loading}/>
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { fs_node_icon, fs_node_type, fs_encode_path } from "filesystem/FilesystemAPI";
|
||||
import { fs_node_icon, fs_node_type, fs_encode_path } from "lib/FilesystemAPI";
|
||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
||||
import { FileAction } from "./FileManagerLib";
|
||||
let dispatch = createEventDispatcher()
|
||||
@@ -46,15 +46,15 @@ export let large_icons = false
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
background: var(--input_background);
|
||||
background: var(--shaded_background);
|
||||
backdrop-filter: blur(4px);
|
||||
border-radius: 4px;
|
||||
color: var(--input_text);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: background 0.2s;
|
||||
text-decoration: none;
|
||||
padding: 3px;
|
||||
box-shadow: 1px 1px 0px 0px var(--shadow_color);
|
||||
}
|
||||
.file.large_icons {
|
||||
width: 200px;
|
||||
@@ -87,7 +87,7 @@ export let large_icons = false
|
||||
}
|
||||
.node_icon {
|
||||
flex: 1 1 0;
|
||||
border-radius: 6px;
|
||||
border-radius: 4px;
|
||||
background-position: center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { formatDataVolume } from "util/Formatting";
|
||||
import { fs_encode_path, fs_node_icon, node_is_shared } from "filesystem/FilesystemAPI"
|
||||
import { fs_encode_path, fs_node_icon, node_is_shared } from "lib/FilesystemAPI"
|
||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
||||
import SortButton from "layout/SortButton.svelte";
|
||||
import { FileAction } from "./FileManagerLib";
|
||||
@@ -19,7 +19,7 @@ export let hide_branding = false
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><SortButton active_field={$nav.sort_last_field} asc={$nav.sort_asc} sort_func={nav.sort_children} field="name">Name</SortButton></td>
|
||||
<td><SortButton active_field={$nav.sort_last_field} asc={$nav.sort_asc} sort_func={nav.sort_children} field="file_size">Size</SortButton></td>
|
||||
<td class="hide_small"><SortButton active_field={$nav.sort_last_field} asc={$nav.sort_asc} sort_func={nav.sort_children} field="file_size">Size</SortButton></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{#each $nav.children as child, index (child.path)}
|
||||
@@ -60,14 +60,11 @@ export let hide_branding = false
|
||||
<i class="icon">palette</i>
|
||||
</button>
|
||||
{/if}
|
||||
{#if $nav.permissions.write && !hide_edit}
|
||||
<button class="action_button" on:click={e => dispatch("file", {index: index, action: FileAction.Edit, original: e})}>
|
||||
<i class="icon">edit</i>
|
||||
{#if !hide_edit}
|
||||
<button class="action_button" on:click={e => dispatch("file", {index: index, action: FileAction.Menu, original: e})}>
|
||||
<i class="icon">menu</i>
|
||||
</button>
|
||||
{/if}
|
||||
<button class="action_button" on:click={e => dispatch("file", {index: index, action: FileAction.Download, original: e})}>
|
||||
<i class="icon">save</i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</a>
|
||||
@@ -77,13 +74,11 @@ export let hide_branding = false
|
||||
<style>
|
||||
.directory {
|
||||
display: table;
|
||||
margin: 8px auto 16px auto;
|
||||
background: var(--shaded_background);
|
||||
border-collapse: collapse;
|
||||
border-radius: 8px;
|
||||
|
||||
max-width: 99%;
|
||||
width: 1200px;
|
||||
backdrop-filter: blur(4px);
|
||||
max-width: 1200px;
|
||||
margin: auto; /* center */
|
||||
}
|
||||
.directory > * {
|
||||
display: table-row;
|
||||
@@ -116,7 +111,7 @@ td {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
vertical-align: middle;
|
||||
border-radius: 4px;
|
||||
/* border-radius: 4px; */
|
||||
margin: 2px;
|
||||
}
|
||||
.node_name {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { fs_search, fs_encode_path, fs_thumbnail_url } from "filesystem/FilesystemAPI";
|
||||
import { fs_search, fs_encode_path, fs_thumbnail_url } from "lib/FilesystemAPI";
|
||||
import type { FSNavigator } from "filesystem/FSNavigator";
|
||||
import { loading_finish, loading_start } from "lib/Loading";
|
||||
|
||||
export let nav: FSNavigator
|
||||
|
||||
@@ -43,9 +44,9 @@ const search = async (limit = 10) => {
|
||||
last_limit = limit
|
||||
|
||||
searching = true
|
||||
nav.set_loading(true)
|
||||
|
||||
try {
|
||||
loading_start()
|
||||
search_results = await fs_search(nav.base.path, search_term, limit)
|
||||
} catch (err) {
|
||||
if (err.value) {
|
||||
@@ -54,6 +55,8 @@ const search = async (limit = 10) => {
|
||||
alert(err)
|
||||
console.error(err)
|
||||
}
|
||||
} finally {
|
||||
loading_finish()
|
||||
}
|
||||
|
||||
if (search_results.length > 0 && selected_result > search_results.length-1) {
|
||||
@@ -61,7 +64,6 @@ const search = async (limit = 10) => {
|
||||
}
|
||||
|
||||
searching = false
|
||||
nav.set_loading(false)
|
||||
|
||||
// It's possible that the user entered another letter while we were
|
||||
// performing the search reqeust. If this happens we run the search function
|
||||
@@ -218,7 +220,6 @@ const window_keydown = (e: KeyboardEvent) => {
|
||||
max-width: 100%;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
border-bottom: 1px solid var(--separator);
|
||||
}
|
||||
|
||||
.search_form {
|
||||
|
||||
Reference in New Issue
Block a user