1/*
2 * File uploads via Drag and Drop on elements with class "droptarget"
3 * and attribute "data-account-name"
4 */
5
6import { writable, Writable } from "svelte/store";
7
8import { put } from "./api";
9import { todayAsString } from "./format";
10import { delegate } from "./lib/events";
11import { basename, documentHasAccount } from "./lib/paths";
12import { notify } from "./notifications";
13
14function dragover(event: DragEvent, closestTarget: HTMLElement): void {
15  if (
16    event.dataTransfer &&
17    (event.dataTransfer.types.includes("Files") ||
18      event.dataTransfer.types.includes("text/uri-list"))
19  ) {
20    closestTarget.classList.add("dragover");
21    event.preventDefault();
22  }
23}
24delegate(document, "dragenter", ".droptarget", dragover);
25delegate(document, "dragover", ".droptarget", dragover);
26
27function dragleave(event: DragEvent, closestTarget: HTMLElement): void {
28  closestTarget.classList.remove("dragover");
29  event.preventDefault();
30}
31delegate(document, "dragleave", ".droptarget", dragleave);
32
33/* Stores that the Svelte component accesses. */
34export const account = writable("");
35export const hash = writable("");
36export const files: Writable<
37  {
38    dataTransferFile: File;
39    name: string;
40  }[]
41> = writable([]);
42
43function drop(event: DragEvent, target: HTMLElement): void {
44  target.classList.remove("dragover");
45  event.preventDefault();
46  event.stopPropagation();
47  if (!event.dataTransfer) {
48    return;
49  }
50
51  const url = event.dataTransfer.getData("URL");
52  if (url) {
53    let filename = new URL(url).searchParams.get("filename");
54    const acc = target.getAttribute("data-account-name");
55    if (acc && filename && documentHasAccount(filename, acc)) {
56      filename = basename(filename);
57    }
58    const entry_hash = target.getAttribute("data-entry");
59    if (filename && entry_hash) {
60      put("attach_document", { filename, entry_hash }).then(
61        (response) => {
62          notify(response);
63        },
64        (error) => {
65          notify(error, "error");
66        }
67      );
68    }
69    return;
70  }
71
72  const dateAttribute = target.getAttribute("data-entry-date");
73  const entryDate = dateAttribute || todayAsString();
74  account.set(target.getAttribute("data-account-name") || "");
75  hash.set(target.getAttribute("data-entry") || "");
76
77  const uploadedFiles: { dataTransferFile: File; name: string }[] = [];
78  for (const dataTransferFile of event.dataTransfer.files) {
79    let { name } = dataTransferFile;
80
81    if (!/^\d{4}-\d{2}-\d{2}/.test(name)) {
82      name = `${entryDate} ${name}`;
83    }
84
85    uploadedFiles.push({
86      dataTransferFile,
87      name,
88    });
89  }
90  files.set(uploadedFiles);
91}
92
93delegate(document, "drop", ".droptarget", drop);
94