forked from retoor/devplacepy
Implement full attachment CRUD for issues and comments, restricted to open issues only. Attachments are stored locally and mirrored to the Gitea tracker via new `mirror_attachment_to_gitea` and `set_gitea_asset_id` functions. Add `gitea_asset_id` column to the attachments table, extend `IssueForm` and `IssueCommentForm` with `attachment_uids` field, and expose new API endpoints for listing, adding, and deleting issue attachments. Update agent configuration to include web research tools, and document the new capability in README, AGENTS.md, and CLAUDE.md.
94 lines
4.7 KiB
HTML
94 lines
4.7 KiB
HTML
{% extends "base.html" %}
|
|
{% block extra_head %}
|
|
<link rel="stylesheet" href="{{ static_url('/static/css/issues.css') }}">
|
|
{% endblock %}
|
|
{% block content %}
|
|
<div class="issues-layout issue-detail">
|
|
<div class="issue-detail-nav">
|
|
<a href="/issues" class="issue-back">← All issues</a>
|
|
{% if issue.html_url %}<a href="{{ issue.html_url }}" class="issue-gitea-link" target="_blank" rel="noopener noreferrer">View on Gitea</a>{% endif %}
|
|
</div>
|
|
|
|
<div class="card issue-detail-card">
|
|
<div class="issue-detail-header">
|
|
<span class="issue-number">#{{ issue.number }}</span>
|
|
<h1 class="issue-detail-title">{{ render_title(issue.title) }}</h1>
|
|
<span class="issue-status {{ issue.state }}"><span class="sr-only">Status: </span>{{ issue.state }}</span>
|
|
</div>
|
|
<div class="issue-meta">
|
|
{% if issue.is_local_author %}
|
|
{% set _user = {'username': issue.author_username} %}{% set _size = 24 %}{% set _size_class = "sm" %}{% include "_avatar_link.html" %}
|
|
{% endif %}
|
|
<span class="issue-author">{{ issue.author_username }}</span>
|
|
<span class="issue-dot">·</span>
|
|
<span class="issue-date">{{ local_dt(issue.created_at) }}</span>
|
|
</div>
|
|
|
|
{% if viewer_is_admin %}
|
|
<div class="issue-admin-actions">
|
|
{% if issue.state == 'open' %}
|
|
<form method="POST" action="/issues/{{ issue.number }}/status">
|
|
<input type="hidden" name="status" value="closed">
|
|
<button type="submit" class="btn btn-secondary btn-sm"><span class="btn-spinner" aria-hidden="true"></span>Close ticket</button>
|
|
</form>
|
|
{% else %}
|
|
<form method="POST" action="/issues/{{ issue.number }}/status">
|
|
<input type="hidden" name="status" value="open">
|
|
<button type="submit" class="btn btn-secondary btn-sm"><span class="btn-spinner" aria-hidden="true"></span>Reopen ticket</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="issue-detail-body rendered-content">{{ render_content(body) }}</div>
|
|
|
|
{% if attachments %}
|
|
{% set _attachments = attachments %}{% set _delete_base = "/issues/" ~ issue.number ~ "/attachments" %}{% include "_issue_attachments.html" %}
|
|
{% endif %}
|
|
|
|
{% if can_attach %}
|
|
<form class="issue-attach-form" data-issue-attach data-action="/issues/{{ issue.number }}/attachments">
|
|
{% include "_attachment_form.html" %}
|
|
<button type="submit" class="btn btn-secondary btn-sm"><span class="btn-spinner" aria-hidden="true"></span>Attach files</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<section class="comments-section">
|
|
<h3>Updates & comments</h3>
|
|
{% for comment in comments %}
|
|
<div class="issue-comment">
|
|
<div class="issue-comment-head">
|
|
{% if comment.is_local_author %}
|
|
{% set _user = {'username': comment.author_username} %}{% set _size = 20 %}{% set _size_class = "sm" %}{% include "_avatar_link.html" %}
|
|
{% else %}
|
|
<span class="issue-comment-badge"><span class="sr-only">Developer reply from </span>dev</span>
|
|
{% endif %}
|
|
<span class="issue-author">{{ comment.author_username }}</span>
|
|
<span class="issue-dot">·</span>
|
|
<span class="issue-date">{{ local_dt(comment.created_at) }}</span>
|
|
</div>
|
|
<div class="issue-comment-body rendered-content">{{ render_content(comment.body) }}</div>
|
|
{% if comment.attachments %}
|
|
{% set _attachments = comment.attachments %}{% set _delete_base = "/issues/" ~ issue.number ~ "/comments/" ~ comment.id ~ "/attachments" %}{% include "_issue_attachments.html" %}
|
|
{% endif %}
|
|
</div>
|
|
{% else %}
|
|
<p class="no-comments-msg">No updates yet.</p>
|
|
{% endfor %}
|
|
|
|
{% if can_comment %}
|
|
<form method="POST" action="/issues/{{ issue.number }}/comment" class="comment-form issue-comment-form">
|
|
<textarea name="body" required aria-required="true" maxlength="5000" placeholder="Add a comment (posted to the tracker)..." class="min-h-120" data-mention aria-label="Add a comment"></textarea>
|
|
<div class="issue-comment-form-footer">
|
|
{% include "_attachment_form.html" %}
|
|
<button type="submit" class="btn btn-primary btn-sm"><span class="btn-spinner" aria-hidden="true"></span>Comment</button>
|
|
</div>
|
|
</form>
|
|
{% else %}
|
|
<p class="no-comments-msg"><a href="/auth/login">Log in</a> to comment.</p>
|
|
{% endif %}
|
|
</section>
|
|
</div>
|
|
{% endblock %}
|