105 lines
12 KiB
HTML
105 lines
12 KiB
HTML
{% extends 'core/base.html' %}
|
|
{% load i18n markdown_extras %}
|
|
{% block content %}
|
|
<div class="d-md-none alert alert-info">{% trans "Collections are currently available on desktop only." %}</div>
|
|
<div id="collection-manage" class="d-none d-md-block" hx-boost="true" hx-target="#collection-manage" hx-select="#collection-manage" hx-swap="outerHTML show:none" hx-on::after-settle="if(window.collectionFocus==='__last'){document.querySelector('#collection-sections section:last-of-type')?.scrollIntoView({block:'center'})}else if(window.collectionFocus){document.getElementById(window.collectionFocus)?.scrollIntoView({block:'center'})}window.collectionFocus=null">
|
|
<div class="d-flex justify-content-between align-items-start gap-3 mb-4">
|
|
<div>
|
|
<a class="btn btn-sm btn-outline-secondary mb-3" href="{{ collection.get_absolute_url }}" hx-boost="false">← {% trans "View collection" %}</a>
|
|
<h1 class="display-6 mb-2">{{ collection.title }}</h1>
|
|
<div class="d-flex flex-wrap gap-2 align-items-center">
|
|
{% if collection.mode != 'manual' %}<span class="badge text-bg-info">{{ collection.get_mode_display }}</span>{% endif %}
|
|
{% if collection.team %}<span class="badge text-bg-warning">{{ collection.team.name }}</span>{% else %}<span class="badge text-bg-light">{{ collection.get_visibility_display }}</span>{% endif %}
|
|
{% for tag in collection.filter_tags.all %}<span class="badge rounded-pill text-bg-light">#{{ tag.name }}</span>{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% if can_edit %}<div class="d-flex gap-2"><a class="btn btn-outline-secondary" href="{% url 'collection_edit' collection.id %}" hx-boost="false">{% trans "Collection settings" %}</a>{% if can_delete %}<form method="post" action="{% url 'collection_delete' collection.id %}" hx-boost="false" onsubmit="return confirm('{% trans "Delete collection? The notes remain available." %}')">{% csrf_token %}<button class="btn btn-outline-danger">{% trans "Delete" %}</button></form>{% endif %}</div>{% endif %}
|
|
</div>
|
|
|
|
{% if collection.description %}<div class="content lead mb-4">{{ collection.description|markdown }}</div>{% endif %}
|
|
|
|
{% if sections %}
|
|
<div class="card item-card mb-4"><div class="card-body"><div class="fw-semibold mb-2">{% trans "Contents" %}</div><ol class="mb-0">{% include 'core/_collection_toc_items.html' with sections=sections %}</ol></div></div>
|
|
{% endif %}
|
|
|
|
{% if pending_item %}
|
|
<div class="alert alert-warning">
|
|
<h2 class="h5">{% trans "The note has a different visibility" %}</h2>
|
|
<p>{% trans "To add it, change its visibility or create a separate copy for this collection." %}</p>
|
|
<div class="border rounded bg-white p-2 mb-3">{{ pending_item.content|truncatechars:180 }}</div>
|
|
<div class="d-flex gap-2">
|
|
{% if pending_can_convert %}<form method="post">{% csrf_token %}<input type="hidden" name="action" value="confirm_add"><input type="hidden" name="item_id" value="{{ pending_item.id }}"><input type="hidden" name="mode" value="convert"><button class="btn btn-warning">{% if collection.visibility == 'public' %}{% trans "Make note public" %}{% elif collection.team %}{% trans "Share note with team" %}{% else %}{% trans "Make note private" %}{% endif %}</button></form>{% endif %}
|
|
<form method="post">{% csrf_token %}<input type="hidden" name="action" value="confirm_add"><input type="hidden" name="item_id" value="{{ pending_item.id }}"><input type="hidden" name="mode" value="copy"><button class="btn btn-outline-secondary">{% trans "Create compatible copy" %}</button></form>
|
|
<a class="btn btn-link" href="{% url 'collection_manage' collection.id %}">{% trans "Cancel" %}</a>
|
|
</div>
|
|
{% if not pending_can_convert %}<div class="small text-muted mt-2">{% trans "The original cannot be changed because it is used elsewhere or you cannot edit it." %}</div>{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div id="collection-sections" class="vstack gap-4 mb-5" data-reorder-url="{% url 'collection_manage' collection.id %}">
|
|
{% for section in sections %}
|
|
<section id="section-{{ section.id }}" class="card item-card" draggable="true" data-section-id="{{ section.id }}" data-position="{{ forloop.counter0 }}"><div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-start gap-3 mb-3">
|
|
<h2 class="h3 mb-0">{% if section.item %}{{ section.title|default:section.item.content|markdown_title|truncatechars:100 }}{% else %}{{ section.title|default:section.sub_collection.title|truncatechars:100 }}{% endif %}</h2>
|
|
<div class="d-flex gap-2 align-items-center">{% if section.item %}<a class="btn btn-sm btn-outline-secondary" href="{% url 'item_editor' section.item.id %}?next={% url 'collection_manage' collection.id %}" hx-boost="false">{% trans "Edit note" %}</a><a class="small text-muted" href="{{ section.item.get_absolute_url }}">#{{ section.item.id }}</a>{% else %}<a class="btn btn-sm btn-outline-secondary" href="{% url 'collection_manage' section.sub_collection.id %}" hx-boost="false">{% trans "Edit collection" %}</a><a class="small text-muted" href="{{ section.sub_collection.get_absolute_url }}">#{{ section.sub_collection.id }}</a>{% endif %}</div>
|
|
</div>
|
|
{% if section.item %}<div class="content">{{ section.item|item_markdown }}</div>
|
|
{% if section.item.comment %}<div class="content text-muted border-start ps-3 mt-3">{{ section.item.comment|markdown }}</div>{% endif %}{% else %}<div class="text-muted">{% trans "Nested collection" %}: {{ section.sub_collection.title }}</div>{% endif %}
|
|
{% if can_edit %}<div class="border-top mt-4 pt-3 d-flex align-items-center gap-2">
|
|
<span class="btn btn-sm btn-outline-secondary" title="{% trans 'Drag to reorder' %}">↕</span>
|
|
<form method="post" class="d-none move-form">{% csrf_token %}<input type="hidden" name="action" value="move_to"><input type="hidden" name="section_id" value="{{ section.id }}"><input type="hidden" name="position" value="{{ forloop.counter0 }}"></form>
|
|
<form method="post" class="d-flex gap-2 flex-grow-1" hx-on::before-request="window.collectionFocus='section-{{ section.id }}'">{% csrf_token %}<input type="hidden" name="action" value="title"><input type="hidden" name="section_id" value="{{ section.id }}"><input class="form-control form-control-sm" name="title" value="{{ section.title }}" placeholder="{% trans 'Optional section title' %}"><button class="btn btn-sm btn-outline-secondary">{% trans "Save title" %}</button></form>
|
|
<form method="post" hx-on::before-request="window.collectionFocus='section-{{ section.id }}'">{% csrf_token %}<input type="hidden" name="action" value="up"><input type="hidden" name="section_id" value="{{ section.id }}"><button class="btn btn-sm btn-outline-secondary" title="{% trans 'Move up' %}">↑</button></form>
|
|
<form method="post" hx-on::before-request="window.collectionFocus='section-{{ section.id }}'">{% csrf_token %}<input type="hidden" name="action" value="down"><input type="hidden" name="section_id" value="{{ section.id }}"><button class="btn btn-sm btn-outline-secondary" title="{% trans 'Move down' %}">↓</button></form>
|
|
<form method="post" hx-on::before-request="window.collectionFocus='collection-sections'">{% csrf_token %}<input type="hidden" name="action" value="remove"><input type="hidden" name="section_id" value="{{ section.id }}"><button class="btn btn-sm btn-outline-danger">{% trans "Remove" %}</button></form>
|
|
</div>{% endif %}
|
|
</div></section>
|
|
{% empty %}<div class="text-center text-muted py-5">{% trans "This collection has no sections yet." %}</div>{% endfor %}
|
|
</div>
|
|
|
|
{% if can_edit %}
|
|
<div class="card item-card"><div class="card-body">
|
|
<h2 class="h4">{% trans "Add existing note or collection" %}</h2>
|
|
<div class="mb-4"><a class="btn btn-dark" href="{% url 'new_item' %}?kind=note&collection={{ collection.id }}&next={% url 'collection_manage' collection.id %}" hx-boost="false">{% trans "Create note" %}</a></div>
|
|
<form method="post" class="input-group mb-4" hx-boost="false">{% csrf_token %}<input type="hidden" name="action" value="create_chapter"><input class="form-control" name="title" placeholder="{% trans 'New chapter title' %}"><button class="btn btn-outline-dark">{% trans "Create chapter" %}</button></form>
|
|
<form method="get" class="input-group mb-3"><input class="form-control" name="q" value="{{ q }}" placeholder="{% trans 'Search notes and collections' %}"><button class="btn btn-outline-secondary">{% trans "Search" %}</button></form>
|
|
<h3 class="h6">{% trans "Notes" %}</h3>
|
|
<div class="vstack gap-2 mb-4">
|
|
{% for item in candidates %}<div class="border rounded p-3 d-flex justify-content-between align-items-start gap-3{% if item.used_in_current_collection %} bg-light opacity-75{% endif %}"><div><div>{{ item.content|truncatechars:180 }}</div><div class="small text-muted">#{{ item.id }} · {{ item.get_visibility_display }}{% if item.team %} · {{ item.team.name }}{% endif %}{% if item.collection_use_count %} · {% blocktrans count count=item.collection_use_count %}used once{% plural %}used {{ count }} times{% endblocktrans %}{% endif %}</div>{% if item.used_in_current_collection %}<span class="badge text-bg-secondary mt-2">{% trans "Already in this collection" %}</span>{% endif %}</div>{% if item.used_in_current_collection %}<button class="btn btn-sm btn-outline-secondary" disabled>{% trans "Added" %}</button>{% else %}<form method="post" hx-on::before-request="window.collectionFocus='__last'">{% csrf_token %}<input type="hidden" name="action" value="add"><input type="hidden" name="item_id" value="{{ item.id }}"><button class="btn btn-sm btn-dark">{% trans "Add" %}</button></form>{% endif %}</div>{% empty %}<div class="text-muted">{% trans "No matching notes." %}</div>{% endfor %}
|
|
</div>
|
|
<h3 class="h6">{% trans "Collections" %}</h3>
|
|
<div class="vstack gap-2">
|
|
{% for candidate in collection_candidates %}<div class="border rounded p-3 d-flex justify-content-between align-items-start gap-3{% if candidate.used_in_current_collection %} bg-light opacity-75{% endif %}"><div><div>{{ candidate.title }}</div><div class="small text-muted">#{{ candidate.id }} · {{ candidate.get_visibility_display }}{% if candidate.team %} · {{ candidate.team.name }}{% endif %}{% if candidate.collection_use_count %} · {% blocktrans count count=candidate.collection_use_count %}used once{% plural %}used {{ count }} times{% endblocktrans %}{% endif %}</div>{% if candidate.used_in_current_collection %}<span class="badge text-bg-secondary mt-2">{% trans "Already in this collection" %}</span>{% endif %}</div>{% if candidate.used_in_current_collection %}<button class="btn btn-sm btn-outline-secondary" disabled>{% trans "Added" %}</button>{% else %}<form method="post" hx-on::before-request="window.collectionFocus='__last'">{% csrf_token %}<input type="hidden" name="action" value="add_collection"><input type="hidden" name="collection_id" value="{{ candidate.id }}"><button class="btn btn-sm btn-dark">{% trans "Add" %}</button></form>{% endif %}</div>{% empty %}<div class="text-muted">{% trans "No matching collections." %}</div>{% endfor %}
|
|
</div>
|
|
</div></div>
|
|
{% endif %}
|
|
</div>
|
|
<script>
|
|
(function(){
|
|
const list = document.getElementById('collection-sections');
|
|
if(!list) return;
|
|
let dragged = null;
|
|
list.addEventListener('dragstart', event => {
|
|
dragged = event.target.closest('[data-section-id]');
|
|
if(dragged) event.dataTransfer.effectAllowed = 'move';
|
|
});
|
|
list.addEventListener('dragover', event => {
|
|
if(!dragged) return;
|
|
const target = event.target.closest('[data-section-id]');
|
|
if(!target || target === dragged) return;
|
|
event.preventDefault();
|
|
const after = event.clientY > target.getBoundingClientRect().top + target.offsetHeight / 2;
|
|
target.parentNode.insertBefore(dragged, after ? target.nextSibling : target);
|
|
});
|
|
list.addEventListener('drop', event => {
|
|
if(!dragged) return;
|
|
event.preventDefault();
|
|
const sections = [...list.querySelectorAll('[data-section-id]')];
|
|
const form = dragged.querySelector('.move-form');
|
|
form.querySelector('[name=position]').value = sections.indexOf(dragged);
|
|
form.submit();
|
|
});
|
|
})();
|
|
</script>
|
|
{% endblock %}
|