mirror of
https://github.com/sissbruecker/linkding.git
synced 2026-02-28 06:53:12 +08:00
Cleanup modals
This commit is contained in:
@@ -22,16 +22,20 @@ customElements.define("ld-filter-drawer-trigger", FilterDrawerTrigger);
|
||||
|
||||
class FilterDrawer extends Modal {
|
||||
connectedCallback() {
|
||||
this.classList.add("modal", "drawer", "filter-drawer");
|
||||
this.classList.add("modal", "drawer");
|
||||
|
||||
// Render modal structure
|
||||
render(
|
||||
html`
|
||||
<div class="modal-overlay"></div>
|
||||
<div class="modal-overlay" data-close-modal></div>
|
||||
<div class="modal-container" role="dialog" aria-modal="true">
|
||||
<div class="modal-header">
|
||||
<h2>Filters</h2>
|
||||
<button class="btn btn-noborder close" aria-label="Close dialog">
|
||||
<button
|
||||
class="btn btn-noborder close"
|
||||
aria-label="Close dialog"
|
||||
data-close-modal
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
@@ -49,9 +53,7 @@ class FilterDrawer extends Modal {
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="content"></div>
|
||||
</div>
|
||||
<div class="modal-body"></div>
|
||||
</div>
|
||||
`,
|
||||
this,
|
||||
@@ -61,6 +63,8 @@ class FilterDrawer extends Modal {
|
||||
// Force close on turbo cache to restore content
|
||||
this.doClose = this.doClose.bind(this);
|
||||
document.addEventListener("turbo:before-cache", this.doClose);
|
||||
// Force reflow to make transform transition work
|
||||
this.getBoundingClientRect();
|
||||
// Add active class to start slide-in animation
|
||||
requestAnimationFrame(() => this.classList.add("active"));
|
||||
// Call super after rendering to ensure elements are available
|
||||
@@ -70,7 +74,7 @@ class FilterDrawer extends Modal {
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.teleportBack();
|
||||
document.addEventListener("turbo:before-cache", this.doClose);
|
||||
document.removeEventListener("turbo:before-cache", this.doClose);
|
||||
}
|
||||
|
||||
mapHeading(container, from, to) {
|
||||
@@ -83,7 +87,7 @@ class FilterDrawer extends Modal {
|
||||
}
|
||||
|
||||
teleport() {
|
||||
const content = this.querySelector(".content");
|
||||
const content = this.querySelector(".modal-body");
|
||||
const sidePanel = document.querySelector(".side-panel");
|
||||
content.append(...sidePanel.children);
|
||||
this.mapHeading(content, "h2", "h3");
|
||||
@@ -91,7 +95,7 @@ class FilterDrawer extends Modal {
|
||||
|
||||
teleportBack() {
|
||||
const sidePanel = document.querySelector(".side-panel");
|
||||
const content = this.querySelector(".content");
|
||||
const content = this.querySelector(".modal-body");
|
||||
sidePanel.append(...content.children);
|
||||
this.mapHeading(sidePanel, "h3", "h2");
|
||||
}
|
||||
|
||||
@@ -5,11 +5,10 @@ export class Modal extends HTMLElement {
|
||||
requestAnimationFrame(() => {
|
||||
this.onClose = this.onClose.bind(this);
|
||||
this.onKeyDown = this.onKeyDown.bind(this);
|
||||
this.overlay = this.querySelector(".modal-overlay");
|
||||
this.closeButton = this.querySelector(".modal-header .close");
|
||||
|
||||
this.overlay.addEventListener("click", this.onClose);
|
||||
this.closeButton.addEventListener("click", this.onClose);
|
||||
this.querySelectorAll("[data-close-modal]").forEach((btn) => {
|
||||
btn.addEventListener("click", this.onClose);
|
||||
});
|
||||
document.addEventListener("keydown", this.onKeyDown);
|
||||
|
||||
this.setupScrollLock();
|
||||
@@ -20,8 +19,9 @@ export class Modal extends HTMLElement {
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.overlay.removeEventListener("click", this.onClose);
|
||||
this.closeButton.removeEventListener("click", this.onClose);
|
||||
this.querySelectorAll("[data-close-modal]").forEach((btn) => {
|
||||
btn.removeEventListener("click", this.onClose);
|
||||
});
|
||||
document.removeEventListener("keydown", this.onKeyDown);
|
||||
|
||||
this.removeScrollLock();
|
||||
@@ -74,8 +74,9 @@ export class Modal extends HTMLElement {
|
||||
// Navigate to close URL
|
||||
const closeUrl = this.dataset.closeUrl;
|
||||
const frame = this.dataset.turboFrame;
|
||||
const action = this.dataset.turboAction || "replace";
|
||||
if (closeUrl) {
|
||||
Turbo.visit(closeUrl, { action: "replace", frame: frame });
|
||||
Turbo.visit(closeUrl, { action, frame: frame });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,12 @@
|
||||
<ld-details-modal class="modal active bookmark-details"
|
||||
data-bookmark-id="{{ details.bookmark.id }}" data-close-url="{{ details.close_url }}"
|
||||
data-turbo-frame="details-modal">
|
||||
<div class="modal-overlay"></div>
|
||||
<div class="modal-overlay" data-close-modal></div>
|
||||
<div class="modal-container" role="dialog" aria-modal="true">
|
||||
<div class="modal-header">
|
||||
<h2 class="title">{{ details.bookmark.resolved_title }}</h2>
|
||||
<button class="btn btn-noborder close" aria-label="Close dialog">
|
||||
<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>
|
||||
<path d="M6 6l12 12"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
{% include 'shared/modal_header.html' with title=details.bookmark.resolved_title %}
|
||||
<div class="modal-body">
|
||||
<div class="content">
|
||||
{% include 'bookmarks/details/form.html' %}
|
||||
</div>
|
||||
{% include 'bookmarks/details/form.html' %}
|
||||
</div>
|
||||
|
||||
{% if details.is_editable %}
|
||||
<div class="modal-footer">
|
||||
<div class="actions">
|
||||
|
||||
@@ -3,40 +3,25 @@
|
||||
data-turbo-frame="api-section">
|
||||
{% csrf_token %}
|
||||
<ld-modal class="modal active" data-close-url="{% url 'linkding:settings.integrations' %}"
|
||||
data-turbo-frame="api-modal">
|
||||
<div class="modal-overlay"></div>
|
||||
data-turbo-frame="api-modal">
|
||||
<div class="modal-overlay" data-close-modal></div>
|
||||
<div class="modal-container" role="dialog" aria-modal="true">
|
||||
<div class="modal-header">
|
||||
<h2 class="title">Create API Token</h2>
|
||||
<button type="button" class="btn btn-noborder close" aria-label="Close dialog">
|
||||
<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>
|
||||
<path d="M6 6l12 12"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
{% include 'shared/modal_header.html' with title="Create API Token" %}
|
||||
<div class="modal-body">
|
||||
<div class="content">
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="token-name">Token name</label>
|
||||
<input type="text"
|
||||
class="form-input"
|
||||
id="token-name"
|
||||
name="name"
|
||||
placeholder="e.g., Browser Extension, Mobile App"
|
||||
value="API Token"
|
||||
maxlength="128">
|
||||
<p class="form-input-hint">A descriptive name to identify the purpose of the token</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="token-name">Token name</label>
|
||||
<input type="text"
|
||||
class="form-input"
|
||||
id="token-name"
|
||||
name="name"
|
||||
placeholder="e.g., Browser Extension, Mobile App"
|
||||
value="API Token"
|
||||
maxlength="128">
|
||||
<p class="form-input-hint">A descriptive name to identify the purpose of the token</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer d-flex justify-between">
|
||||
<a class="btn btn-wide"
|
||||
href="{% url 'linkding:settings.integrations' %}"
|
||||
data-turbo-frame="api-modal">Cancel</a>
|
||||
<a class="btn btn-wide" data-close-modal>Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Create Token</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user