mirror of
https://github.com/sissbruecker/linkding.git
synced 2025-08-07 18:58:30 +02:00
Add bookmark details view (#665)
* Experiment with bookmark details * Add basic tests * Refactor details into modal * Implement edit and delete button * Remove slide down animation * Add fallback details view * Add status actions * Improve dark theme * Improve return URLs * Make bookmark details sharable * Fix E2E tests
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { registerBehavior } from "./index";
|
||||
import { applyBehaviors, registerBehavior } from "./index";
|
||||
|
||||
class ModalBehavior {
|
||||
constructor(element) {
|
||||
@@ -7,14 +7,50 @@ class ModalBehavior {
|
||||
this.toggle = toggle;
|
||||
}
|
||||
|
||||
onToggleClick() {
|
||||
async onToggleClick(event) {
|
||||
// Ignore Ctrl + click
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Create modal either by teleporting existing content or fetching from URL
|
||||
const modal = this.toggle.hasAttribute("modal-content")
|
||||
? this.createFromContent()
|
||||
: await this.createFromUrl();
|
||||
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register close handlers
|
||||
const modalOverlay = modal.querySelector(".modal-overlay");
|
||||
const closeButton = modal.querySelector("button.close");
|
||||
modalOverlay.addEventListener("click", this.onClose.bind(this));
|
||||
closeButton.addEventListener("click", this.onClose.bind(this));
|
||||
|
||||
document.body.append(modal);
|
||||
applyBehaviors(document.body);
|
||||
this.modal = modal;
|
||||
}
|
||||
|
||||
async createFromUrl() {
|
||||
const url = this.toggle.getAttribute("modal-url");
|
||||
const modalHtml = await fetch(url).then((response) => response.text());
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(modalHtml, "text/html");
|
||||
return doc.querySelector(".modal");
|
||||
}
|
||||
|
||||
createFromContent() {
|
||||
const contentSelector = this.toggle.getAttribute("modal-content");
|
||||
const content = document.querySelector(contentSelector);
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create modal
|
||||
// Todo: make title configurable, only used for tag cloud for now
|
||||
const modal = document.createElement("div");
|
||||
modal.classList.add("modal", "active");
|
||||
modal.innerHTML = `
|
||||
@@ -22,7 +58,7 @@ class ModalBehavior {
|
||||
<div class="modal-container">
|
||||
<div class="modal-header d-flex justify-between align-center">
|
||||
<div class="modal-title h5">Tags</div>
|
||||
<button class="btn btn-link close">
|
||||
<button class="close">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M18 6l-12 12"></path>
|
||||
@@ -36,29 +72,28 @@ class ModalBehavior {
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Teleport content element
|
||||
const contentOwner = content.parentElement;
|
||||
const contentContainer = modal.querySelector(".content");
|
||||
contentContainer.append(content);
|
||||
this.content = content;
|
||||
this.contentOwner = contentOwner;
|
||||
|
||||
// Register close handlers
|
||||
const modalOverlay = modal.querySelector(".modal-overlay");
|
||||
const closeButton = modal.querySelector(".btn.close");
|
||||
modalOverlay.addEventListener("click", this.onClose.bind(this));
|
||||
closeButton.addEventListener("click", this.onClose.bind(this));
|
||||
|
||||
document.body.append(modal);
|
||||
this.modal = modal;
|
||||
return modal;
|
||||
}
|
||||
|
||||
onClose() {
|
||||
// Teleport content back
|
||||
this.contentOwner.append(this.content);
|
||||
if (this.content && this.contentOwner) {
|
||||
this.contentOwner.append(this.content);
|
||||
}
|
||||
|
||||
// Remove modal
|
||||
this.modal.remove();
|
||||
this.modal.classList.add("closing");
|
||||
this.modal.addEventListener("animationend", (event) => {
|
||||
if (event.animationName === "fade-out") {
|
||||
this.modal.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user