mirror of
https://codeberg.org/catask-org/catask.git
synced 2025-04-19 13:23:41 -05:00
128 lines
6.1 KiB
HTML
128 lines
6.1 KiB
HTML
{% extends 'base.html' %}
|
|
{% block title %}Admin{% endblock %}
|
|
{% set adminLink = 'active' %}
|
|
{% block content %}
|
|
<h1 class="mb-3">Admin panel</h1>
|
|
<div id="response-container"></div>
|
|
<form hx-post="{{ url_for('api.updateConfig') }}" hx-target="#response-container" hx-swap="none">
|
|
<h2 id="instance">Instance</h2>
|
|
<div class="form-group mb-3">
|
|
<label class="form-label" for="instance.title">Title <small class="text-secondary">(e.g. My question box)</small></label>
|
|
<input type="text" id="instance.title" name="instance.title" value="{{ cfg.instance.title }}" class="form-control">
|
|
<p class="form-text">Title of this CatAsk instance</p>
|
|
</div>
|
|
<div class="form-group mb-3">
|
|
<label class="form-label" for="instance.description">Description <small class="text-secondary">(e.g. Ask me a question!)</small></label>
|
|
<input type="text" id="instance.description" name="instance.description" value="{{ cfg.instance.description }}" class="form-control">
|
|
<p class="form-text">Description of this CatAsk instance</p>
|
|
</div>
|
|
<div class="form-group mb-3">
|
|
<label class="form-label" for="instance.image">Relative image path <small class="text-secondary">(default: /static/img/ca_screenshot.png)</small></label>
|
|
<input type="text" id="instance.image" name="instance.image" value="{{ cfg.instance.image }}" class="form-control">
|
|
<p class="form-text">Image that's going to be used in a link preview</p>
|
|
</div>
|
|
<div class="form-group mb-4">
|
|
<label class="form-label" for="instance.fullBaseUrl">Base URL <small class="text-secondary">(e.g. https://ask.example.com)</small></label>
|
|
<input type="text" id="instance.fullBaseUrl" name="instance.fullBaseUrl" value="{{ cfg.instance.fullBaseUrl }}" class="form-control">
|
|
<p class="form-text">Full URL to homepage of this CatAsk instance without a trailing slash</p>
|
|
</div>
|
|
<h2 id="general">General</h2>
|
|
<div class="form-group mb-3">
|
|
<label class="form-label" for="charLimit">Question character limit</label>
|
|
<input type="number" id="charLimit" name="charLimit" value="{{ cfg.charLimit }}" class="form-control">
|
|
<p class="form-text">Max length of a question in characters; questions extending this character limit will not be added to the database</p>
|
|
</div>
|
|
<div class="form-group mb-4">
|
|
<label class="form-label" for="anonName">Name for anonymous users</label>
|
|
<input type="text" id="anonName" name="anonName" value="{{ cfg.anonName }}" class="form-control">
|
|
<p class="form-text">This name will be used for questions asked to you by anonymous users</p>
|
|
</div>
|
|
<div class="form-check mb-2">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
name="_lockInbox"
|
|
id="_lockInbox"
|
|
value="{{ cfg.lockInbox }}"
|
|
{% if cfg.lockInbox == true %}checked{% endif %}>
|
|
<input type="hidden" id="lockInbox" name="lockInbox" value="{{ cfg.lockInbox }}">
|
|
<label for="_lockInbox" class="form-check-label">Lock inbox and don't allow new questions</label>
|
|
</div>
|
|
<div class="form-check mb-2">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
name="_allowAnonQuestions"
|
|
id="_allowAnonQuestions"
|
|
value="{{ cfg.allowAnonQuestions }}"
|
|
{% if cfg.allowAnonQuestions == true %}checked{% endif %}>
|
|
<input type="hidden" id="allowAnonQuestions" name="allowAnonQuestions" value="{{ cfg.allowAnonQuestions }}">
|
|
<label for="_allowAnonQuestions" class="form-check-label">Allow anonymous questions</label>
|
|
</div>
|
|
<div class="form-check mb-3">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
name="_showQuestionCount"
|
|
id="_showQuestionCount"
|
|
value="{{ cfg.showQuestionCount }}"
|
|
{% if cfg.showQuestionCount == true %}checked{% endif %}>
|
|
<input type="hidden" id="showQuestionCount" name="showQuestionCount" value="{{ cfg.showQuestionCount }}">
|
|
<label for="_showQuestionCount" class="form-check-label">Show question count in homepage</label>
|
|
</div>
|
|
<div class="form-group mb-3">
|
|
<button type="submit" class="btn btn-primary mt-3">
|
|
<span class="spinner-border spinner-border-sm htmx-indicator" aria-hidden="true"></span>
|
|
<span class="visually-hidden" role="status">Loading...</span>
|
|
Save
|
|
</button>
|
|
</div>
|
|
</form>
|
|
<hr class="mt-4 mb-4">
|
|
<form hx-post="{{ url_for('admin.index') }}" hx-target="#response-container" hx-swap="none">
|
|
<input type="hidden" name="action" value="update_word_blacklist">
|
|
<div class="form-group mb-3">
|
|
<label class="form-label" for="blacklist_cat"><h2 id="blacklist">Word blacklist</h2></label>
|
|
<p class="text-secondary">Blacklisted words for questions; one word per line</p>
|
|
<textarea id="blacklist_cat" name="blacklist" style="height: 300px; resize: vertical;" class="form-control">{{ blacklist }}</textarea>
|
|
<button type="submit" class="btn btn-primary mt-3">
|
|
<span class="spinner-border spinner-border-sm htmx-indicator" aria-hidden="true"></span>
|
|
<span class="visually-hidden" role="status">Loading...</span>
|
|
Save
|
|
</button>
|
|
</div>
|
|
</form>
|
|
{% endblock %}
|
|
{% block scripts %}
|
|
<script>
|
|
// fix handling checkboxes
|
|
document.querySelectorAll('.form-check-input').forEach(function(checkbox) {
|
|
checkbox.addEventListener('change', function() {
|
|
checkbox.nextElementSibling.value = this.checked ? 'True' : 'False';
|
|
});
|
|
});
|
|
</script>
|
|
<script>
|
|
const appendAlert = (elementId, message, type) => {
|
|
const alertPlaceholder = document.getElementById(elementId);
|
|
const alertHtml = `
|
|
<div class="alert alert-${type} alert-dismissible" role="alert">
|
|
<div>${message}</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
`;
|
|
|
|
alertPlaceholder.innerHTML = alertHtml;
|
|
}
|
|
|
|
document.addEventListener('htmx:afterRequest', function(event) {
|
|
const jsonResponse = event.detail.xhr.response;
|
|
if (jsonResponse) {
|
|
const parsed = JSON.parse(jsonResponse);
|
|
const msgType = event.detail.successful ? 'success' : 'error';
|
|
const targetElementId = event.detail.target.id;
|
|
appendAlert(targetElementId, parsed.message, msgType);
|
|
}
|
|
})
|
|
</script>
|
|
{% endblock %}
|