mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-08 05:39:13 +00:00
Construct config page elements on Web via DOM scripting.
Minimize isage of innerHTML to prevent DOM clobbering and unintended escape by user Input
This commit is contained in:
@@ -242,18 +242,25 @@
|
|||||||
<script>
|
<script>
|
||||||
async function openChat(agentSlug) {
|
async function openChat(agentSlug) {
|
||||||
// Create a loading animation
|
// Create a loading animation
|
||||||
let loading = document.createElement("div");
|
let loadingTextEl = document.createElement("div");
|
||||||
loading.innerHTML = '<div>Booting your agent...</div><span class="loader"></span>';
|
loadingTextEl.textContent = 'Booting your agent...';
|
||||||
loading.style.position = "fixed";
|
|
||||||
loading.style.top = "0";
|
let loadingAnimationEl = document.createElement("span");
|
||||||
loading.style.right = "0";
|
loadingAnimationEl.className = "loader";
|
||||||
loading.style.bottom = "0";
|
|
||||||
loading.style.left = "0";
|
let loadingEl = document.createElement("div");
|
||||||
loading.style.display = "flex";
|
loadingEl.style.position = "fixed";
|
||||||
loading.style.justifyContent = "center";
|
loadingEl.style.top = "0";
|
||||||
loading.style.alignItems = "center";
|
loadingEl.style.right = "0";
|
||||||
loading.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; // Semi-transparent black
|
loadingEl.style.bottom = "0";
|
||||||
document.body.appendChild(loading);
|
loadingEl.style.left = "0";
|
||||||
|
loadingEl.style.display = "flex";
|
||||||
|
loadingEl.style.justifyContent = "center";
|
||||||
|
loadingEl.style.alignItems = "center";
|
||||||
|
loadingEl.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; // Semi-transparent black
|
||||||
|
|
||||||
|
loadingEl.append(loadingTextEl, loadingAnimationEl);
|
||||||
|
document.body.appendChild(loadingEl);
|
||||||
|
|
||||||
let response = await fetch(`/api/chat/sessions?agent_slug=${agentSlug}`, { method: "POST" });
|
let response = await fetch(`/api/chat/sessions?agent_slug=${agentSlug}`, { method: "POST" });
|
||||||
let data = await response.json();
|
let data = await response.json();
|
||||||
|
|||||||
@@ -149,7 +149,6 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
}
|
}
|
||||||
|
|
||||||
function generateOnlineReference(reference, index) {
|
function generateOnlineReference(reference, index) {
|
||||||
|
|
||||||
// Generate HTML for Chat Reference
|
// Generate HTML for Chat Reference
|
||||||
let title = reference.title || reference.link;
|
let title = reference.title || reference.link;
|
||||||
let link = reference.link;
|
let link = reference.link;
|
||||||
@@ -170,7 +169,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
linkElement.textContent = title;
|
linkElement.textContent = title;
|
||||||
|
|
||||||
let referenceButton = document.createElement('button');
|
let referenceButton = document.createElement('button');
|
||||||
referenceButton.innerHTML = linkElement.outerHTML;
|
referenceButton.appendChild(linkElement);
|
||||||
referenceButton.id = `ref-${index}`;
|
referenceButton.id = `ref-${index}`;
|
||||||
referenceButton.classList.add("reference-button");
|
referenceButton.classList.add("reference-button");
|
||||||
referenceButton.classList.add("collapsed");
|
referenceButton.classList.add("collapsed");
|
||||||
@@ -181,11 +180,12 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
if (this.classList.contains("collapsed")) {
|
if (this.classList.contains("collapsed")) {
|
||||||
this.classList.remove("collapsed");
|
this.classList.remove("collapsed");
|
||||||
this.classList.add("expanded");
|
this.classList.add("expanded");
|
||||||
this.innerHTML = linkElement.outerHTML + `<br><br>${question + snippet}`;
|
this.innerHTML = `${linkElement.outerHTML}<br><br>${question}${snippet}`;
|
||||||
} else {
|
} else {
|
||||||
this.classList.add("collapsed");
|
this.classList.add("collapsed");
|
||||||
this.classList.remove("expanded");
|
this.classList.remove("expanded");
|
||||||
this.innerHTML = linkElement.outerHTML;
|
this.innerHTML = "";
|
||||||
|
this.appendChild(linkElement);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -578,7 +578,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
|
|
||||||
let referenceExpandButton = document.createElement('button');
|
let referenceExpandButton = document.createElement('button');
|
||||||
referenceExpandButton.classList.add("reference-expand-button");
|
referenceExpandButton.classList.add("reference-expand-button");
|
||||||
referenceExpandButton.innerHTML = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
referenceExpandButton.textContent = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
||||||
|
|
||||||
referenceExpandButton.addEventListener('click', function() {
|
referenceExpandButton.addEventListener('click', function() {
|
||||||
if (referenceSection.classList.contains("collapsed")) {
|
if (referenceSection.classList.contains("collapsed")) {
|
||||||
@@ -888,7 +888,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
if (overlayText == null) {
|
if (overlayText == null) {
|
||||||
dropzone.classList.add('dragover');
|
dropzone.classList.add('dragover');
|
||||||
var overlayText = document.createElement("div");
|
var overlayText = document.createElement("div");
|
||||||
overlayText.innerHTML = "Select file(s) or drag + drop it here to share it with Khoj";
|
overlayText.textContent = "Select file(s) or drag + drop it here to share it with Khoj";
|
||||||
overlayText.className = "dropzone-overlay";
|
overlayText.className = "dropzone-overlay";
|
||||||
overlayText.id = "dropzone-overlay";
|
overlayText.id = "dropzone-overlay";
|
||||||
dropzone.appendChild(overlayText);
|
dropzone.appendChild(overlayText);
|
||||||
@@ -949,7 +949,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
if (overlayText != null) {
|
if (overlayText != null) {
|
||||||
// Display loading spinner
|
// Display loading spinner
|
||||||
var loadingSpinner = document.createElement("div");
|
var loadingSpinner = document.createElement("div");
|
||||||
overlayText.innerHTML = "Uploading file(s) for indexing";
|
overlayText.textContent = "Uploading file(s) for indexing";
|
||||||
loadingSpinner.className = "spinner";
|
loadingSpinner.className = "spinner";
|
||||||
overlayText.appendChild(loadingSpinner);
|
overlayText.appendChild(loadingSpinner);
|
||||||
}
|
}
|
||||||
@@ -1042,7 +1042,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
|
|
||||||
if (overlayText == null) {
|
if (overlayText == null) {
|
||||||
var overlayText = document.createElement("div");
|
var overlayText = document.createElement("div");
|
||||||
overlayText.innerHTML = "Drop file to share it with Khoj";
|
overlayText.textContent = "Drop file to share it with Khoj";
|
||||||
overlayText.className = "dropzone-overlay";
|
overlayText.className = "dropzone-overlay";
|
||||||
overlayText.id = "dropzone-overlay";
|
overlayText.id = "dropzone-overlay";
|
||||||
this.appendChild(overlayText);
|
this.appendChild(overlayText);
|
||||||
@@ -1179,11 +1179,15 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
websocket.onclose = function(event) {
|
websocket.onclose = function(event) {
|
||||||
websocket = null;
|
websocket = null;
|
||||||
console.log("WebSocket is closed now.");
|
console.log("WebSocket is closed now.");
|
||||||
|
let setupWebSocketButton = document.createElement("button");
|
||||||
|
setupWebSocketButton.textContent = "Reconnect to Server";
|
||||||
|
setupWebSocketButton.onclick = setupWebSocket;
|
||||||
let statusDotIcon = document.getElementById("connection-status-icon");
|
let statusDotIcon = document.getElementById("connection-status-icon");
|
||||||
statusDotIcon.style.backgroundColor = "red";
|
statusDotIcon.style.backgroundColor = "red";
|
||||||
let statusDotText = document.getElementById("connection-status-text");
|
let statusDotText = document.getElementById("connection-status-text");
|
||||||
|
statusDotText.innerHTML = "";
|
||||||
statusDotText.style.marginTop = "5px";
|
statusDotText.style.marginTop = "5px";
|
||||||
statusDotText.innerHTML = '<button onclick="setupWebSocket()">Reconnect to Server</button>';
|
statusDotText.appendChild(setupWebSocketButton);
|
||||||
}
|
}
|
||||||
websocket.onerror = function(event) {
|
websocket.onerror = function(event) {
|
||||||
console.log("WebSocket error observed:", event);
|
console.log("WebSocket error observed:", event);
|
||||||
@@ -1434,7 +1438,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
questionStarterSuggestions.innerHTML = "";
|
questionStarterSuggestions.innerHTML = "";
|
||||||
data.forEach((questionStarter) => {
|
data.forEach((questionStarter) => {
|
||||||
let questionStarterButton = document.createElement('button');
|
let questionStarterButton = document.createElement('button');
|
||||||
questionStarterButton.innerHTML = questionStarter;
|
questionStarterButton.textContent = questionStarter;
|
||||||
questionStarterButton.classList.add("question-starter");
|
questionStarterButton.classList.add("question-starter");
|
||||||
questionStarterButton.addEventListener('click', function() {
|
questionStarterButton.addEventListener('click', function() {
|
||||||
questionStarterSuggestions.style.display = "none";
|
questionStarterSuggestions.style.display = "none";
|
||||||
@@ -1606,7 +1610,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
|
|
||||||
let closeButton = document.createElement('button');
|
let closeButton = document.createElement('button');
|
||||||
closeButton.id = "close-button";
|
closeButton.id = "close-button";
|
||||||
closeButton.innerHTML = "Close";
|
closeButton.textContent = "Close";
|
||||||
closeButton.classList.add("close-button");
|
closeButton.classList.add("close-button");
|
||||||
closeButton.addEventListener('click', function() {
|
closeButton.addEventListener('click', function() {
|
||||||
modal.remove();
|
modal.remove();
|
||||||
@@ -1660,7 +1664,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
let threeDotMenu = document.createElement('div');
|
let threeDotMenu = document.createElement('div');
|
||||||
threeDotMenu.classList.add("three-dot-menu");
|
threeDotMenu.classList.add("three-dot-menu");
|
||||||
let threeDotMenuButton = document.createElement('button');
|
let threeDotMenuButton = document.createElement('button');
|
||||||
threeDotMenuButton.innerHTML = "⋮";
|
threeDotMenuButton.textContent = "⋮";
|
||||||
threeDotMenuButton.classList.add("three-dot-menu-button");
|
threeDotMenuButton.classList.add("three-dot-menu-button");
|
||||||
threeDotMenuButton.addEventListener('click', function(event) {
|
threeDotMenuButton.addEventListener('click', function(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -1679,7 +1683,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
conversationMenu.classList.add("conversation-menu");
|
conversationMenu.classList.add("conversation-menu");
|
||||||
|
|
||||||
let editTitleButton = document.createElement('button');
|
let editTitleButton = document.createElement('button');
|
||||||
editTitleButton.innerHTML = "Rename";
|
editTitleButton.textContent = "Rename";
|
||||||
editTitleButton.classList.add("edit-title-button");
|
editTitleButton.classList.add("edit-title-button");
|
||||||
editTitleButton.classList.add("three-dot-menu-button-item");
|
editTitleButton.classList.add("three-dot-menu-button-item");
|
||||||
editTitleButton.addEventListener('click', function(event) {
|
editTitleButton.addEventListener('click', function(event) {
|
||||||
@@ -1713,7 +1717,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
|
|
||||||
conversationTitleInputBox.appendChild(conversationTitleInput);
|
conversationTitleInputBox.appendChild(conversationTitleInput);
|
||||||
let conversationTitleInputButton = document.createElement('button');
|
let conversationTitleInputButton = document.createElement('button');
|
||||||
conversationTitleInputButton.innerHTML = "Save";
|
conversationTitleInputButton.textContent = "Save";
|
||||||
conversationTitleInputButton.classList.add("three-dot-menu-button-item");
|
conversationTitleInputButton.classList.add("three-dot-menu-button-item");
|
||||||
conversationTitleInputButton.addEventListener('click', function(event) {
|
conversationTitleInputButton.addEventListener('click', function(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -1737,7 +1741,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
threeDotMenu.appendChild(conversationMenu);
|
threeDotMenu.appendChild(conversationMenu);
|
||||||
|
|
||||||
let shareButton = document.createElement('button');
|
let shareButton = document.createElement('button');
|
||||||
shareButton.innerHTML = "Share";
|
shareButton.textContent = "Share";
|
||||||
shareButton.type = "button";
|
shareButton.type = "button";
|
||||||
shareButton.classList.add("share-conversation-button");
|
shareButton.classList.add("share-conversation-button");
|
||||||
shareButton.classList.add("three-dot-menu-button-item");
|
shareButton.classList.add("three-dot-menu-button-item");
|
||||||
@@ -1804,7 +1808,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
|
|
||||||
let deleteButton = document.createElement('button');
|
let deleteButton = document.createElement('button');
|
||||||
deleteButton.type = "button";
|
deleteButton.type = "button";
|
||||||
deleteButton.innerHTML = "Delete";
|
deleteButton.textContent = "Delete";
|
||||||
deleteButton.classList.add("delete-conversation-button");
|
deleteButton.classList.add("delete-conversation-button");
|
||||||
deleteButton.classList.add("three-dot-menu-button-item");
|
deleteButton.classList.add("three-dot-menu-button-item");
|
||||||
deleteButton.addEventListener('click', function(event) {
|
deleteButton.addEventListener('click', function(event) {
|
||||||
@@ -1968,12 +1972,16 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
}
|
}
|
||||||
allFiles = data;
|
allFiles = data;
|
||||||
var nofilesmessage = document.getElementsByClassName("no-files-message")[0];
|
var nofilesmessage = document.getElementsByClassName("no-files-message")[0];
|
||||||
|
nofilesmessage.innerHTML = "";
|
||||||
if(allFiles.length === 0){
|
if(allFiles.length === 0){
|
||||||
nofilesmessage.innerHTML = `<a class="inline-chat-link" href="https://docs.khoj.dev/category/clients/">How to upload files</a>`;
|
let inlineChatLinkEl = document.createElement('a');
|
||||||
|
inlineChatLinkEl.className = "inline-chat-link";
|
||||||
|
inlineChatLinkEl.href = "https://docs.khoj.dev/category/clients/";
|
||||||
|
inlineChatLinkEl.textContent = "How to upload files";
|
||||||
|
nofilesmessage.appendChild(inlineChatLinkEl);
|
||||||
document.getElementsByClassName("file-toggle-button")[0].style.display = "none";
|
document.getElementsByClassName("file-toggle-button")[0].style.display = "none";
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
nofilesmessage.innerHTML = "";
|
|
||||||
document.getElementsByClassName("file-toggle-button")[0].style.display = "block";
|
document.getElementsByClassName("file-toggle-button")[0].style.display = "block";
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -163,10 +163,6 @@
|
|||||||
<div class="section-cards">
|
<div class="section-cards">
|
||||||
<div class="finalize-buttons">
|
<div class="finalize-buttons">
|
||||||
<button id="sync" type="submit" title="Regenerate index from scratch for Notion, GitHub configuration" style="display: flex; justify-content: center;">
|
<button id="sync" type="submit" title="Regenerate index from scratch for Notion, GitHub configuration" style="display: flex; justify-content: center;">
|
||||||
<img class="card-icon" src="/static/assets/icons/sync.svg" alt="Sync">
|
|
||||||
<h3 class="card-title">
|
|
||||||
Sync
|
|
||||||
</h3>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -408,7 +404,8 @@
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.status == "ok") {
|
if (data.status == "ok") {
|
||||||
let notificationBanner = document.getElementById("notification-banner");
|
let notificationBanner = document.getElementById("notification-banner");
|
||||||
notificationBanner.innerHTML = "Profile name has been updated!";
|
notificationBanner.innerHTML = "";
|
||||||
|
notificationBanner.textContent = "Profile name has been updated!";
|
||||||
notificationBanner.style.display = "block";
|
notificationBanner.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
notificationBanner.style.display = "none";
|
notificationBanner.style.display = "none";
|
||||||
@@ -420,8 +417,9 @@
|
|||||||
function updateVoiceModel() {
|
function updateVoiceModel() {
|
||||||
const voiceModel = document.getElementById("voice-models").value;
|
const voiceModel = document.getElementById("voice-models").value;
|
||||||
const saveVoiceModelButton = document.getElementById("save-voice-model");
|
const saveVoiceModelButton = document.getElementById("save-voice-model");
|
||||||
|
saveVoiceModelButton.innerHTML = "";
|
||||||
saveVoiceModelButton.disabled = true;
|
saveVoiceModelButton.disabled = true;
|
||||||
saveVoiceModelButton.innerHTML = "Saving...";
|
saveVoiceModelButton.textContent = "Saving...";
|
||||||
|
|
||||||
fetch('/api/config/data/voice/model?id=' + voiceModel, {
|
fetch('/api/config/data/voice/model?id=' + voiceModel, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -432,18 +430,19 @@
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.status == "ok") {
|
if (data.status == "ok") {
|
||||||
saveVoiceModelButton.innerHTML = "Save";
|
saveVoiceModelButton.textContent = "Save";
|
||||||
saveVoiceModelButton.disabled = false;
|
saveVoiceModelButton.disabled = false;
|
||||||
|
|
||||||
let notificationBanner = document.getElementById("notification-banner");
|
let notificationBanner = document.getElementById("notification-banner");
|
||||||
notificationBanner.innerHTML = "Voice model has been updated!";
|
notificationBanner.innerHTML = "";
|
||||||
|
notificationBanner.textContent = "Voice model has been updated!";
|
||||||
notificationBanner.style.display = "block";
|
notificationBanner.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
notificationBanner.style.display = "none";
|
notificationBanner.style.display = "none";
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
saveVoiceModelButton.innerHTML = "Error";
|
saveVoiceModelButton.textContent = "Error";
|
||||||
saveVoiceModelButton.disabled = false;
|
saveVoiceModelButton.disabled = false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -453,7 +452,8 @@
|
|||||||
const chatModel = document.getElementById("chat-models").value;
|
const chatModel = document.getElementById("chat-models").value;
|
||||||
const saveModelButton = document.getElementById("save-chat-model");
|
const saveModelButton = document.getElementById("save-chat-model");
|
||||||
saveModelButton.disabled = true;
|
saveModelButton.disabled = true;
|
||||||
saveModelButton.innerHTML = "Saving...";
|
saveModelButton.innerHTML = "";
|
||||||
|
saveModelButton.textContent = "Saving...";
|
||||||
|
|
||||||
fetch('/api/config/data/conversation/model?id=' + chatModel, {
|
fetch('/api/config/data/conversation/model?id=' + chatModel, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -464,18 +464,19 @@
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.status == "ok") {
|
if (data.status == "ok") {
|
||||||
saveModelButton.innerHTML = "Save";
|
saveModelButton.textContent = "Save";
|
||||||
saveModelButton.disabled = false;
|
saveModelButton.disabled = false;
|
||||||
|
|
||||||
let notificationBanner = document.getElementById("notification-banner");
|
let notificationBanner = document.getElementById("notification-banner");
|
||||||
notificationBanner.innerHTML = "Conversation model has been updated!";
|
notificationBanner.innerHTML = "";
|
||||||
|
notificationBanner.textContent = "Conversation model has been updated!";
|
||||||
notificationBanner.style.display = "block";
|
notificationBanner.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
notificationBanner.style.display = "none";
|
notificationBanner.style.display = "none";
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
saveModelButton.innerHTML = "Error";
|
saveModelButton.textContent = "Error";
|
||||||
saveModelButton.disabled = false;
|
saveModelButton.disabled = false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -489,8 +490,9 @@
|
|||||||
|
|
||||||
const searchModel = document.getElementById("search-models").value;
|
const searchModel = document.getElementById("search-models").value;
|
||||||
const saveSearchModelButton = document.getElementById("save-search-model");
|
const saveSearchModelButton = document.getElementById("save-search-model");
|
||||||
|
saveSearchModelButton.innerHTML = "";
|
||||||
saveSearchModelButton.disabled = true;
|
saveSearchModelButton.disabled = true;
|
||||||
saveSearchModelButton.innerHTML = "Saving...";
|
saveSearchModelButton.textContent = "Saving...";
|
||||||
|
|
||||||
fetch('/api/config/data/search/model?id=' + searchModel, {
|
fetch('/api/config/data/search/model?id=' + searchModel, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -501,15 +503,16 @@
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.status == "ok") {
|
if (data.status == "ok") {
|
||||||
saveSearchModelButton.innerHTML = "Save";
|
saveSearchModelButton.textContent = "Save";
|
||||||
saveSearchModelButton.disabled = false;
|
saveSearchModelButton.disabled = false;
|
||||||
} else {
|
} else {
|
||||||
saveSearchModelButton.innerHTML = "Error";
|
saveSearchModelButton.textContent = "Error";
|
||||||
saveSearchModelButton.disabled = false;
|
saveSearchModelButton.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let notificationBanner = document.getElementById("notification-banner");
|
let notificationBanner = document.getElementById("notification-banner");
|
||||||
notificationBanner.innerHTML = "Khoj can now better understand the language of your content! Manually sync your data from one of the Khoj clients to update your knowledge base.";
|
notificationBanner.innerHTML = "";
|
||||||
|
notificationBanner.textContent = "Khoj can now better understand the language of your content! Manually sync your data from one of the Khoj clients to update your knowledge base.";
|
||||||
notificationBanner.style.display = "block";
|
notificationBanner.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
notificationBanner.style.display = "none";
|
notificationBanner.style.display = "none";
|
||||||
@@ -607,23 +610,38 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var sync = document.getElementById("sync");
|
function populateSyncButton() {
|
||||||
sync.addEventListener("click", function(event) {
|
let syncIconEl = document.createElement("img");
|
||||||
|
syncIconEl.className = "card-icon";
|
||||||
|
syncIconEl.src = "/static/assets/icons/sync.svg";
|
||||||
|
syncIconEl.alt = "Sync";
|
||||||
|
|
||||||
|
let syncButtonTitleEl = document.createElement("h3");
|
||||||
|
syncButtonTitleEl.className = "card-title";
|
||||||
|
syncButtonTitleEl.textContent = "Sync";
|
||||||
|
|
||||||
|
return [syncButtonTitleEl, syncIconEl];
|
||||||
|
}
|
||||||
|
|
||||||
|
var syncButtonEl = document.getElementById("sync");
|
||||||
|
syncButtonEl.innerHTML = "";
|
||||||
|
syncButtonEl.append(...populateSyncButton());
|
||||||
|
syncButtonEl.addEventListener("click", function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
updateIndex(
|
updateIndex(
|
||||||
force=true,
|
force=true,
|
||||||
successText="Synced!",
|
successText="Synced!",
|
||||||
errorText="Unable to sync. Raise issue on Khoj <a href='https://github.com/khoj-ai/khoj/issues'>Github</a> or <a href='https://discord.gg/BDgyabRM6e'>Discord</a>.",
|
errorText="Unable to sync. Raise issue on Khoj <a href='https://github.com/khoj-ai/khoj/issues'>Github</a> or <a href='https://discord.gg/BDgyabRM6e'>Discord</a>.",
|
||||||
button=sync,
|
button=syncButtonEl,
|
||||||
loadingText="Syncing...",
|
loadingText="Syncing...",
|
||||||
emoji="");
|
emoji="");
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateIndex(force, successText, errorText, button, loadingText, emoji) {
|
function updateIndex(force, successText, errorText, button, loadingText, emoji) {
|
||||||
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
|
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
|
||||||
const original_html = button.innerHTML;
|
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
button.innerHTML = emoji + " " + loadingText;
|
button.innerHTML = ""
|
||||||
|
button.textContent = emoji + " " + loadingText;
|
||||||
fetch('/api/update?&client=web&force=' + force, {
|
fetch('/api/update?&client=web&force=' + force, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -640,19 +658,19 @@
|
|||||||
document.getElementById("status").style.display = "none";
|
document.getElementById("status").style.display = "none";
|
||||||
|
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
button.innerHTML = `✅ ${successText}`;
|
button.textContent = `✅ ${successText}`;
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
button.innerHTML = original_html;
|
button.append(...populateSyncButton());
|
||||||
}, 2000);
|
}, 2000);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
document.getElementById("status").innerHTML = emoji + " " + errorText
|
document.getElementById("status").textContent = emoji + " " + errorText
|
||||||
document.getElementById("status").style.display = "block";
|
document.getElementById("status").style.display = "block";
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
button.innerHTML = '⚠️ Unsuccessful';
|
button.textContent = '⚠️ Unsuccessful';
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
button.innerHTML = original_html;
|
button.append(...populateSyncButton());
|
||||||
}, 2000);
|
}, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -687,7 +705,7 @@
|
|||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(tokenObj => {
|
.then(tokenObj => {
|
||||||
apiKeyList.innerHTML += generateTokenRow(tokenObj);
|
apiKeyList.appendChild(generateTokenRow(tokenObj));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,16 +714,16 @@
|
|||||||
navigator.clipboard.writeText(token);
|
navigator.clipboard.writeText(token);
|
||||||
// Flash the API key copied icon
|
// Flash the API key copied icon
|
||||||
const apiKeyColumn = document.getElementById(`api-key-${token}`);
|
const apiKeyColumn = document.getElementById(`api-key-${token}`);
|
||||||
const original_html = apiKeyColumn.innerHTML;
|
const original_text = apiKeyColumn.textContent;
|
||||||
const copyApiKeyButton = document.getElementById(`api-key-copy-${token}`);
|
const copyApiKeyButton = document.getElementById(`api-key-copy-${token}`);
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
copyApiKeyButton.src = "/static/assets/icons/copy-button-success.svg";
|
copyApiKeyButton.src = "/static/assets/icons/copy-button-success.svg";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
copyApiKeyButton.src = "/static/assets/icons/copy-button.svg";
|
copyApiKeyButton.src = "/static/assets/icons/copy-button.svg";
|
||||||
}, 1000);
|
}, 1000);
|
||||||
apiKeyColumn.innerHTML = "✅ Copied!";
|
apiKeyColumn.textContent = "✅ Copied!";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
apiKeyColumn.innerHTML = original_html;
|
apiKeyColumn.textContent = original_text;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
@@ -728,16 +746,50 @@
|
|||||||
let tokenName = tokenObj.name;
|
let tokenName = tokenObj.name;
|
||||||
let truncatedToken = token.slice(0, 4) + "..." + token.slice(-4);
|
let truncatedToken = token.slice(0, 4) + "..." + token.slice(-4);
|
||||||
let tokenId = `${tokenName}-${truncatedToken}`;
|
let tokenId = `${tokenName}-${truncatedToken}`;
|
||||||
return `
|
|
||||||
<tr id="api-key-item-${token}">
|
// Create API Key Row
|
||||||
<td><b>${tokenName}</b></td>
|
let apiKeyItemEl = document.createElement("tr");
|
||||||
<td id="api-key-${token}">${truncatedToken}</td>
|
apiKeyItemEl.id = `api-key-item-${token}`;
|
||||||
<td>
|
|
||||||
<img id="api-key-copy-${token}" onclick="copyAPIKey('${token}')" class="configured-icon api-key-action enabled" src="/static/assets/icons/copy-button.svg" alt="Copy API Key" title="Copy API Key">
|
// API Key Name Row
|
||||||
<img id="api-key-delete-${token}" onclick="deleteAPIKey('${token}')" class="configured-icon api-key-action enabled" src="/static/assets/icons/delete.svg" alt="Delete API Key" title="Delete API Key">
|
let apiKeyNameEl = document.createElement("td");
|
||||||
</td>
|
let apiKeyNameTextEl = document.createElement("b");
|
||||||
</tr>
|
apiKeyNameTextEl.textContent = tokenName;
|
||||||
`;
|
|
||||||
|
// API Key Token Row
|
||||||
|
let apiKeyTokenEl = document.createElement("td");
|
||||||
|
apiKeyTokenEl.id = `api-key-${token}`;
|
||||||
|
apiKeyTokenEl.textContent = truncatedToken;
|
||||||
|
|
||||||
|
// API Key Actions Row
|
||||||
|
let apiKeyActionsEl = document.createElement("td");
|
||||||
|
// Copy API Key Button
|
||||||
|
let copyApiKeyButtonEl = document.createElement("img");
|
||||||
|
copyApiKeyButtonEl.id = `api-key-copy-${token}`;
|
||||||
|
copyApiKeyButtonEl.className = "configured-icon api-key-action enabled";
|
||||||
|
copyApiKeyButtonEl.src = "/static/assets/icons/copy-button.svg";
|
||||||
|
copyApiKeyButtonEl.alt = "Copy API Key";
|
||||||
|
copyApiKeyButtonEl.title = "Copy API Key";
|
||||||
|
copyApiKeyButtonEl.onclick = function() {
|
||||||
|
copyAPIKey(token);
|
||||||
|
};
|
||||||
|
// Delete API Key Button
|
||||||
|
let deleteApiKeyButtonEl = document.createElement("img");
|
||||||
|
deleteApiKeyButtonEl.id = `api-key-delete-${token}`;
|
||||||
|
deleteApiKeyButtonEl.className = "configured-icon api-key-action enabled";
|
||||||
|
deleteApiKeyButtonEl.src = "/static/assets/icons/delete.svg";
|
||||||
|
deleteApiKeyButtonEl.alt = "Delete API Key";
|
||||||
|
deleteApiKeyButtonEl.title = "Delete API Key";
|
||||||
|
deleteApiKeyButtonEl.onclick = function() {
|
||||||
|
deleteAPIKey(token);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Construct the API Key Row
|
||||||
|
apiKeyNameEl.append(apiKeyNameTextEl);
|
||||||
|
apiKeyActionsEl.append(copyApiKeyButtonEl, deleteApiKeyButtonEl);
|
||||||
|
apiKeyItemEl.append(apiKeyNameEl, apiKeyTokenEl, apiKeyActionsEl);
|
||||||
|
|
||||||
|
return apiKeyItemEl;
|
||||||
}
|
}
|
||||||
|
|
||||||
function listApiKeys() {
|
function listApiKeys() {
|
||||||
@@ -746,7 +798,7 @@
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(tokens => {
|
.then(tokens => {
|
||||||
if (!tokens?.length > 0) return;
|
if (!tokens?.length > 0) return;
|
||||||
apiKeyList.innerHTML = tokens?.map(generateTokenRow).join("");
|
apiKeyList.append(...tokens?.map(generateTokenRow));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,11 +806,11 @@
|
|||||||
listApiKeys();
|
listApiKeys();
|
||||||
|
|
||||||
function getIndexedDataSize() {
|
function getIndexedDataSize() {
|
||||||
document.getElementById("indexed-data-size").innerHTML = "Calculating...";
|
document.getElementById("indexed-data-size").textContent = "Calculating...";
|
||||||
fetch('/api/config/index/size')
|
fetch('/api/config/index/size')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
document.getElementById("indexed-data-size").innerHTML = data.indexed_data_size_in_mb + " MB used";
|
document.getElementById("indexed-data-size").textContent = data.indexed_data_size_in_mb + " MB used";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,7 +839,7 @@
|
|||||||
.catch(() => callback("us"))
|
.catch(() => callback("us"))
|
||||||
},
|
},
|
||||||
separateDialCode: true,
|
separateDialCode: true,
|
||||||
utilsScript: "https://cdn.jsdelivr.net/npm/intl-tel-input@18.2.1/build/js/utils.js",
|
utilsScript: "https://assets.khoj.dev/intl-tel-input/utils.js",
|
||||||
});
|
});
|
||||||
|
|
||||||
const errorMap = ["Invalid number", "Invalid country code", "Too short", "Too long", "Invalid number"];
|
const errorMap = ["Invalid number", "Invalid country code", "Too short", "Too long", "Invalid number"];
|
||||||
@@ -858,7 +910,7 @@
|
|||||||
phonenumberVerifyButton.addEventListener("click", () => {
|
phonenumberVerifyButton.addEventListener("click", () => {
|
||||||
console.log(iti.getValidationError());
|
console.log(iti.getValidationError());
|
||||||
if (iti.isValidNumber() == false) {
|
if (iti.isValidNumber() == false) {
|
||||||
phoneNumberUpdateCallback.innerHTML = "Invalid phone number: " + errorMap[iti.getValidationError()];
|
phoneNumberUpdateCallback.textContent = "Invalid phone number: " + errorMap[iti.getValidationError()];
|
||||||
phoneNumberUpdateCallback.style.display = "block";
|
phoneNumberUpdateCallback.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
phoneNumberUpdateCallback.style.display = "none";
|
phoneNumberUpdateCallback.style.display = "none";
|
||||||
@@ -875,12 +927,12 @@
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.status == "ok") {
|
if (data.status == "ok") {
|
||||||
if (isTwilioEnabled == "True" || isTwilioEnabled == "true") {
|
if (isTwilioEnabled == "True" || isTwilioEnabled == "true") {
|
||||||
phoneNumberUpdateCallback.innerHTML = "OTP sent to your phone number";
|
phoneNumberUpdateCallback.textContent = "OTP sent to your phone number";
|
||||||
phonenumberVerifyOTPButton.style.display = "block";
|
phonenumberVerifyOTPButton.style.display = "block";
|
||||||
phonenumberOTPInput.style.display = "block";
|
phonenumberOTPInput.style.display = "block";
|
||||||
} else {
|
} else {
|
||||||
phonenumberVerifiedText.style.display = "block";
|
phonenumberVerifiedText.style.display = "block";
|
||||||
phoneNumberUpdateCallback.innerHTML = "Phone number updated";
|
phoneNumberUpdateCallback.textContent = "Phone number updated";
|
||||||
phonenumberUnverifiedText.style.display = "none";
|
phonenumberUnverifiedText.style.display = "none";
|
||||||
}
|
}
|
||||||
phonenumberVerifyButton.style.display = "none";
|
phonenumberVerifyButton.style.display = "none";
|
||||||
@@ -889,7 +941,7 @@
|
|||||||
phoneNumberUpdateCallback.style.display = "none";
|
phoneNumberUpdateCallback.style.display = "none";
|
||||||
}, 5000);
|
}, 5000);
|
||||||
} else {
|
} else {
|
||||||
phoneNumberUpdateCallback.innerHTML = "Error updating phone number";
|
phoneNumberUpdateCallback.textContent = "Error updating phone number";
|
||||||
phoneNumberUpdateCallback.style.display = "block";
|
phoneNumberUpdateCallback.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
phoneNumberUpdateCallback.style.display = "none";
|
phoneNumberUpdateCallback.style.display = "none";
|
||||||
@@ -898,7 +950,7 @@
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
phoneNumberUpdateCallback.innerHTML = "Error updating phone number";
|
phoneNumberUpdateCallback.textContent = "Error updating phone number";
|
||||||
phoneNumberUpdateCallback.style.display = "block";
|
phoneNumberUpdateCallback.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
phoneNumberUpdateCallback.style.display = "none";
|
phoneNumberUpdateCallback.style.display = "none";
|
||||||
@@ -910,7 +962,7 @@
|
|||||||
phonenumberVerifyOTPButton.addEventListener("click", () => {
|
phonenumberVerifyOTPButton.addEventListener("click", () => {
|
||||||
const otp = phonenumberOTPInput.value;
|
const otp = phonenumberOTPInput.value;
|
||||||
if (otp.length != 6) {
|
if (otp.length != 6) {
|
||||||
phoneNumberUpdateCallback.innerHTML = "Your OTP should be exactly 6 digits";
|
phoneNumberUpdateCallback.textContent = "Your OTP should be exactly 6 digits";
|
||||||
phoneNumberUpdateCallback.style.display = "block";
|
phoneNumberUpdateCallback.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
phoneNumberUpdateCallback.style.display = "none";
|
phoneNumberUpdateCallback.style.display = "none";
|
||||||
@@ -927,7 +979,7 @@
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.status == "ok") {
|
if (data.status == "ok") {
|
||||||
phoneNumberUpdateCallback.innerHTML = "Phone number updated";
|
phoneNumberUpdateCallback.textContent = "Phone number updated";
|
||||||
phonenumberVerifiedText.style.display = "block";
|
phonenumberVerifiedText.style.display = "block";
|
||||||
phonenumberUnverifiedText.style.display = "none";
|
phonenumberUnverifiedText.style.display = "none";
|
||||||
phoneNumberUpdateCallback.style.display = "block";
|
phoneNumberUpdateCallback.style.display = "block";
|
||||||
@@ -939,7 +991,7 @@
|
|||||||
phoneNumberUpdateCallback.style.display = "none";
|
phoneNumberUpdateCallback.style.display = "none";
|
||||||
}, 5000);
|
}, 5000);
|
||||||
} else {
|
} else {
|
||||||
phoneNumberUpdateCallback.innerHTML = "Error updating phone number";
|
phoneNumberUpdateCallback.textContent = "Error updating phone number";
|
||||||
phoneNumberUpdateCallback.style.display = "block";
|
phoneNumberUpdateCallback.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
phoneNumberUpdateCallback.style.display = "none";
|
phoneNumberUpdateCallback.style.display = "none";
|
||||||
@@ -948,7 +1000,7 @@
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
phoneNumberUpdateCallback.innerHTML = "Error updating phone number";
|
phoneNumberUpdateCallback.textContent = "Error updating phone number";
|
||||||
phoneNumberUpdateCallback.style.display = "block";
|
phoneNumberUpdateCallback.style.display = "block";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
phoneNumberUpdateCallback.style.display = "none";
|
phoneNumberUpdateCallback.style.display = "none";
|
||||||
|
|||||||
@@ -56,7 +56,10 @@
|
|||||||
|
|
||||||
if (data.length == 0) {
|
if (data.length == 0) {
|
||||||
document.getElementById("delete-all-files").style.display = "none";
|
document.getElementById("delete-all-files").style.display = "none";
|
||||||
indexedFiles.innerHTML = "<div class='card-description'>No documents synced with Khoj</div>";
|
let noFilesElement = document.createElement("div");
|
||||||
|
noFilesElement.classList.add("card-description");
|
||||||
|
noFilesElement.textContent = "No documents synced with Khoj";
|
||||||
|
indexedFiles.appendChild(noFilesElement);
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("get-desktop-client").style.display = "none";
|
document.getElementById("get-desktop-client").style.display = "none";
|
||||||
document.getElementById("delete-all-files").style.display = "block";
|
document.getElementById("delete-all-files").style.display = "block";
|
||||||
@@ -86,14 +89,14 @@
|
|||||||
|
|
||||||
let fileNameElement = document.createElement("div");
|
let fileNameElement = document.createElement("div");
|
||||||
fileNameElement.classList.add("content-name");
|
fileNameElement.classList.add("content-name");
|
||||||
fileNameElement.innerHTML = filename;
|
fileNameElement.textContent = filename;
|
||||||
fileElement.appendChild(fileNameElement);
|
fileElement.appendChild(fileNameElement);
|
||||||
|
|
||||||
let buttonContainer = document.createElement("div");
|
let buttonContainer = document.createElement("div");
|
||||||
buttonContainer.classList.add("remove-button-container");
|
buttonContainer.classList.add("remove-button-container");
|
||||||
let removeFileButton = document.createElement("button");
|
let removeFileButton = document.createElement("button");
|
||||||
removeFileButton.classList.add("remove-file-button");
|
removeFileButton.classList.add("remove-file-button");
|
||||||
removeFileButton.innerHTML = "🗑️";
|
removeFileButton.textContent = "🗑️";
|
||||||
removeFileButton.addEventListener("click", ((filename) => {
|
removeFileButton.addEventListener("click", ((filename) => {
|
||||||
return () => {
|
return () => {
|
||||||
removeFile(filename);
|
removeFile(filename);
|
||||||
|
|||||||
@@ -70,18 +70,50 @@
|
|||||||
repo.classList.add("repo");
|
repo.classList.add("repo");
|
||||||
const id = Date.now();
|
const id = Date.now();
|
||||||
repo.id = "repo-card-" + id;
|
repo.id = "repo-card-" + id;
|
||||||
repo.innerHTML = `
|
|
||||||
<label for="repo-owner">Repository Owner</label>
|
// Create repo owner, name, branch elements
|
||||||
<input type="text" id="repo-owner" name="repo_owner">
|
let repoOwnerLabel = document.createElement("label");
|
||||||
<label for="repo-name">Repository Name</label>
|
repoOwnerLabel.textContent = "Repository Owner";
|
||||||
<input type="text" id="repo-name" name="repo_name">
|
repoOwnerLabel.for = "repo-owner";
|
||||||
<label for="repo-branch">Repository Branch</label>
|
|
||||||
<input type="text" id="repo-branch" name="repo_branch">
|
let repoOwner = document.createElement("input");
|
||||||
<button type="button"
|
repoOwner.type = "text";
|
||||||
class="remove-repo-button"
|
repoOwner.id = "repo-owner-" + id;
|
||||||
onclick="remove_repo(${id})"
|
repoOwner.name = "repo_owner";
|
||||||
id="remove-repo-button-${id}">Remove Repository</button>
|
|
||||||
`;
|
let repoNameLabel = document.createElement("label");
|
||||||
|
repoNameLabel.textContent = "Repository Name";
|
||||||
|
repoNameLabel.for = "repo-name";
|
||||||
|
|
||||||
|
let repoName = document.createElement("input");
|
||||||
|
repoName.type = "text";
|
||||||
|
repoName.id = "repo-name-" + id;
|
||||||
|
repoName.name = "repo_name";
|
||||||
|
|
||||||
|
let repoBranchLabel = document.createElement("label");
|
||||||
|
repoBranchLabel.textContent = "Repository Branch";
|
||||||
|
repoBranchLabel.for = "repo-branch";
|
||||||
|
|
||||||
|
let repoBranch = document.createElement("input");
|
||||||
|
repoBranch.type = "text";
|
||||||
|
repoBranch.id = "repo-branch-" + id;
|
||||||
|
repoBranch.name = "repo_branch";
|
||||||
|
|
||||||
|
let removeRepoButton = document.createElement("button");
|
||||||
|
removeRepoButton.type = "button";
|
||||||
|
removeRepoButton.classList.add("remove-repo-button");
|
||||||
|
removeRepoButton.onclick = function() { remove_repo(id); };
|
||||||
|
removeRepoButton.id = "remove-repo-button-" + id;
|
||||||
|
removeRepoButton.textContent = "Remove Repository";
|
||||||
|
|
||||||
|
// Append elements to repo card
|
||||||
|
repo.append(
|
||||||
|
repoOwnerLabel, repoOwner,
|
||||||
|
repoNameLabel, repoName,
|
||||||
|
repoBranchLabel, repoBranch,
|
||||||
|
removeRepoButton
|
||||||
|
);
|
||||||
|
|
||||||
document.getElementById("repositories").appendChild(repo);
|
document.getElementById("repositories").appendChild(repo);
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -95,7 +127,7 @@
|
|||||||
const pat_token = document.getElementById("pat-token").value;
|
const pat_token = document.getElementById("pat-token").value;
|
||||||
|
|
||||||
if (pat_token == "") {
|
if (pat_token == "") {
|
||||||
document.getElementById("success").innerHTML = "❌ Please enter a Personal Access Token.";
|
document.getElementById("success").textContent = "❌ Please enter a Personal Access Token.";
|
||||||
document.getElementById("success").style.display = "block";
|
document.getElementById("success").style.display = "block";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -122,14 +154,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (repos.length == 0) {
|
if (repos.length == 0) {
|
||||||
document.getElementById("success").innerHTML = "❌ Please add at least one repository.";
|
document.getElementById("success").textContent = "❌ Please add at least one repository.";
|
||||||
document.getElementById("success").style.display = "block";
|
document.getElementById("success").style.display = "block";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const submitButton = document.getElementById("submit");
|
const submitButton = document.getElementById("submit");
|
||||||
submitButton.disabled = true;
|
submitButton.disabled = true;
|
||||||
submitButton.innerHTML = "Saving...";
|
submitButton.textContent = "Saving...";
|
||||||
|
|
||||||
// Save Github config on server
|
// Save Github config on server
|
||||||
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
|
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
|
||||||
@@ -147,11 +179,11 @@
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => { data["status"] === "ok" ? data : Promise.reject(data) })
|
.then(data => { data["status"] === "ok" ? data : Promise.reject(data) })
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
document.getElementById("success").innerHTML = "⚠️ Failed to save Github settings.";
|
document.getElementById("success").textContent = "⚠️ Failed to save Github settings.";
|
||||||
document.getElementById("success").style.display = "block";
|
document.getElementById("success").style.display = "block";
|
||||||
submitButton.innerHTML = "⚠️ Failed to save settings";
|
submitButton.textContent = "⚠️ Failed to save settings";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
submitButton.innerHTML = "Save";
|
submitButton.textContent = "Save";
|
||||||
submitButton.disabled = false;
|
submitButton.disabled = false;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
return;
|
return;
|
||||||
@@ -163,18 +195,18 @@
|
|||||||
.then(data => { data["status"] == "ok" ? data : Promise.reject(data) })
|
.then(data => { data["status"] == "ok" ? data : Promise.reject(data) })
|
||||||
.then(data => {
|
.then(data => {
|
||||||
document.getElementById("success").style.display = "none";
|
document.getElementById("success").style.display = "none";
|
||||||
submitButton.innerHTML = "✅ Successfully updated";
|
submitButton.textContent = "✅ Successfully updated";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
submitButton.innerHTML = "Save";
|
submitButton.textContent = "Save";
|
||||||
submitButton.disabled = false;
|
submitButton.disabled = false;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
document.getElementById("success").innerHTML = "⚠️ Failed to save Github content.";
|
document.getElementById("success").textContent = "⚠️ Failed to save Github content.";
|
||||||
document.getElementById("success").style.display = "block";
|
document.getElementById("success").style.display = "block";
|
||||||
submitButton.innerHTML = "⚠️ Failed to save content";
|
submitButton.textContent = "⚠️ Failed to save content";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
submitButton.innerHTML = "Save";
|
submitButton.textContent = "Save";
|
||||||
submitButton.disabled = false;
|
submitButton.disabled = false;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,14 +34,14 @@
|
|||||||
const token = document.getElementById("token").value;
|
const token = document.getElementById("token").value;
|
||||||
|
|
||||||
if (token == "") {
|
if (token == "") {
|
||||||
document.getElementById("success").innerHTML = "❌ Please enter a Notion Token.";
|
document.getElementById("success").textContent = "❌ Please enter a Notion Token.";
|
||||||
document.getElementById("success").style.display = "block";
|
document.getElementById("success").style.display = "block";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const submitButton = document.getElementById("submit");
|
const submitButton = document.getElementById("submit");
|
||||||
submitButton.disabled = true;
|
submitButton.disabled = true;
|
||||||
submitButton.innerHTML = "Syncing...";
|
submitButton.textContent = "Syncing...";
|
||||||
|
|
||||||
// Save Notion config on server
|
// Save Notion config on server
|
||||||
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
|
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
|
||||||
@@ -58,11 +58,11 @@
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => { data["status"] === "ok" ? data : Promise.reject(data) })
|
.then(data => { data["status"] === "ok" ? data : Promise.reject(data) })
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
document.getElementById("success").innerHTML = "⚠️ Failed to save Notion settings.";
|
document.getElementById("success").textContent = "⚠️ Failed to save Notion settings.";
|
||||||
document.getElementById("success").style.display = "block";
|
document.getElementById("success").style.display = "block";
|
||||||
submitButton.innerHTML = "⚠️ Failed to save settings";
|
submitButton.textContent = "⚠️ Failed to save settings";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
submitButton.innerHTML = "Save";
|
submitButton.textContent = "Save";
|
||||||
submitButton.disabled = false;
|
submitButton.disabled = false;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
return;
|
return;
|
||||||
@@ -74,18 +74,18 @@
|
|||||||
.then(data => { data["status"] == "ok" ? data : Promise.reject(data) })
|
.then(data => { data["status"] == "ok" ? data : Promise.reject(data) })
|
||||||
.then(data => {
|
.then(data => {
|
||||||
document.getElementById("success").style.display = "none";
|
document.getElementById("success").style.display = "none";
|
||||||
submitButton.innerHTML = "✅ Successfully updated";
|
submitButton.textContent = "✅ Successfully updated";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
submitButton.innerHTML = "Save";
|
submitButton.textContent = "Save";
|
||||||
submitButton.disabled = false;
|
submitButton.disabled = false;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
document.getElementById("success").innerHTML = "⚠️ Failed to save Notion content.";
|
document.getElementById("success").textContent = "⚠️ Failed to save Notion content.";
|
||||||
document.getElementById("success").style.display = "block";
|
document.getElementById("success").style.display = "block";
|
||||||
submitButton.innerHTML = "⚠️ Failed to save content";
|
submitButton.textContent = "⚠️ Failed to save content";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
submitButton.innerHTML = "Save";
|
submitButton.textContent = "Save";
|
||||||
submitButton.disabled = false;
|
submitButton.disabled = false;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
linkElement.textContent = title;
|
linkElement.textContent = title;
|
||||||
|
|
||||||
let referenceButton = document.createElement('button');
|
let referenceButton = document.createElement('button');
|
||||||
referenceButton.innerHTML = linkElement.outerHTML;
|
referenceButton.appendChild(linkElement);
|
||||||
referenceButton.id = `ref-${index}`;
|
referenceButton.id = `ref-${index}`;
|
||||||
referenceButton.classList.add("reference-button");
|
referenceButton.classList.add("reference-button");
|
||||||
referenceButton.classList.add("collapsed");
|
referenceButton.classList.add("collapsed");
|
||||||
@@ -138,11 +138,12 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
if (this.classList.contains("collapsed")) {
|
if (this.classList.contains("collapsed")) {
|
||||||
this.classList.remove("collapsed");
|
this.classList.remove("collapsed");
|
||||||
this.classList.add("expanded");
|
this.classList.add("expanded");
|
||||||
this.innerHTML = linkElement.outerHTML + `<br><br>${question + snippet}`;
|
this.innerHTML = `${linkElement.outerHTML}<br><br>${question + snippet}`;
|
||||||
} else {
|
} else {
|
||||||
this.classList.add("collapsed");
|
this.classList.add("collapsed");
|
||||||
this.classList.remove("expanded");
|
this.classList.remove("expanded");
|
||||||
this.innerHTML = linkElement.outerHTML;
|
this.innerHTML = "";
|
||||||
|
this.appendChild(linkElement);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -296,7 +297,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
}
|
}
|
||||||
|
|
||||||
let expandButtonText = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
let expandButtonText = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
||||||
referenceExpandButton.innerHTML = expandButtonText;
|
referenceExpandButton.textContent = expandButtonText;
|
||||||
|
|
||||||
references.appendChild(referenceSection);
|
references.appendChild(referenceSection);
|
||||||
|
|
||||||
@@ -447,7 +448,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
|
|
||||||
let referenceExpandButton = document.createElement('button');
|
let referenceExpandButton = document.createElement('button');
|
||||||
referenceExpandButton.classList.add("reference-expand-button");
|
referenceExpandButton.classList.add("reference-expand-button");
|
||||||
referenceExpandButton.innerHTML = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
referenceExpandButton.textContent = numReferences == 1 ? "1 reference" : `${numReferences} references`;
|
||||||
|
|
||||||
referenceExpandButton.addEventListener('click', function() {
|
referenceExpandButton.addEventListener('click', function() {
|
||||||
if (referenceSection.classList.contains("collapsed")) {
|
if (referenceSection.classList.contains("collapsed")) {
|
||||||
@@ -815,7 +816,7 @@ Learn more [here](https://khoj.dev).
|
|||||||
|
|
||||||
let closeButton = document.createElement('button');
|
let closeButton = document.createElement('button');
|
||||||
closeButton.id = "close-button";
|
closeButton.id = "close-button";
|
||||||
closeButton.innerHTML = "Close";
|
closeButton.textContent = "Close";
|
||||||
closeButton.classList.add("close-button");
|
closeButton.classList.add("close-button");
|
||||||
closeButton.addEventListener('click', function() {
|
closeButton.addEventListener('click', function() {
|
||||||
modal.remove();
|
modal.remove();
|
||||||
|
|||||||
Reference in New Issue
Block a user