mirror of
https://github.com/khoj-ai/khoj.git
synced 2024-11-23 23:48:56 +01:00
Simplify settings pages for configuration
- Add one-click disablement - Remove fields that probably don't need to be edited (our implementation details) - Add a green tick if a given field is configured
This commit is contained in:
parent
b6772d8fc3
commit
1a1b044d12
8 changed files with 227 additions and 31 deletions
1
src/khoj/interface/web/assets/icons/confirm-icon.svg
Normal file
1
src/khoj/interface/web/assets/icons/confirm-icon.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><defs><style>.cls-1{fill:#00a912;}.cls-1,.cls-2{fill-rule:evenodd;}.cls-2{fill:#fff;}</style></defs><title>confirm</title><path class="cls-1" d="M61.44,0A61.44,61.44,0,1,1,0,61.44,61.44,61.44,0,0,1,61.44,0Z"/><path class="cls-2" d="M42.37,51.68,53.26,62,79,35.87c2.13-2.16,3.47-3.9,6.1-1.19l8.53,8.74c2.8,2.77,2.66,4.4,0,7L58.14,85.34c-5.58,5.46-4.61,5.79-10.26.19L28,65.77c-1.18-1.28-1.05-2.57.24-3.84l9.9-10.27c1.5-1.58,2.7-1.44,4.22,0Z"/></svg>
|
After Width: | Height: | Size: 549 B |
|
@ -55,7 +55,7 @@
|
|||
gap: 8px;
|
||||
padding: 24px 16px;
|
||||
width: 320px;
|
||||
height: 160px;
|
||||
height: 180px;
|
||||
background: white;
|
||||
border: 1px solid rgb(229, 229, 229);
|
||||
border-radius: 4px;
|
||||
|
@ -114,6 +114,22 @@
|
|||
font-size: 16px;
|
||||
}
|
||||
|
||||
button.card-button {
|
||||
color: rgb(255, 136, 136);
|
||||
background: transparent;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 32px;
|
||||
text-align: right;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
img.configured-icon {
|
||||
max-width: 16px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.section-cards {
|
||||
grid-template-columns: 1fr;
|
||||
|
|
|
@ -8,62 +8,127 @@
|
|||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<img class="card-icon" src="/static/assets/icons/github.svg" alt="Github">
|
||||
<h3 class="card-title">Github</h3>
|
||||
<h3 class="card-title">
|
||||
Github
|
||||
{% if current_config.content_type.github %}
|
||||
<img id="configured-icon-github" class="configured-icon" src="/static/assets/icons/confirm-icon.svg" alt="Configured">
|
||||
{% endif %}
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
<div class="card-description-row">
|
||||
<p class="card-description">Set repositories for Khoj to index</p>
|
||||
</div>
|
||||
<div class="card-action-row">
|
||||
<a class="card-button" href="/config/content_type/github">
|
||||
Setup
|
||||
{% if current_config.content_type.github %}
|
||||
Update
|
||||
{% else %}
|
||||
Setup
|
||||
{% endif %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
|
||||
</a>
|
||||
</div>
|
||||
{% if current_config.content_type.github %}
|
||||
<div id="clear-github" class="card-action-row">
|
||||
<button class="card-button" onclick="clearContentType('github')">
|
||||
Disable
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<img class="card-icon" src="/static/assets/icons/markdown.svg" alt="markdown">
|
||||
<h3 class="card-title">Markdown</h3>
|
||||
<h3 class="card-title">
|
||||
Markdown
|
||||
{% if current_config.content_type.markdown %}
|
||||
<img id="configured-icon-markdown" class="configured-icon" src="/static/assets/icons/confirm-icon.svg" alt="Configured">
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-description-row">
|
||||
<p class="card-description">Set markdown files for Khoj to index</p>
|
||||
</div>
|
||||
<div class="card-action-row">
|
||||
<a class="card-button" href="/config/content_type/markdown">
|
||||
Setup
|
||||
{% if current_config.content_type.markdown %}
|
||||
Update
|
||||
{% else %}
|
||||
Setup
|
||||
{% endif %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
|
||||
</a>
|
||||
</div>
|
||||
{% if current_config.content_type.markdown %}
|
||||
<div id="clear-markdown" class="card-action-row">
|
||||
<button class="card-button" onclick="clearContentType('markdown')">
|
||||
Disable
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<img class="card-icon" src="/static/assets/icons/org.svg" alt="org">
|
||||
<h3 class="card-title">Org</h3>
|
||||
<h3 class="card-title">
|
||||
Org
|
||||
{% if current_config.content_type.org %}
|
||||
<img id="configured-icon-org" class="configured-icon" src="/static/assets/icons/confirm-icon.svg" alt="Configured">
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-description-row">
|
||||
<p class="card-description">Set org files for Khoj to index</p>
|
||||
</div>
|
||||
<div class="card-action-row">
|
||||
<a class="card-button" href="/config/content_type/org">
|
||||
Setup
|
||||
{% if current_config.content_type.org %}
|
||||
Update
|
||||
{% else %}
|
||||
Setup
|
||||
{% endif %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
|
||||
</a>
|
||||
</div>
|
||||
{% if current_config.content_type.org %}
|
||||
<div id="clear-org" class="card-action-row">
|
||||
<button class="card-button" onclick="clearContentType('org')">
|
||||
Disable
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<img class="card-icon" src="/static/assets/icons/pdf.svg" alt="PDF">
|
||||
<h3 class="card-title">PDF</h3>
|
||||
<h3 class="card-title">
|
||||
PDF
|
||||
{% if current_config.content_type.pdf %}
|
||||
<img id="configured-icon-pdf" class="configured-icon" src="/static/assets/icons/confirm-icon.svg" alt="Configured">
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-description-row">
|
||||
<p class="card-description">Set PDF files for Khoj to index</p>
|
||||
</div>
|
||||
<div class="card-action-row">
|
||||
<a class="card-button" href="/config/content_type/pdf">
|
||||
Setup
|
||||
{% if current_config.content_type.pdf %}
|
||||
Update
|
||||
{% else %}
|
||||
Setup
|
||||
{% endif %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
|
||||
</a>
|
||||
</div>
|
||||
{% if current_config.content_type.pdf %}
|
||||
<div id="clear-pdf" class="card-action-row">
|
||||
<button class="card-button" onclick="clearContentType('pdf')">
|
||||
Disable
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -73,26 +138,85 @@
|
|||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<img class="card-icon" src="/static/assets/icons/chat.svg" alt="Chat">
|
||||
<h3 class="card-title">Chat</h3>
|
||||
<h3 class="card-title">
|
||||
Chat
|
||||
{% if current_config.processor and current_config.processor.conversation %}
|
||||
<img id="configured-icon-conversation-processor" class="configured-icon" src="/static/assets/icons/confirm-icon.svg" alt="Configured">
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-description-row">
|
||||
<p class="card-description">Setup Khoj Chat</p>
|
||||
<p class="card-description">Setup Khoj Chat with OpenAI</p>
|
||||
</div>
|
||||
<div class="card-action-row">
|
||||
<a class="card-button" href="/config/processor/conversation">
|
||||
Setup
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
|
||||
</a>
|
||||
<a class="card-button" href="/config/processor/conversation">
|
||||
{% if current_config.processor and current_config.processor.conversation %}
|
||||
Update
|
||||
{% else %}
|
||||
Setup
|
||||
{% endif %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
|
||||
</a>
|
||||
</div>
|
||||
{% if current_config.processor and current_config.processor.conversation %}
|
||||
<div id="clear-conversation" class="card-action-row">
|
||||
<button class="card-button" onclick="clearConversationProcessor()">
|
||||
Disable
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div id="status" style="display: none;"></div>
|
||||
<button id="configure" type="submit">⚙️ Configure</button>
|
||||
<button id="reinitialize" type="submit">🔄 Reinitialize</button>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function clearContentType(content_type) {
|
||||
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
|
||||
fetch('/api/delete/config/data/content_type/' + content_type, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status == "ok") {
|
||||
var contentTypeClearButton = document.getElementById("clear-" + content_type);
|
||||
contentTypeClearButton.style.display = "none";
|
||||
|
||||
var configuredIcon = document.getElementById("configured-icon-" + content_type);
|
||||
configuredIcon.style.display = "none";
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function clearConversationProcessor() {
|
||||
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
|
||||
fetch('/api/delete/config/data/processor/conversation', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status == "ok") {
|
||||
var conversationClearButton = document.getElementById("clear-conversation");
|
||||
conversationClearButton.style.display = "none";
|
||||
|
||||
var configuredIcon = document.getElementById("configured-icon-conversation-processor");
|
||||
configuredIcon.style.display = "none";
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
var configure = document.getElementById("configure");
|
||||
configure.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
|
@ -122,5 +246,35 @@
|
|||
configure.innerHTML = "⚙️ Configure";
|
||||
});
|
||||
});
|
||||
|
||||
var reinitialize = document.getElementById("reinitialize");
|
||||
reinitialize.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
reinitialize.disabled = true;
|
||||
reinitialize.innerHTML = "Reinitializing...";
|
||||
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
|
||||
fetch('/api/reinitialize?&client=web', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log('Success:', data);
|
||||
document.getElementById("status").innerHTML = "Reinitialized successfully!";
|
||||
document.getElementById("status").style.display = "block";
|
||||
reinitialize.disabled = false;
|
||||
reinitialize.innerHTML = "🔄 Reinitialized";
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
document.getElementById("status").innerHTML = "Unable to reinitialize. Raise issue on Khoj Discord or Github.";
|
||||
document.getElementById("status").style.display = "block";
|
||||
reinitialize.disabled = false;
|
||||
reinitialize.innerHTML = "🔄 Reinitialize";
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -35,9 +35,9 @@
|
|||
{% endfor %}
|
||||
</div>
|
||||
<button type="button" id="add-repository-button">Add Repository</button>
|
||||
<h4>You probably don't need to edit these.</h4>
|
||||
<h4 style="display: none;">You probably don't need to edit these.</h4>
|
||||
|
||||
<table>
|
||||
<table style="display: none;" >
|
||||
<tr>
|
||||
<td>
|
||||
<label for="compressed-jsonl">Compressed JSONL (Output)</label>
|
||||
|
@ -160,7 +160,7 @@
|
|||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data["status"] == "ok") {
|
||||
document.getElementById("success").innerHTML = "✅ Successfully updated. Click Configure on your <a href='/config'>settings page</a> to complete your Khoj setup.";
|
||||
document.getElementById("success").innerHTML = "✅ Successfully updated. Go to your <a href='/config'>settings page</a> to complete setup.";
|
||||
document.getElementById("success").style.display = "block";
|
||||
} else {
|
||||
document.getElementById("success").innerHTML = "⚠️ Failed to update settings.";
|
||||
|
|
|
@ -44,9 +44,9 @@
|
|||
</tr>
|
||||
</table>
|
||||
|
||||
<h4>You probably don't need to edit these.</h4>
|
||||
<h4 style="display: none;">You probably don't need to edit these.</h4>
|
||||
|
||||
<table>
|
||||
<table style="display: none;" >
|
||||
<tr>
|
||||
<td>
|
||||
<label for="compressed-jsonl">Compressed JSONL (Output)</label>
|
||||
|
@ -149,7 +149,7 @@
|
|||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data["status"] == "ok") {
|
||||
document.getElementById("success").innerHTML = "✅ Successfully updated. Click Configure on your <a href='/config'>settings page</a> to complete your Khoj setup.";
|
||||
document.getElementById("success").innerHTML = "✅ Successfully updated. Go to your <a href='/config'>settings page</a> to complete setup.";
|
||||
document.getElementById("success").style.display = "block";
|
||||
} else {
|
||||
document.getElementById("success").innerHTML = "⚠️ Failed to update settings.";
|
||||
|
|
|
@ -17,11 +17,8 @@
|
|||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4>You probably don't need to edit these.</h4>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<table >
|
||||
<tr style="display: none;">
|
||||
<td>
|
||||
<label for="conversation-logfile">Conversation Logfile</label>
|
||||
</td>
|
||||
|
@ -78,7 +75,7 @@
|
|||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data["status"] == "ok") {
|
||||
document.getElementById("success").innerHTML = "✅ Successfully updated. Click Configure on your <a href='/config'>settings page</a> to complete your Khoj setup.";
|
||||
document.getElementById("success").innerHTML = "✅ Successfully updated. Go to your <a href='/config'>settings page</a> to complete setup.";
|
||||
document.getElementById("success").style.display = "block";
|
||||
} else {
|
||||
document.getElementById("success").innerHTML = "⚠️ Failed to update settings.";
|
||||
|
|
|
@ -54,7 +54,7 @@ if not state.demo:
|
|||
return state.config
|
||||
|
||||
@api.post("/config/data/content_type/github", status_code=200)
|
||||
async def set_content_config_github_data(updated_config: GithubContentConfig):
|
||||
async def set_content_config_github_data(updated_config: Union[GithubContentConfig, None]):
|
||||
if not state.config:
|
||||
state.config = FullConfig()
|
||||
state.config.search_type = SearchConfig.parse_obj(constants.default_config["search-type"])
|
||||
|
@ -70,8 +70,35 @@ if not state.demo:
|
|||
except Exception as e:
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
@api.post("/delete/config/data/content_type/{content_type}", status_code=200)
|
||||
async def remove_content_config_data(content_type: str):
|
||||
if not state.config or not state.config.content_type:
|
||||
return {"status": "ok"}
|
||||
|
||||
if state.config.content_type:
|
||||
state.config.content_type[content_type] = None
|
||||
|
||||
try:
|
||||
save_config_to_file_updated_state()
|
||||
return {"status": "ok"}
|
||||
except Exception as e:
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
@api.post("/delete/config/data/processor/conversation", status_code=200)
|
||||
async def remove_processor_conversation_config_data():
|
||||
if not state.config or not state.config.processor or not state.config.processor.conversation:
|
||||
return {"status": "ok"}
|
||||
|
||||
state.config.processor.conversation = None
|
||||
|
||||
try:
|
||||
save_config_to_file_updated_state()
|
||||
return {"status": "ok"}
|
||||
except Exception as e:
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
@api.post("/config/data/content_type/{content_type}", status_code=200)
|
||||
async def set_content_config_data(content_type: str, updated_config: TextContentConfig):
|
||||
async def set_content_config_data(content_type: str, updated_config: Union[TextContentConfig, None]):
|
||||
if not state.config:
|
||||
state.config = FullConfig()
|
||||
state.config.search_type = SearchConfig.parse_obj(constants.default_config["search-type"])
|
||||
|
@ -88,7 +115,7 @@ if not state.demo:
|
|||
return {"status": "error", "message": str(e)}
|
||||
|
||||
@api.post("/config/data/processor/conversation", status_code=200)
|
||||
async def set_processor_conversation_config_data(updated_config: ConversationProcessorConfig):
|
||||
async def set_processor_conversation_config_data(updated_config: Union[ConversationProcessorConfig, None]):
|
||||
if not state.config:
|
||||
state.config = FullConfig()
|
||||
state.config.search_type = SearchConfig.parse_obj(constants.default_config["search-type"])
|
||||
|
|
|
@ -34,7 +34,8 @@ if not state.demo:
|
|||
|
||||
@web_client.get("/config", response_class=HTMLResponse)
|
||||
def config_page(request: Request):
|
||||
return templates.TemplateResponse("config.html", context={"request": request})
|
||||
current_config = state.config if state.config else constants.default_config
|
||||
return templates.TemplateResponse("config.html", context={"request": request, "current_config": current_config})
|
||||
|
||||
@web_client.get("/config/content_type/github", response_class=HTMLResponse)
|
||||
def github_config_page(request: Request):
|
||||
|
|
Loading…
Reference in a new issue