From afa87af01c79a9baa539f2992d32154d2a4739bd Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Sat, 14 Feb 2026 14:46:37 -0800 Subject: task: delete vanilla js prototype\n\n- Removed vanilla/ directory and web/dist/vanilla directory\n- Updated Makefile, Dockerfile, and CI workflow to remove vanilla references\n- Cleaned up web/web.go to remove vanilla embed and routes\n- Verified build and tests pass\n\nCloses NK-2tcnmq --- vanilla/coverage/app.js.html | 856 ------------------------------------------- 1 file changed, 856 deletions(-) delete mode 100644 vanilla/coverage/app.js.html (limited to 'vanilla/coverage/app.js.html') diff --git a/vanilla/coverage/app.js.html b/vanilla/coverage/app.js.html deleted file mode 100644 index 954ba71..0000000 --- a/vanilla/coverage/app.js.html +++ /dev/null @@ -1,856 +0,0 @@ - - - - - - Code coverage report for app.js - - - - - - - - - -
-
-

All files app.js

-
- -
- 84.91% - Statements - 152/179 -
- - -
- 65.26% - Branches - 62/95 -
- - -
- 69.23% - Functions - 18/26 -
- - -
- 88.66% - Lines - 133/150 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -2581x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -5x -5x -4x -4x -4x -4x -  -1x -1x -1x -1x -  -  -  -  -11x -11x -  -11x -11x -11x -11x -11x -11x -  -11x -5x -  -  -11x -11x -10x -10x -10x -10x -  -1x -1x -1x -  -  -  -  -5x -5x -  -  -5x -5x -5x -  -5x -5x -5x -5x -5x -1x -1x -1x -1x -  -5x -  -5x -5x -5x -5x -5x -1x -1x -1x -1x -  -5x -  -5x -5x -5x -5x -5x -1x -1x -1x -1x -  -5x -  -5x -5x -3x -3x -3x -3x -3x -5x -1x -1x -1x -1x -  -3x -  -  -  -  -  -12x -12x -12x -  -12x -10x -10x -  -  -2x -2x -2x -  -2x -  -2x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -2x -2x -  -2x -2x -  -2x -  -  -  -  -1x -1x -1x -  -  -  -  -1x -  -  -1x -1x -1x -  -  -1x -  -1x -  -  -  -  -  -  -  -  -1x -1x -1x -  -  -  -  -1x -  -  -1x -1x -1x -1x -  -  -1x -  -  -1x -1x -1x -1x -1x -1x -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -  -4x -  -4x -3x -3x -  -3x -3x -3x -2x -2x -2x -1x -1x -1x -1x -  -  -  -  -  -  -  - 
document.addEventListener('DOMContentLoaded', () => {
-    fetchFeeds();
-    fetchItems(); // Default to fetching recent items
- 
-    const searchInput = document.getElementById('search-input');
-    searchInput.addEventListener('keypress', (e) => {
-        if (e.key === 'Enter') {
-            const query = searchInput.value.trim();
-            if (query) {
-                document.getElementById('feed-title').textContent = `Search: ${query}`;
-                document.querySelectorAll('.feed-item').forEach(el => el.classList.remove('active'));
-                fetchItems(null, null, query);
-            }
-        }
-    });
-});
- 
-export async function fetchFeeds(apiBase = '') {
-    try {
-        const response = await fetch(`${apiBase}/api/feed/`);
-        Iif (!response.ok) throw new Error('Failed to fetch feeds');
-        const feeds = await response.json();
-        renderFeeds(feeds);
-        return feeds;
-    } catch (err) {
-        console.error(err);
-        const nav = document.getElementById('feeds-nav');
-        Eif (nav) nav.innerHTML = '<div class="error">Error loading feeds</div>';
-        throw err;
-    }
-}
- 
-export async function fetchItems(feedId = null, filter = null, query = null, apiBase = '') {
-    const listEl = document.getElementById('entries-list');
-    Eif (listEl) listEl.innerHTML = '<div class="loading">Loading items...</div>';
- 
-    let url = `${apiBase}/api/stream/`;
-    const params = new URLSearchParams();
-    if (feedId) params.append('feed_id', feedId);
-    if (filter === 'unread') params.append('read_filter', 'unread');
-    if (filter === 'starred') params.append('starred', 'true');
-    if (query) params.append('q', query);
- 
-    if ([...params].length > 0) {
-        url += '?' + params.toString();
-    }
- 
-    try {
-        const response = await fetch(url);
-        Iif (!response.ok) throw new Error('Failed to fetch items');
-        const items = await response.json();
-        renderItems(items);
-        return items;
-    } catch (err) {
-        console.error(err);
-        Eif (listEl) listEl.innerHTML = '<div class="error">Error loading items</div>';
-        throw err;
-    }
-}
- 
-export function renderFeeds(feeds) {
-    const nav = document.getElementById('feeds-nav');
-    Iif (!nav) return;
- 
-    // Clear existing items but keep search container if present
-    const searchContainer = nav.querySelector('.search-container');
-    nav.innerHTML = '';
-    Eif (searchContainer) nav.appendChild(searchContainer);
- 
-    const allLink = document.createElement('div');
-    allLink.className = 'feed-item';
-    allLink.textContent = 'All Items';
-    allLink.onclick = () => {
-        document.querySelectorAll('.feed-item').forEach(el => el.classList.remove('active'));
-        allLink.classList.add('active');
-        const title = document.getElementById('feed-title');
-        Eif (title) title.textContent = 'All Items';
-        fetchItems();
-    };
-    nav.appendChild(allLink);
- 
-    const unreadLink = document.createElement('div');
-    unreadLink.className = 'feed-item';
-    unreadLink.textContent = 'Unread Items';
-    unreadLink.onclick = () => {
-        document.querySelectorAll('.feed-item').forEach(el => el.classList.remove('active'));
-        unreadLink.classList.add('active');
-        const title = document.getElementById('feed-title');
-        Eif (title) title.textContent = 'Unread Items';
-        fetchItems(null, 'unread');
-    };
-    nav.appendChild(unreadLink);
- 
-    const starredLink = document.createElement('div');
-    starredLink.className = 'feed-item';
-    starredLink.textContent = 'Starred Items';
-    starredLink.onclick = () => {
-        document.querySelectorAll('.feed-item').forEach(el => el.classList.remove('active'));
-        starredLink.classList.add('active');
-        const title = document.getElementById('feed-title');
-        Eif (title) title.textContent = 'Starred Items';
-        fetchItems(null, 'starred');
-    };
-    nav.appendChild(starredLink);
- 
-    Eif (Array.isArray(feeds)) {
-        feeds.forEach(feed => {
-            const div = document.createElement('div');
-            div.className = 'feed-item';
-            div.textContent = feed.title || feed.url;
-            div.title = feed.url;
-            div.onclick = () => {
-                document.querySelectorAll('.feed-item').forEach(el => el.classList.remove('active'));
-                div.classList.add('active');
-                const title = document.getElementById('feed-title');
-                Eif (title) title.textContent = feed.title;
-                fetchItems(feed.id);
-            };
-            nav.appendChild(div);
-        });
-    }
-}
- 
-export function renderItems(items) {
-    const list = document.getElementById('entries-list');
-    Iif (!list) return;
-    list.innerHTML = '';
- 
-    if (!items || items.length === 0) {
-        list.innerHTML = '<div class="empty">No items found.</div>';
-        return;
-    }
- 
-    items.forEach(item => {
-        const article = document.createElement('article');
-        article.className = 'entry';
- 
-        const date = new Date(item.published_at || item.created_at).toLocaleString();
- 
-        article.innerHTML = `
-            <header class="entry-header">
-                <div class="entry-controls">
-                    <button class="btn-star ${item.starred ? 'active' : ''}" data-id="${item.id}" data-starred="${item.starred}">${item.starred ? '★' : '☆'}</button>
-                    <button class="btn-read ${item.read ? 'read' : 'unread'}" data-id="${item.id}" data-read="${item.read}">${item.read ? 'Mark Unread' : 'Mark Read'}</button>
-                </div>
-                <a href="${item.url}" class="entry-title ${item.read ? 'read' : ''}" target="_blank">${item.title}</a>
-                <div class="entry-meta">
-                    ${item.feed ? `<span class="feed-name">${item.feed.title}</span> • ` : ''}
-                    <span class="date">${date}</span>
-                </div>
-            </header>
-            <div class="entry-content">
-                ${item.description || ''}
-            </div>
-        `;
- 
-        // Add event listeners programmatically to avoid inline onclick with modules
-        const starBtn = article.querySelector('.btn-star');
-        starBtn.onclick = () => toggleStar(item.id, item.starred, starBtn);
- 
-        const readBtn = article.querySelector('.btn-read');
-        readBtn.onclick = () => toggleRead(item.id, item.read, readBtn);
- 
-        list.appendChild(article);
-    });
-}
- 
-export async function toggleStar(id, currentStatus, btn, apiBase = '') {
-    const newStatus = !currentStatus;
-    try {
-        const response = await fetch(`${apiBase}/api/item/${id}`, {
-            method: 'PUT',
-            headers: { 'Content-Type': 'application/json' },
-            body: JSON.stringify({ id: id, starred: newStatus })
-        });
-        Iif (!response.ok) throw new Error('Failed to toggle star');
- 
-        // Update UI
-        btn.textContent = newStatus ? '★' : '☆';
-        btn.classList.toggle('active');
-        btn.onclick = () => toggleStar(id, newStatus, btn, apiBase);
- 
-        // Update data attributes
-        btn.dataset.starred = newStatus;
- 
-        return newStatus;
-    } catch (err) {
-        console.error(err);
-        alert('Error toggling star');
-        throw err;
-    }
-}
- 
-export async function toggleRead(id, currentStatus, btn, apiBase = '') {
-    const newStatus = !currentStatus;
-    try {
-        const response = await fetch(`${apiBase}/api/item/${id}`, {
-            method: 'PUT',
-            headers: { 'Content-Type': 'application/json' },
-            body: JSON.stringify({ id: id, read: newStatus })
-        });
-        Iif (!response.ok) throw new Error('Failed to toggle read');
- 
-        // Update UI
-        btn.textContent = newStatus ? 'Mark Unread' : 'Mark Read';
-        btn.classList.toggle('read');
-        btn.classList.toggle('unread');
-        btn.onclick = () => toggleRead(id, newStatus, btn, apiBase);
- 
-        // Update data attributes
-        btn.dataset.read = newStatus;
- 
-        // Find title and dim it if read
-        const header = btn.closest('.entry-header');
-        Eif (header) {
-            const title = header.querySelector('.entry-title');
-            Eif (title) {
-                if (newStatus) {
-                    title.classList.add('read');
-                } else E{
-                    title.classList.remove('read');
-                }
-            }
-        }
- 
-        return newStatus;
-    } catch (err) {
-        console.error(err);
-        alert('Error toggling read status');
-        throw err;
-    }
-}
- 
-export function init() {
-    Eif (typeof document !== 'undefined') {
-        // Only run if we're in a browser environment with these elements
-        if (document.getElementById('feeds-nav')) {
-            fetchFeeds();
-            fetchItems();
- 
-            const searchInput = document.getElementById('search-input');
-            Eif (searchInput) {
-                searchInput.addEventListener('keypress', (e) => {
-                    Eif (e.key === 'Enter') {
-                        const query = searchInput.value.trim();
-                        if (query) {
-                            const title = document.getElementById('feed-title');
-                            Eif (title) title.textContent = `Search: ${query}`;
-                            document.querySelectorAll('.feed-item').forEach(el => el.classList.remove('active'));
-                            fetchItems(null, null, query);
-                        }
-                    }
-                });
-            }
-        }
-    }
-}
- 
- -
-
- - - - - - - - \ No newline at end of file -- cgit v1.2.3