1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 04:38:53 +03:00
This commit is contained in:
Anton Afanasyeu
2026-06-05 15:19:48 +02:00
parent 5df496c0a5
commit db91842dd9
12 changed files with 520 additions and 25 deletions

View File

@@ -826,6 +826,16 @@ a:hover { text-decoration: underline; }
color: #fff;
background: var(--tag-bg, #5c6b82);
}
button.report-tag--filter {
border: none;
cursor: pointer;
font: inherit;
color: inherit;
line-height: 1.3;
}
button.report-tag--filter:hover {
filter: brightness(1.12);
}
.reports-filter-banner {
margin: 8px 0 0;
padding: 10px 12px;

View File

@@ -224,17 +224,26 @@
return { label: kind || '?', bg: '#5c6b82' };
}
function renderTagPills(tags) {
function renderTagPills(tags, filterable) {
if (!tags.length) return '<span class="muted">—</span>';
return tags
.map(
(t) =>
'<span class="report-tag" style="--tag-bg:' +
escapeHtml(t.bg) +
'">' +
escapeHtml(t.label) +
'</span>'
)
.map((t) => {
const label = escapeHtml(t.label || t.id || '');
const bg = escapeHtml(t.bg || '#5c6b82');
const id = t.id ? String(t.id).trim() : '';
if (filterable && id) {
return (
'<button type="button" class="report-tag report-tag--filter" data-tag-id="' +
escapeHtml(id) +
'" style="--tag-bg:' +
bg +
'" title="Filter by tag">' +
label +
'</button>'
);
}
return '<span class="report-tag" style="--tag-bg:' + bg + '">' + label + '</span>';
})
.join('');
}
@@ -255,12 +264,13 @@
const id = String(t.id).toLowerCase();
if (id === 'new' || id === 'java' || id === 'ndk' || id === 'android') return;
tags.push({
id,
label: t.label || t.id,
bg: t.bg || '#5c6b82',
});
});
}
return renderTagPills(tags);
return renderTagPills(tags, !grouped);
}
function apiSortKey(key) {
@@ -621,12 +631,12 @@
if (!href) return;
const go = () => navigateTo(href);
const onActivate = (e) => {
if (e.target.closest('.report-tree-toggle')) return;
if (e.target.closest('.report-tree-toggle, .tag-edit-btn, .report-tag--filter')) return;
go();
};
el.addEventListener('click', onActivate);
el.addEventListener('keydown', (e) => {
if (e.target.closest('.report-tree-toggle')) return;
if (e.target.closest('.report-tree-toggle, .tag-edit-btn, .report-tag--filter')) return;
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
go();
@@ -635,6 +645,16 @@
});
}
function bindReportTagFilters(root, onTag) {
if (!root || typeof onTag !== 'function') return;
root.querySelectorAll('.report-tag--filter').forEach((btn) => {
btn.addEventListener('click', (e) => {
const tagId = btn.getAttribute('data-tag-id') || '';
if (tagId) onTag(tagId, e);
});
});
}
function initReportsApp() {
const app = document.getElementById('reports-app');
if (!app) return;
@@ -948,6 +968,63 @@
});
tbody.innerHTML = html;
bindTreeInteractions(tbody);
bindReportTagFilters(tbody, handleReportTagClick);
}
function applyReportTagFilter(tagId) {
listContext.filterTags = [tagId];
listContext.tagMode = listContext.tagMode || 'and';
grouped = false;
app.setAttribute('data-grouped', '0');
page = 1;
updateFilterBanner(listContext, filterBanner);
const p = new URLSearchParams(window.location.search);
p.set('view', 'reports');
p.delete('tag');
p.append('tag', tagId);
p.set('tag_mode', listContext.tagMode);
p.delete('group');
p.delete('page');
history.replaceState(null, '', basePath() + '/?' + p.toString());
const modeWrap = document.getElementById('tag-mode-wrap');
if (modeWrap) modeWrap.hidden = false;
const modeSel = document.getElementById('tag-mode-select');
if (modeSel) modeSel.value = listContext.tagMode;
load();
}
function handleReportTagClick(tagId, ev) {
ev.stopPropagation();
ev.preventDefault();
if (grouped) {
applyReportTagFilter(tagId);
return;
}
const xhr = new XMLHttpRequest();
xhr.open(
'GET',
basePath() +
'/api/reports.php?page=1&per_page=2&tag=' +
encodeURIComponent(tagId) +
'&tag_mode=and&sort=received_at_ms&dir=desc&since_ms=0',
true
);
xhr.onload = function () {
let data;
try {
data = JSON.parse(xhr.responseText);
} catch {
return;
}
if (!data.ok) return;
const total = Number(data.total || 0);
if (total === 1 && data.items && data.items[0] && data.items[0].id) {
navigateTo(basePath() + '/?view=report&id=' + data.items[0].id);
return;
}
applyReportTagFilter(tagId);
};
xhr.send();
}
function load() {

View File

@@ -32,12 +32,20 @@
}
function renderTagPill(tag) {
const id = String(tag.id || '').trim();
const label = escapeHtml(tag.label || tag.id);
const bg = escapeHtml(tag.bg || '#5c6b82');
if (!id) {
return '<span class="report-tag" style="--tag-bg:' + bg + '">' + label + '</span>';
}
return (
'<span class="report-tag" style="--tag-bg:' +
escapeHtml(tag.bg || '#5c6b82') +
'">' +
escapeHtml(tag.label || tag.id) +
'</span>'
'<button type="button" class="report-tag report-tag--filter" data-tag-id="' +
escapeHtml(id) +
'" style="--tag-bg:' +
bg +
'" title="Filter by tag">' +
label +
'</button>'
);
}
@@ -172,6 +180,56 @@
bindRows();
}
function applyTagFilter(tagId) {
tag = tagId;
if (tagFilter) {
let found = false;
tagFilter.querySelectorAll('option').forEach((opt) => {
if (opt.value === tagId) found = true;
});
if (!found) {
const opt = document.createElement('option');
opt.value = tagId;
opt.textContent = tagId;
tagFilter.appendChild(opt);
}
tagFilter.value = tagId;
}
page = 1;
load();
}
function activateTag(tagId, ev) {
if (!tagId) return;
ev.stopPropagation();
ev.preventDefault();
const xhr = new XMLHttpRequest();
xhr.open(
'GET',
basePath() +
'/api/tickets.php?page=1&per_page=2&tag=' +
encodeURIComponent(tagId),
true
);
xhr.onload = function () {
let data;
try {
data = JSON.parse(xhr.responseText);
} catch {
return;
}
if (!data.ok) return;
const total = Number(data.total || 0);
if (total === 1 && data.items && data.items[0] && data.items[0].id) {
window.location.href =
basePath() + '/?view=ticket&id=' + encodeURIComponent(String(data.items[0].id));
return;
}
applyTagFilter(tagId);
};
xhr.send();
}
function bindRows() {
tbody.querySelectorAll('.report-tree-toggle').forEach((btn) => {
btn.addEventListener('click', (e) => {
@@ -192,11 +250,11 @@
window.location.href = href;
};
el.addEventListener('click', (e) => {
if (e.target.closest('.report-tree-toggle, .tag-edit-btn')) return;
if (e.target.closest('.report-tree-toggle, .tag-edit-btn, .report-tag--filter')) return;
go();
});
el.addEventListener('keydown', (e) => {
if (e.target.closest('.report-tree-toggle, .tag-edit-btn')) return;
if (e.target.closest('.report-tree-toggle, .tag-edit-btn, .report-tag--filter')) return;
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
go();
@@ -212,6 +270,11 @@
}
});
});
tbody.querySelectorAll('.report-tag--filter').forEach((btn) => {
btn.addEventListener('click', (e) => {
activateTag(btn.getAttribute('data-tag-id') || '', e);
});
});
}
function renderPagination(total, currentPage) {