Add breadcrumbs feature for improved navigation

The commit introduces a new breadcrumbs.js file, which creates a breadcrumb functionality to improve the app's navigation. The rendered breadcrumbs allow users to keep track of their current directory path and navigate back to previous directories by clicking on the breadcrumb links. This function is also integrated into the main application in index.js.
In addition, changes have been made in 'navigation.js' to include 'exists' method for better directory existence checking before navigation.
Some updates are made in 'favourites.js' to simplify and improve the rendering of favourites. Modifications in 'index.html' support the new breadcrumb feature.
Overall, these changes significantly improve user experience and navigation efficiency.
This commit is contained in:
Ian Wijma 2023-11-27 16:34:30 +11:00
parent f276f686a9
commit e3716d7e89
5 changed files with 89 additions and 37 deletions

View File

@ -16,16 +16,14 @@
</span> </span>
<span class="flex"> <span class="flex">
<div> <div data-ui="breadcrumbs" class="flex gap-0 before:content-['/']"></div>
path / to / memes
</div>
<button>Search</button> <button>Search</button>
</span> </span>
<span class="flex"> <span class="flex">
<button>List</button> <button data-ui="view-list">List</button>
<button>Panel</button> <button data-ui="view-panel">Panel</button>
<button>Column</button> <button data-ui="view-column">Column</button>
</span> </span>
</header> </header>
<div class="h-full flex"> <div class="h-full flex">
@ -42,7 +40,7 @@
<button data-ui="add-favourite">+ Add favourite</button> <button data-ui="add-favourite">+ Add favourite</button>
</li> </li>
</menu> </menu>
<main class="bg-red-500 h-full w-full" id="ui-files"></main> <main class="bg-red-500 h-full w-full" data-ui="files"></main>
</div> </div>
<template data-template="favourites"> <template data-template="favourites">
@ -51,5 +49,9 @@
<button data-el="remove" class="w-8">x</button> <button data-el="remove" class="w-8">x</button>
</li> </li>
</template> </template>
<template data-template="breadcrumbs">
<button data-el="action" class="after:content-['/']"></button>
</template>
</body> </body>
</html> </html>

View File

@ -1,7 +1,9 @@
import {renderFavourite} from "./parts/favourites.js"; import {renderFavourite} from "./parts/favourites.js";
import {renderBreadcrumbs} from "./parts/breadcrumbs.js";
async function Main() { async function Main() {
renderBreadcrumbs();
renderFavourite(); renderFavourite();
} }

View File

@ -1,5 +1,5 @@
import {homeDir} from "./path.js"; import {homeDir} from "./path.js";
import {readDir} from "./fs.js"; import {exists, readDir} from "./fs.js";
const eventBus = new Comment(); const eventBus = new Comment();
@ -7,23 +7,48 @@ const NAVIGATE_EVENT = 'navigate';
let currentDir = await homeDir(); let currentDir = await homeDir();
/**
* @param {function} callback
*/
export const onNavigate = (callback) => eventBus.addEventListener( export const onNavigate = (callback) => eventBus.addEventListener(
NAVIGATE_EVENT, NAVIGATE_EVENT,
() => callback(currentDir) () => callback(currentDir)
); );
/**
* @param {function} callback
*/
export const onceNavigate = (callback) => eventBus.addEventListener( export const onceNavigate = (callback) => eventBus.addEventListener(
NAVIGATE_EVENT, NAVIGATE_EVENT,
() => callback(currentDir), () => callback(currentDir),
{ once: true } { once: true }
); );
export const navigate = (toDir) => {
/**
* @param {string} toDir
*/
export const navigate = async (toDir) => {
const dirExists =await exists(toDir);
if (!dirExists) throw new Error(`Target dir does not exists: ${toDir}`);
if (!toDir.endsWith('/')) {
toDir = toDir + '/'
}
currentDir = toDir; currentDir = toDir;
eventBus.dispatchEvent(new CustomEvent(NAVIGATE_EVENT)) eventBus.dispatchEvent(new CustomEvent(NAVIGATE_EVENT))
} }
/**
* @returns {string}
*/
export const getCurrentDir = () => currentDir;
const logDir = async () => console.log({ const logDir = async () => console.log({
currentDir, currentDir,
items: await readDir(currentDir) items: await readDir(currentDir)
}); });
onNavigate(logDir); onNavigate(logDir);
logDir();

28
src/parts/breadcrumbs.js Normal file
View File

@ -0,0 +1,28 @@
import {getOneElementOrThrow} from "../libs/element.js";
import {getCurrentDir, navigate, onceNavigate} from "../libs/navigation.js";
import {sep} from "../libs/path.js";
import {getTemplate} from "../libs/template.js";
export const renderBreadcrumbs = () => {
const breadcrumbsEl = getOneElementOrThrow(document, '[data-ui=breadcrumbs]');
breadcrumbsEl.innerHTML = '';
const currentDir = getCurrentDir();
const currentDirSplit = currentDir.split(sep);
currentDirSplit.map((value, index, array) => {
if (value) {
const restSplit = [...array].reverse().splice(array.length - (index + 1)).reverse();
const path = restSplit.join(sep);
const template = getTemplate('breadcrumbs');
const actionEl = template.el('action');
actionEl.innerText = value;
actionEl.addEventListener('click', () => navigate(path));
breadcrumbsEl.appendChild(template.render());
}
});
onceNavigate(() => renderBreadcrumbs());
}

View File

@ -4,36 +4,31 @@ import {getTemplate} from "../libs/template.js";
import {navigate} from "../libs/navigation.js"; import {navigate} from "../libs/navigation.js";
export const renderFavourite = () => { export const renderFavourite = () => {
const updateFavourites = (favouritesArray) => { const favouriteList = getOneElementOrThrow(document, '[data-ui=favourites]');
const favouriteList = getOneElementOrThrow(document, '[data-ui=favourites]');
const addedItems = getElements(favouriteList, '[data-el=added]'); const addedItems = getElements(favouriteList, '[data-el=added]');
addedItems.forEach(addedItems => addedItems.remove()); addedItems.forEach(addedItems => addedItems.remove());
favouritesArray.forEach(({ name, path, system }, index) => {
const template = getTemplate('favourites');
const actionEl = template.el('action');
actionEl.textContent = name;
actionEl.addEventListener('click', () => navigate(path));
const removeEl = template.el('remove');
if (system) {
removeEl.remove();
} else {
removeEl.addEventListener('click', () => {
removeFavouriteByIndex(index);
renderFavourite();
});
}
favouriteList.appendChild(template.render());
});
}
const favourites = getFavourites(); const favourites = getFavourites();
updateFavourites(favourites); favourites.forEach(({ name, path, system }, index) => {
const template = getTemplate('favourites');
const actionEl = template.el('action');
actionEl.textContent = name;
actionEl.addEventListener('click', () => navigate(path));
const removeEl = template.el('remove');
if (system) {
removeEl.remove();
} else {
removeEl.addEventListener('click', () => {
removeFavouriteByIndex(index);
renderFavourite();
});
}
favouriteList.appendChild(template.render());
});
const addEl = getOneElementOrThrow(document, '[data-ui=add-favourite]'); const addEl = getOneElementOrThrow(document, '[data-ui=add-favourite]');