forked from retoor/devplacepy
feat: add admin CLI, SEO meta tags, security headers, and production Makefile targets
This commit is contained in:
@@ -8,8 +8,10 @@ class Application {
|
||||
this.initMessageSearch();
|
||||
this.initNotificationDismiss();
|
||||
this.initProfileEdit();
|
||||
this.initProjectForm();
|
||||
|
||||
this.initFormDisable();
|
||||
this.initContentRenderer();
|
||||
this.initEmojiPickers();
|
||||
}
|
||||
|
||||
loadCSS(href) {
|
||||
@@ -38,7 +40,8 @@ class Application {
|
||||
|
||||
initModals() {
|
||||
document.querySelectorAll("[data-modal]").forEach((trigger) => {
|
||||
trigger.addEventListener("click", () => {
|
||||
trigger.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
const modalId = trigger.dataset.modal;
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
@@ -53,12 +56,11 @@ class Application {
|
||||
modal.classList.remove("visible");
|
||||
}
|
||||
});
|
||||
const closeBtn = modal.querySelector(".modal-close");
|
||||
if (closeBtn) {
|
||||
modal.querySelectorAll(".modal-close").forEach((closeBtn) => {
|
||||
closeBtn.addEventListener("click", () => {
|
||||
modal.classList.remove("visible");
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -186,49 +188,38 @@ class Application {
|
||||
});
|
||||
}
|
||||
|
||||
initProjectForm() {
|
||||
const platformsInput = document.getElementById("platforms-input");
|
||||
if (!platformsInput) {
|
||||
return;
|
||||
}
|
||||
const hiddenInput = document.getElementById("platforms");
|
||||
const tagsContainer = document.getElementById("platforms-tags");
|
||||
initContentRenderer() {
|
||||
document.querySelectorAll("[data-render]").forEach((el) => {
|
||||
contentRenderer.applyTo(el);
|
||||
});
|
||||
contentRenderer.highlightAll();
|
||||
}
|
||||
|
||||
platformsInput.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
const val = platformsInput.value.trim();
|
||||
if (!val) {
|
||||
return;
|
||||
initEmojiPickers() {
|
||||
document.querySelectorAll(".comment-form textarea, .emoji-picker-target").forEach((textarea) => {
|
||||
if (textarea.dataset.emojiInitialized) return;
|
||||
textarea.dataset.emojiInitialized = "true";
|
||||
|
||||
const btn = document.createElement("button");
|
||||
btn.type = "button";
|
||||
btn.className = "emoji-toggle-btn";
|
||||
btn.title = "Add emoji";
|
||||
btn.innerHTML = "\u{1F600}";
|
||||
|
||||
const picker = new EmojiPicker(textarea);
|
||||
btn.addEventListener("click", () => picker.toggle());
|
||||
|
||||
const parent = textarea.parentElement;
|
||||
if (parent) {
|
||||
const actions = parent.querySelector(".comment-form-actions");
|
||||
if (actions) {
|
||||
actions.insertBefore(btn, actions.firstChild);
|
||||
}
|
||||
const tag = document.createElement("span");
|
||||
tag.className = "platform-tag";
|
||||
tag.textContent = val;
|
||||
const remove = document.createElement("button");
|
||||
remove.type = "button";
|
||||
remove.textContent = "x";
|
||||
remove.style.marginLeft = "4px";
|
||||
remove.style.fontSize = "0.75rem";
|
||||
remove.style.padding = "0";
|
||||
remove.addEventListener("click", () => {
|
||||
tag.remove();
|
||||
updatePlatforms();
|
||||
});
|
||||
tag.appendChild(remove);
|
||||
tagsContainer.appendChild(tag);
|
||||
platformsInput.value = "";
|
||||
updatePlatforms();
|
||||
}
|
||||
});
|
||||
|
||||
function updatePlatforms() {
|
||||
const tags = tagsContainer.querySelectorAll(".platform-tag");
|
||||
const values = Array.from(tags).map((t) =>
|
||||
t.textContent.replace("x", "").trim()
|
||||
);
|
||||
hiddenInput.value = values.join(",");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const app = new Application();
|
||||
|
||||
Reference in New Issue
Block a user