diff --git a/e2e/navigation.spec.js b/e2e/navigation.spec.js index 840e44c..cc987b0 100644 --- a/e2e/navigation.spec.js +++ b/e2e/navigation.spec.js @@ -72,3 +72,19 @@ test('Abos & Quellen: one page for every subscription, reached from the feeds to await tab.locator('[data-filter="all"]').click(); await expect(tab.locator('.src-chip.on')).toContainText('Alle'); }); + +test('the library: a header with search, sort, layout and +, the add menu', async ({ page }) => { + await page.setViewportSize({ width: 1200, height: 800 }); + await page.goto('/#books'); + const list = page.locator('#book-list'); + await expect(list.locator('.lib-h')).toHaveText('Bücher'); + await expect(list.locator('.lib-q')).toBeVisible(); + await expect(list.locator('.lib-sort')).toBeVisible(); + await expect(page.locator('#book-drop-zone')).toBeHidden(); // adding is behind + + await list.locator('[data-lib="add"]').click(); + await expect(page.locator('.dfo-sheet')).toContainText('E-Book-Datei'); + await page.locator('.dfo-sheet [data-x]').click(); + await expect(page.locator('.dfo-sheet')).toHaveCount(0); + await page.goto('/#magazines'); + await expect(list.locator('.lib-h')).toHaveText('Zeitschriften'); +}); diff --git a/static/js/app/52-book-list.js b/static/js/app/52-book-list.js index 0f592a1..ff8b34b 100644 --- a/static/js/app/52-book-list.js +++ b/static/js/app/52-book-list.js @@ -29,6 +29,8 @@ async function loadBookList() { return; } if (!books.length) { + // Drawn like any list: the page's header (with +) is how a first book gets in. + if (window.__dioraLibraryV2) { renderBookList([]); return; } listEl.innerHTML = '

Noch keine Bücher. Zieh oben eine .epub- oder .pdf-Datei hinein.

'; return; } diff --git a/static/js/feeds.js b/static/js/feeds.js index c86d83a..a29ea0c 100644 --- a/static/js/feeds.js +++ b/static/js/feeds.js @@ -309,7 +309,9 @@ (sum(list, 'unread') ? ' ' + sum(list, 'unread') + '' : '') + ''; h += '
' + chip(null, 'Alle', visible) + folders.map(f => chip(f, f, inFolder(f))).join('') + - (blogs.some(b => !(b.folders || []).length) ? chip('', 'Ohne Ordner', inFolder('')) : '') + '
'; + (blogs.some(b => !(b.folders || []).length) ? chip('', 'Ohne Ordner', inFolder('')) : '') + + (window.DioraFolders ? '' : '') + + ''; } const main = st.blogFolder === null; const shown = main ? blogs : inFolder(st.blogFolder); @@ -336,6 +338,7 @@ (one.hidden ? 'Im Hauptfeed ausgeblendet' : 'Im Hauptfeed ausblenden') + '' + '' + + (window.DioraFolders ? '' : '') + ''; } if (!st.items.length) return h + '

' + (st.loading ? 'Lädt …' : (st.blogUnread ? 'Alles gelesen.' : 'Keine Artikel.')) + '

'; @@ -823,6 +826,42 @@ try { await api('/feeds/refresh/', {}); } catch (err) {} return load(); } + // Folders the same way as everywhere (folders.js, docs/library.md). + if (act === 'folders-manage' && window.DioraFolders) { + const done = () => loadState().catch(() => {}).then(() => (st.view === 'blogs' ? load() : render())); + window.DioraFolders.manage({ + title: 'Ordner der Blogs', + folders: (st.state && st.state.folders) || [], + onRename: (name, neu) => api('/feeds/folders/rename/', {name, new: neu}).catch(() => {}).then(() => { + if (st.blogFolder !== null && st.blogFolder.toLowerCase() === name.toLowerCase()) st.blogFolder = neu; + return done(); + }), + onDelete: name => api('/feeds/folders/dissolve/', {name}).catch(() => {}).then(() => { + if (st.blogFolder !== null && st.blogFolder.toLowerCase() === name.toLowerCase()) st.blogFolder = null; + return done(); + }), + onOrder: order => api('/feeds/folders/order/', {order}).then(d => { + if (st.state && d && d.folders) st.state.folders = d.folders; + render(); + }).catch(() => {}), + }); + return; + } + if (act === 'blog-folders' && window.DioraFolders) { + const src = sources().find(x => x.id === parseInt(t.dataset.id, 10)); + if (!src) return; + window.DioraFolders.assign({ + title: 'Ordner für „' + src.title + '“', + folders: (st.state && st.state.folders) || [], + selected: src.folders || [], + onDone: async names => { + await api('/feeds/sources/' + src.id + '/', {folders: names}).catch(() => {}); + await loadState().catch(() => {}); + load(); + }, + }); + return; + } if (act === 'manage') { // Managing every subscription has its place (Abos & Quellen, docs/sources.md). const nav = window.DioraNav;