Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion application/single_app/static/js/admin/admin_agents.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@
async function openAgentModal(agent = null) {

const modalEl = document.getElementById('agentModal');
if (!modalEl) return alert('Agent modal not found.');
if (!modalEl) return showToast('Agent modal not found.', 'danger');

Check warning on line 143 in application/single_app/static/js/admin/admin_agents.js

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
const modal = bootstrap.Modal.getOrCreateInstance(modalEl);

// Only call showModal; instance is created once globally
Expand Down
2 changes: 1 addition & 1 deletion application/single_app/static/js/admin/admin_plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function openPluginModal(plugin = null) {
// Set up save handler
setupSaveHandler(plugin, modal);
} else {
alert('Action modal not available. Please refresh the page.');
showToast('Action modal not available. Please refresh the page.', 'warning');
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function openPluginModal(plugin = null) {
// Set up save handler
setupSaveHandler(plugin, modal);
} else {
alert('Action modal not available. Please refresh the page.');
showToast('Action modal not available. Please refresh the page.', 'warning');
}
}

Expand Down
20 changes: 11 additions & 9 deletions application/single_app/static/js/admin/admin_settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -5405,7 +5405,6 @@
renderEmbeddingModels();
updateEmbeddingHiddenInput();
markFormAsModified(); // mark form as modified
//alert(`Selected embedding model: ${deploymentName}`);
};

function updateEmbeddingHiddenInput() {
Expand Down Expand Up @@ -5453,7 +5452,6 @@
renderImageModels();
updateImageHiddenInput();
markFormAsModified(); // mark form as modified
// alert(`Selected image model: ${deploymentName}`);
};

function updateImageHiddenInput() {
Expand Down Expand Up @@ -5680,7 +5678,7 @@

// Basic validation
if (!newLabel) {
alert('Label cannot be empty.');
showToast('Label cannot be empty.', 'warning');

Check warning on line 5681 in application/single_app/static/js/admin/admin_settings.js

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains dynamic execution, persistence, or system access marker. Recommendation%3A Do not execute changed lifecycle scripts or installers while this finding is unresolved.
labelInput?.focus();
return;
}
Expand Down Expand Up @@ -6124,13 +6122,13 @@

// Validation
if (!label) {
alert('Please enter a label for the link.');
showToast('Please enter a label for the link.', 'warning');
labelInput.focus();
return;
}

if (!url) {
alert('Please enter a URL for the link.');
showToast('Please enter a URL for the link.', 'warning');
urlInput.focus();
return;
}
Expand All @@ -6139,7 +6137,7 @@
try {
new URL(url);
} catch (e) {
alert('Please enter a valid URL (e.g., https://example.com).');
showToast('Please enter a valid URL (e.g., https://example.com).', 'warning');

Check warning on line 6140 in application/single_app/static/js/admin/admin_settings.js

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains external connection or remote asset marker. Recommendation%3A Review whether changed code can send prompts, files, credentials, cookies, settings, logs, or user data to a new sink.
urlInput.focus();
return;
}
Expand Down Expand Up @@ -9313,16 +9311,20 @@
})
.then(resp => {
if (resp.status === 'success') {
alert(resp.message || `Successfully ${action === 'create' ? 'created' : 'fixed'} ${type} index!`);
showToast(
resp.message || `Successfully ${action === 'create' ? 'created' : 'fixed'} ${type} index!`,
'success',
{ persist: true }
);
window.location.reload();
} else {
alert(`Failed to ${action} ${type} index: ${resp.error}`);
showToast(`Failed to ${action} ${type} index: ${resp.error}`, 'danger');
fixBtn.disabled = false;
fixBtn.textContent = `${action === 'create' ? 'Create' : 'Fix'} ${type} Index`;
}
})
.catch(err => {
alert(`Error ${action === 'create' ? 'creating' : 'fixing'} ${type} index: ${err.message || err}`);
showToast(`Error ${action === 'create' ? 'creating' : 'fixing'} ${type} index: ${err.message || err}`, 'danger');
fixBtn.disabled = false;
fixBtn.textContent = `${action === 'create' ? 'Create' : 'Fix'} ${type} Index`;
});
Expand Down
114 changes: 5 additions & 109 deletions application/single_app/static/js/chat/chat-toast.js
Original file line number Diff line number Diff line change
@@ -1,113 +1,9 @@
// chat-toast.js

const preferredToastContainerSelector = '[data-toast-container="preferred"]';
const syncedToastContainers = new WeakSet();
export function showToast(message, variant = 'danger', options = {}) {
if (typeof window.showToast !== 'function') {
throw new Error('Global toast utility is unavailable.');
}

function getToastContainer() {
return document.querySelector(preferredToastContainerSelector) || document.getElementById("toast-container");
}

function getToastAnchor(container) {
const anchorId = container?.dataset.toastAnchor;
if (!anchorId) {
return null;
}

return document.getElementById(anchorId);
}

function syncToastContainerPosition(container) {
if (!container) {
return;
}

if (!container.dataset.toastAnchor) {
return;
}

const defaultTop = container.dataset.toastDefaultTop || "16px";
const anchor = getToastAnchor(container);

if (!anchor || anchor.offsetParent === null || !anchor.classList.contains("is-ready")) {
container.style.top = defaultTop;
return;
}

const gap = Number.parseInt(container.dataset.toastGap || "12", 10);
const containerPaddingTop = Number.parseFloat(window.getComputedStyle(container).paddingTop || "0");
const anchorRect = anchor.getBoundingClientRect();
const anchoredTop = Math.max(16, Math.ceil(anchorRect.bottom + gap - containerPaddingTop));

container.style.top = `${anchoredTop}px`;
}

function ensureToastContainerAnchorSync(container) {
if (!container || !container.dataset.toastAnchor || syncedToastContainers.has(container)) {
return;
}

syncedToastContainers.add(container);

const reposition = () => syncToastContainerPosition(container);
const anchor = getToastAnchor(container);

window.addEventListener("resize", reposition);

if (window.ResizeObserver && anchor) {
const resizeObserver = new ResizeObserver(reposition);
resizeObserver.observe(anchor);
}

if (window.MutationObserver && anchor) {
const mutationObserver = new MutationObserver(reposition);
mutationObserver.observe(anchor, {
attributes: true,
attributeFilter: ["class", "style"],
});
}

reposition();
}

export function showToast(message, variant = "danger") {
const container = getToastContainer();
if (!container) {
return;
}

ensureToastContainerAnchorSync(container);
syncToastContainerPosition(container);

const id = "toast-" + Date.now();
const toastEl = document.createElement("div");
toastEl.id = id;
toastEl.className = `toast align-items-center text-bg-${variant}`;
toastEl.setAttribute("role", "alert");
toastEl.setAttribute("aria-live", "assertive");
toastEl.setAttribute("aria-atomic", "true");

const contentEl = document.createElement("div");
contentEl.className = "d-flex";

const bodyEl = document.createElement("div");
bodyEl.className = "toast-body";
if (message instanceof Node) {
bodyEl.textContent = message.textContent || "";
} else {
bodyEl.textContent = String(message ?? "");
}

const closeButtonEl = document.createElement("button");
closeButtonEl.type = "button";
closeButtonEl.className = "btn-close btn-close-white me-2 m-auto";
closeButtonEl.setAttribute("data-bs-dismiss", "toast");
closeButtonEl.setAttribute("aria-label", "Close");

contentEl.appendChild(bodyEl);
contentEl.appendChild(closeButtonEl);
toastEl.appendChild(contentEl);
container.appendChild(toastEl);

const bsToast = new bootstrap.Toast(toastEl, { delay: 5000 });
bsToast.show();
window.showToast(message, variant, options);
}
Loading
Loading