mirror of
https://codeberg.org/catask-org/catask.git
synced 2025-04-19 13:23:41 -05:00
136 lines
6.4 KiB
HTML
136 lines
6.4 KiB
HTML
{% extends 'base.html' %}
|
|
{% block title %}Home{% endblock %}
|
|
{% set homeLink = 'active' %}
|
|
{% block content %}
|
|
<div class="mt-5 mb-sm-2 mb-md-5">
|
|
<h1 class="text-center fw-bold">{{ cfg.instance.title }}</h1>
|
|
<h5 class="text-center fw-light">{{ cfg.instance.description }}</h5>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-sm-{% if combined %}4{% else %}8{% endif %}{% if not combined %} m-auto{% endif %}">
|
|
<div class="mb-5 sticky-md-top">
|
|
{% if cfg.lockInbox == false %}
|
|
<br>
|
|
<h2>Ask a question</h2>
|
|
<form class="d-lg-block" hx-post="{{ url_for('api.addQuestion') }}" id="question-form" hx-target="#response-container" hx-swap="none">
|
|
<div class="form-group mb-2">
|
|
<input {% if cfg.allowAnonQuestions == false %}required{% endif %} class="form-control" type="text" name="from_who" id="from_who" placeholder="Name {% if cfg.allowAnonQuestions == true %}(optional){% endif %}">
|
|
</div>
|
|
<div class="form-group mb-2">
|
|
<textarea class="form-control" required name="question" id="question" placeholder="Write your question..."></textarea>
|
|
</div>
|
|
<div class="form-group mb-2">
|
|
<label for="antispam">Anti-spam: please enter the word <code class="text-uppercase">{{ getRandomWord() }}</code> in lowercase</label>
|
|
<input class="form-control" type="text" required name="antispam" id="antispam" autocomplete="off">
|
|
</div>
|
|
<div class="form-group d-grid d-lg-flex justify-content-lg-end mt-3">
|
|
<button type="submit" class="btn btn-primary">
|
|
<span class="spinner-border spinner-border-sm htmx-indicator" aria-hidden="true"></span>
|
|
<span class="visually-hidden" role="status">Loading...</span>
|
|
Ask
|
|
</button>
|
|
</div>
|
|
</form>
|
|
<div id="response-container" class="mt-3"></div>
|
|
{% else %}
|
|
<br>
|
|
<h2 class="text-center">New questions cannot be asked right now.</h2>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% if combined %}
|
|
<div class="col-sm-8">
|
|
{% if cfg.showQuestionCount == true %}
|
|
<h3 class="fs-4">{{ len(combined) }} <span class="fw-light">question(s)</span></h3>
|
|
{% endif %}
|
|
<div id="top-response-container"></div>
|
|
{% for item in combined %}
|
|
<div class="card mt-3 mb-3" id="question-{{ item.question.id }}">
|
|
<div class="card-header">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<h5 class="card-title mt-1 mb-1">
|
|
{% if item.question.from_who %}
|
|
{{ item.question.from_who }}
|
|
{% else %}
|
|
<i class="bi bi-incognito" data-bs-toggle="tooltip" data-bs-title="This question was asked anonymously" data-bs-placement="top"></i> {{ cfg.anonName }}
|
|
{% endif %}
|
|
</h5>
|
|
<h6 class="card-subtitle fw-light text-body-secondary" data-bs-toggle="tooltip" data-bs-title="{{ item.question.creation_date.strftime("%B %d, %Y %H:%M") }}" data-bs-placement="top">{{ formatRelativeTime(str(item.question.creation_date)) }}</h6>
|
|
</div>
|
|
<div class="card-text markdown-content">{{ item.question.content | render_markdown }}</div>
|
|
</div>
|
|
<div class="card-body">
|
|
{% for answer in item.answers %}
|
|
<div class="markdown-content">{{ answer.content | render_markdown }}</div>
|
|
</div>
|
|
<div class="card-footer pt-0 pb-0 ps-3 pe-2 text-body-secondary d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<span class="fs-6" data-bs-toggle="tooltip" data-bs-title="{{ answer.creation_date.strftime("%B %d, %Y %H:%M") }}">{{ formatRelativeTime(str(answer.creation_date)) }}</span>
|
|
{% if item.question.pinned %}
|
|
<span class="ms-1"><i class="bi bi-pin"></i> <span class="fw-medium">Pinned</span></span>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
<div class="d-flex align-items-center">
|
|
<a href="{{ url_for('viewQuestion', question_id=item.question.id) }}" class="btn pt-2 pb-2 text-body-secondary" data-bs-toggle="tooltip" data-bs-title="View question"><i class="bi bi-box-arrow-up-right"></i></a>
|
|
<div class="dropdown">
|
|
<button class="btn btn-sm pt-2 pb-2 no-arrow text-body-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false"><i style="font-size: 1.2rem;" class="bi bi-three-dots"></i></button>
|
|
<ul class="dropdown-menu">
|
|
<li><button class="dropdown-item" onclick="copy({{ item.question.id }})">Copy link</button></li>
|
|
{% if logged_in %}
|
|
{% if not item.question.pinned %}
|
|
<li><button class="dropdown-item" hx-post="{{ url_for('api.pinQuestion', question_id=item.question.id) }}" hx-target="#top-response-container" hx-swap="none">Pin</button></li>
|
|
{% else %}
|
|
<li><button class="dropdown-item" hx-post="{{ url_for('api.unpinQuestion', question_id=item.question.id) }}" hx-target="#top-response-container" hx-swap="none">Unpin</button></li>
|
|
{% endif %}
|
|
<li><button class="bg-hover-danger text-danger dropdown-item" hx-post="{{ url_for('api.returnToInbox', question_id=item.question.id) }}" hx-target="#question-{{ item.question.id }}" hx-swap="none">Return to inbox</button></li>
|
|
{% endif %}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endblock %}
|
|
{% block scripts %}
|
|
<script>
|
|
function copy(questionId) {
|
|
navigator.clipboard.writeText("{{ cfg.instance.fullBaseUrl }}/q/" + questionId + "/")
|
|
}
|
|
</script>
|
|
<script>
|
|
document.getElementById('question-form').reset();
|
|
|
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
|
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
|
|
|
|
const appendAlert = (elementId, message, type, onclick) => {
|
|
const alertPlaceholder = document.querySelector(`#${elementId}`);
|
|
alertPlaceholder.innerHTML = '';
|
|
const alertHtml = `
|
|
<div class="alert alert-${type} alert-dismissible mt-3" role="alert">
|
|
<div>${message}</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close" onclick=${onclick}></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 alertType = event.detail.successful ? 'success' : 'danger';
|
|
msgType = event.detail.successful ? parsed.message : parsed.error;
|
|
const targetElementId = event.detail.target.id;
|
|
onclick = event.detail.successful ? null : "window.location.reload()";
|
|
appendAlert(targetElementId, msgType, alertType, onclick);
|
|
document.getElementById('question-form').reset();
|
|
}
|
|
})
|
|
</script>
|
|
{% endblock %}
|