- 헤더 프로필 왼쪽에 '매뉴얼' 버튼 추가(MANUAL_URL 환경변수, 기본 gitea MANUAL) - 검색을 페이지 내 data-search 카드 전체 대상으로 일반화 → 프로필에서 그 사람 프로젝트도 검색(자리표시자도 페이지별로: 공유/내/○○ 님의 프로젝트) - 상세 페이지 뒤로가기: ?from= 내부경로 기반으로 프로필→상세는 프로필로 복귀 - '사내 개발 포털' +4pt, 도구 카드 이름·설명 +2pt Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
66 lines
2.8 KiB
JavaScript
66 lines
2.8 KiB
JavaScript
// 피드 검색·정렬·즐겨찾기 필터 + 내 프로젝트 필터 (모두 클라이언트 처리).
|
|
import { $, $$ } from "./util.js";
|
|
|
|
function applyFeed() {
|
|
// 검색 대상 = 현재 페이지의 검색 가능한 카드 전체(대시보드=공유 프로젝트, 프로필=그 사람 프로젝트).
|
|
const cards = $$(".fcard[data-search]");
|
|
if (!cards.length) return;
|
|
const q = (($("#feedSearch") && $("#feedSearch").value) || "").trim().toLowerCase();
|
|
const starOnly = $("#feedStarFilter") && $("#feedStarFilter").classList.contains("on");
|
|
let visible = 0;
|
|
cards.forEach((c) => {
|
|
const hit = !q || (c.getAttribute("data-search") || "").indexOf(q) >= 0;
|
|
const st = !starOnly || c.getAttribute("data-starred") === "true";
|
|
const show = hit && st;
|
|
c.style.display = show ? "" : "none";
|
|
if (show) visible++;
|
|
});
|
|
const empty = $("#feedEmpty");
|
|
if (empty) {
|
|
empty.hidden = visible !== 0;
|
|
empty.textContent = starOnly && visible === 0
|
|
? "아직 즐겨찾기한 프로젝트가 없어요 · 카드의 ⭐ 버튼으로 추가하세요"
|
|
: "“" + (($("#feedSearch") && $("#feedSearch").value) || "") + "” 와 일치하는 프로젝트가 없습니다.";
|
|
}
|
|
}
|
|
|
|
function sortFeed(mode) {
|
|
const grid = $("#feedGrid"); if (!grid) return;
|
|
const cards = $$(".fcard", grid);
|
|
cards.sort((a, b) => {
|
|
if (mode === "popular") {
|
|
return (+b.getAttribute("data-pop") || 0) - (+a.getAttribute("data-pop") || 0)
|
|
|| (b.getAttribute("data-created") || "").localeCompare(a.getAttribute("data-created") || "");
|
|
}
|
|
return (b.getAttribute("data-created") || "").localeCompare(a.getAttribute("data-created") || "");
|
|
});
|
|
cards.forEach((c) => grid.appendChild(c));
|
|
}
|
|
|
|
export function initFeed() {
|
|
const search = $("#feedSearch");
|
|
if (search) search.addEventListener("input", applyFeed);
|
|
const sl = $("#sortLatest"), sp = $("#sortPopular");
|
|
if (sl) sl.addEventListener("click", () => { sl.classList.add("on"); if (sp) sp.classList.remove("on"); sortFeed("latest"); });
|
|
if (sp) sp.addEventListener("click", () => { sp.classList.add("on"); if (sl) sl.classList.remove("on"); sortFeed("popular"); });
|
|
const sf = $("#feedStarFilter");
|
|
if (sf) sf.addEventListener("click", () => { sf.classList.toggle("on"); applyFeed(); });
|
|
}
|
|
|
|
export function initMyFilter() {
|
|
const tabs = $$("[data-myfilter]");
|
|
if (!tabs.length) return;
|
|
tabs.forEach((tab) => {
|
|
tab.addEventListener("click", () => {
|
|
const f = tab.getAttribute("data-myfilter"); // all | public | private
|
|
tabs.forEach((t) => t.classList.toggle("on", t === tab));
|
|
$$("#myProjGrid .pcard").forEach((c) => {
|
|
const vis = c.getAttribute("data-vis");
|
|
c.style.display = (f === "all" || vis === f) ? "" : "none";
|
|
});
|
|
const add = $("#addCard");
|
|
if (add) add.style.display = f === "all" ? "" : "none";
|
|
});
|
|
});
|
|
}
|