Add embedding options to filesystem

This commit is contained in:
2024-02-16 21:07:01 +01:00
parent 68ef84b1e7
commit a9d685424f
8 changed files with 246 additions and 94 deletions

View File

@@ -314,7 +314,7 @@ h4,
h5,
h6 {
line-height: 1;
margin: 0.5em 0;
margin: 0.3em 0;
font-weight: lighter;
font-family: 'Open Sans Light', sans-serif;
}
@@ -365,7 +365,7 @@ a {
}
p {
margin: 1em 0;
margin: 0.5em 0;
}
/* Forms*/

View File

@@ -130,7 +130,7 @@ onDestroy(close_socket)
line-height: 0.75em;
margin-top: 0.5em;
}
@media (max-width: 600px) {
@media (max-width: 700px) {
.label {
text-align: center;
padding-left: 0;

View File

@@ -55,7 +55,7 @@ const keydown = e => {
if (edit_visible) {
edit_visible = false
} else {
edit_window.edit(state.base, true)
edit_window.edit(state.base, true, "file")
}
break;
case "s":
@@ -242,7 +242,10 @@ const update_css = path => document.documentElement.style = branding_from_path(p
flex-direction: row;
overflow: hidden;
}
@media (max-width: 600px) {
/* This max-width needs to be synced with the .toolbar max-width in
Toolbar.svelte and the .label max-width in FileStats.svelte */
@media (max-width: 700px) {
.viewer_area {
flex-direction: column-reverse;
}

View File

@@ -25,7 +25,7 @@ $: share_url = generate_share_url(state.path)
let link_copied = false
export const copy_link = () => {
if (share_url === "") {
edit_window.edit(state.base, "share", true)
edit_window.edit(state.base, true, "share")
return
}
@@ -119,7 +119,7 @@ let expand = e => {
</button>
{#if state.base.id !== "me" && state.permissions.update === true}
<button on:click={() => edit_window.edit(state.base, true)} class:button_highlight={edit_visible}>
<button on:click={() => edit_window.edit(state.base, true, "file")} class:button_highlight={edit_visible}>
<i class="icon">edit</i>
<span><u>E</u>dit</span>
</button>
@@ -161,7 +161,10 @@ let expand = e => {
.button_expand {
display: none;
}
@media (max-width: 600px) {
/* This max-width needs to be synced with the .viewer_area max-width in
Toolbar.svelte and the .label max-width in FileStats.svelte */
@media (max-width: 700px) {
.toolbar {
overflow-y: hidden;
max-height: 2.5em;

View File

@@ -1,11 +1,11 @@
<script>
import { fs_delete_all, fs_rename, fs_update } from "../FilesystemAPI";
import { fs_rename, fs_update } from "../FilesystemAPI";
import Modal from "../../util/Modal.svelte";
import { createEventDispatcher } from "svelte";
import Button from "../../layout/Button.svelte";
import BrandingOptions from "./BrandingOptions.svelte";
import PathLink from "../util/PathLink.svelte";
import { branding_from_node } from "./Branding";
import FileOptions from "./FileOptions.svelte";
import SharingOptions from "./SharingOptions.svelte";
let dispatch = createEventDispatcher()
@@ -19,17 +19,24 @@ let file = {
};
let custom_css = ""
$: is_root_dir = file.path === "/"+file.id
export let visible
export const edit = (f, oae = false, t = "file") => {
// Open the edit window. Argument 1 is the file to edit, 2 is whether the file
// should be opened after the user finishes editing and 3 is the default tab
// that should be open when the window shows
export const edit = (f, oae = false, open_tab = "") => {
file = f
open_after_edit = oae
tab = t
if (open_tab !== "") {
tab = open_tab
}
console.log("Editing file", file)
file_name = file.name
// We save the name in a separate field because we need both the original
// name and the new name for the rename operation
new_name = file.name
shared = !(file.id === undefined || file.id === "")
if (file.properties === undefined) {
@@ -49,8 +56,8 @@ export const edit = (f, oae = false, t = "file") => {
let tab = "file"
let open_after_edit = false
let file_name = ""
let shared = false
let new_name = ""
let branding_enabled = false
let branding_colors
@@ -63,14 +70,13 @@ let branding_fields = [
"brand_card_color",
"brand_header_image",
"brand_header_link",
"brand_footer_image",
"brand_footer_link",
"brand_background_image",
]
const save = async () => {
const save = async (keep_editing = false) => {
console.debug("Saving file", file.path)
let new_file
try {
dispatch("loading", true)
let opts = {shared: shared}
@@ -86,14 +92,17 @@ const save = async () => {
}
}
await fs_update(file.path, opts)
new_file = await fs_update(file.path, opts)
if (file_name !== file.name) {
if (new_name !== file.name) {
let parent = file.path.slice(0, -file.name.length)
console.log("Moving", file.path, "to", parent+file_name)
console.log("Moving", file.path, "to", parent+new_name)
await fs_rename(file.path, parent+file_name)
file.path = parent+file_name
await fs_rename(file.path, parent+new_name)
file.path = parent+new_name
new_file.name = new_name
new_file.path = file.path
}
} catch (err) {
if (err.message) {
@@ -112,27 +121,10 @@ const save = async () => {
} else {
fs_navigator.reload()
}
}
const delete_file = async e => {
e.preventDefault()
try {
dispatch("loading", true)
await fs_delete_all(file.path)
} catch (err) {
console.error(err)
alert(err)
return
} finally {
dispatch("loading", false)
if (keep_editing) {
edit(new_file, open_after_edit)
}
if (open_after_edit) {
fs_navigator.navigate(file.path, false)
} else {
fs_navigator.reload()
}
visible = false
}
</script>
@@ -152,55 +144,33 @@ const delete_file = async e => {
</button>
</div>
<form id="edit_form" on:submit|preventDefault={save}></form>
<form id="edit_form" on:submit|preventDefault={() => save(false)}></form>
{#if tab === "file"}
<div class="tab_content">
<h2>File settings</h2>
{#if is_root_dir}
<div class="highlight_yellow">
Filesystem root cannot be renamed. If this shared directory
is in
<PathLink nav={fs_navigator} path="/me">your filesystem</PathLink>
you can rename it from there
</div>
{/if}
<div class="form_grid">
<label for="file_name">Name</label>
<input form="edit_form" bind:value={file_name} id="file_name" type="text" class="form_input" disabled={is_root_dir}/>
</div>
<h2>Delete</h2>
<p>
Delete this file or directory. If this is a directory then all
subfiles will be deleted as well. This action cannot be undone.
</p>
<Button click={delete_file} red icon="delete" label="Delete" style="align-self: flex-start;"/>
</div>
{:else if tab === "share"}
<div class="tab_content">
<h2>Share this file/directory</h2>
<p>
When a file or directory is shared it can be accessed
through a unique link. You can get the URL with the 'Copy
link' button on the toolbar, or share the link with the
'Share' button. If you share a directory all the files
within the directory are also accessible from the link.
</p>
<div>
<input form="edit_form" bind:checked={shared} id="shared" type="checkbox" class="form_input"/>
<label for="shared">Share this file or directory</label>
</div>
</div>
{:else if tab === "branding"}
<div class="tab_content">
<div class="tab_content">
{#if tab === "file"}
<FileOptions
fs_navigator={fs_navigator}
bind:file
bind:new_name
bind:visible
bind:open_after_edit
on:loading
/>
{:else if tab === "share"}
<SharingOptions
bind:file
bind:shared
on:save={() => save(true)}
/>
{:else if tab === "branding"}
<BrandingOptions
bind:enabled={branding_enabled}
bind:colors={branding_colors}
file={file}
bind:file
on:style_change={e => custom_css = branding_from_node(file)}
/>
</div>
{/if}
{/if}
</div>
</Modal>
<style>
@@ -208,13 +178,6 @@ const delete_file = async e => {
border-bottom: 2px solid var(--separator);
}
.tab_content {
display: flex;
flex-direction: column;
padding: 8px;
}
.form_grid {
display: grid;
grid-template-columns: 1fr 10fr;
align-items: center;
}
</style>

View File

@@ -0,0 +1,66 @@
<script>
import { createEventDispatcher } from "svelte";
import Button from "../../layout/Button.svelte";
import { fs_delete_all } from "../FilesystemAPI";
import PathLink from "../util/PathLink.svelte";
let dispatch = createEventDispatcher()
export let fs_navigator
export let file = {}
export let new_name
export let visible
export let open_after_edit
$: is_root_dir = file.path === "/"+file.id
const delete_file = async e => {
e.preventDefault()
try {
dispatch("loading", true)
await fs_delete_all(file.path)
} catch (err) {
console.error(err)
alert(err)
return
} finally {
dispatch("loading", false)
}
if (open_after_edit) {
fs_navigator.navigate(file.path, false)
} else {
fs_navigator.reload()
}
visible = false
}
</script>
<h2>File settings</h2>
{#if is_root_dir}
<div class="highlight_yellow">
Filesystem root cannot be renamed. If this shared directory
is in
<PathLink nav={fs_navigator} path="/me">your filesystem</PathLink>
you can rename it from there
</div>
{/if}
<div class="form_grid">
<label for="file_name">Name</label>
<input form="edit_form" bind:value={new_name} id="file_name" type="text" class="form_input" disabled={is_root_dir}/>
</div>
<h2>Delete</h2>
<p>
Delete this file or directory. If this is a directory then all
subfiles will be deleted as well. This action cannot be undone.
</p>
<Button click={delete_file} red icon="delete" label="Delete" style="align-self: flex-start;"/>
<style>
.form_grid {
display: grid;
grid-template-columns: 1fr 10fr;
align-items: center;
}
</style>

View File

@@ -0,0 +1,117 @@
<script>
import { createEventDispatcher } from "svelte";
import { copy_text, domain_url } from "../../util/Util.svelte";
import Button from "../../layout/Button.svelte";
let dispatch = createEventDispatcher()
export let shared
export let file
let embed_html
let preview_area
$: is_shared = file.id !== undefined && file.id !== ""
$: share_link = window.location.protocol+"//"+window.location.host+"/d/"+file.id
$: embed_iframe(file)
let embed_iframe = file => {
if (!is_shared) {
example = false
embed_html = "File is not shared, can't generate embed code"
return
}
let url = domain_url()+"/d/"+file.id
embed_html = `<iframe ` +
`src="${url}" ` +
`style="border: none; width: 800px; max-width: 100%; height: 600px; max-height: 100%; border-radius: 8px;"` +
`></iframe>`
}
let copy_status = "" // empty, success or error
const copy = () => {
if (copy_text(embed_html)) {
copy_status = "success"
} else {
copy_status = "error"
alert("Your browser does not support copying text.")
}
}
let example = false
const toggle_example = () => {
if (is_shared) {
example = !example
if (example) {
preview_area.innerHTML = embed_html
} else {
preview_area.innerHTML = ""
}
}
}
</script>
<h2>Share this file/directory</h2>
<p>
When a file or directory is shared it can be accessed through a
unique link. You can get the URL with the 'Copy link' button on
the toolbar, or share the link with the 'Share' button. If you
share a directory all the files within the directory are also
accessible from the link.
</p>
<div class="form_grid">
<div>
<input form="edit_form" bind:checked={shared} id="shared" type="checkbox" class="form_input"/>
<label for="shared">Share this file or directory</label>
</div>
<button on:click={() => dispatch("save")}><i class="icon">save</i> Save</button>
{#if is_shared}
<span>Your sharing link: <a href={share_link}>{share_link}</a></span>
<Button highlight_on_click icon="content_copy" label="Copy" click={e => copy_text(share_link)}/>
{/if}
</div>
<h2>Embedding</h2>
<p>
If you have a website you can embed pixeldrain directories and files in your
own webpages with the code below. If you embed a directory then all
subdirectories and files will be accessible through the frame. Branding
options will also apply in the frame, but only when applied to this
directory. It will not inherit the style from parent directories.
</p>
<h3>Code</h3>
<p>
Put this code in your website to embed the file or directory.
</p>
<div class="center">
<textarea bind:value={embed_html} style="width: 100%; height: 4em;"></textarea>
<br/>
<button on:click={copy} class:button_highlight={copy_status === "success"} class:button_red={copy_status === "error"}>
<i class="icon">content_copy</i>
{#if copy_status === "success"}
Copied!
{:else if copy_status === "error"}
Error!
{:else}
Copy HTML
{/if}
</button>
<button on:click={toggle_example} class:button_highlight={example} disabled={!is_shared}>
<i class="icon">visibility</i> Show example
</button>
</div>
<div bind:this={preview_area} style="text-align: center;"></div>
<style>
.center {
text-align: center;
}
.form_grid {
display: grid;
grid-template-columns: 10fr auto;
align-items: center;
}
</style>

View File

@@ -71,7 +71,7 @@ const node_select = e => {
state.children[index].fm_selected = !state.children[index].fm_selected
}
const node_settings = e => edit_window.edit(state.children[e.detail], false)
const node_settings = e => edit_window.edit(state.children[e.detail], false, "file")
const node_branding = e => edit_window.edit(state.children[e.detail], false, "branding")
const navigate_up = () => {