mirror of
https://github.com/karl0ss/homepage.git
synced 2025-04-29 12:03:41 +01:00
Enhancement: apply layout settings to bookmarks (#1902)
* Apply layout settings to bookmarks * merge columnMap const * Remove bookmarksOnTop setting --------- Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
This commit is contained in:
parent
4d55f1fba4
commit
9529553102
@ -5,38 +5,58 @@ import { MdKeyboardArrowDown } from "react-icons/md";
|
||||
|
||||
import ErrorBoundary from "components/errorboundry";
|
||||
import List from "components/bookmarks/list";
|
||||
import ResolvedIcon from "components/resolvedicon";
|
||||
|
||||
export default function BookmarksGroup({ group, disableCollapse }) {
|
||||
export default function BookmarksGroup({ bookmarks, layout, disableCollapse }) {
|
||||
const panel = useRef();
|
||||
return (
|
||||
<div key={group.name} className="flex-1">
|
||||
<div
|
||||
key={bookmarks.name}
|
||||
className={classNames(
|
||||
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6",
|
||||
layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1"
|
||||
)}
|
||||
>
|
||||
<Disclosure defaultOpen>
|
||||
{({ open }) => (
|
||||
<>
|
||||
{layout?.header !== false && (
|
||||
<Disclosure.Button disabled={disableCollapse} className="flex w-full select-none items-center group">
|
||||
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{group.name}</h2>
|
||||
<MdKeyboardArrowDown className={classNames(
|
||||
disableCollapse ? 'hidden' : '',
|
||||
'transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
|
||||
open ? '' : 'rotate-180'
|
||||
)} />
|
||||
{layout?.icon && (
|
||||
<div className="flex-shrink-0 mr-2 w-7 h-7">
|
||||
<ResolvedIcon icon={layout.icon} />
|
||||
</div>
|
||||
)}
|
||||
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{bookmarks.name}</h2>
|
||||
<MdKeyboardArrowDown
|
||||
className={classNames(
|
||||
disableCollapse ? "hidden" : "",
|
||||
"transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl",
|
||||
open ? "" : "rotate-180"
|
||||
)}
|
||||
/>
|
||||
</Disclosure.Button>
|
||||
)}
|
||||
<Transition
|
||||
// Otherwise the transition group does display: none and cancels animation
|
||||
className="!block"
|
||||
unmount={false}
|
||||
beforeLeave={() => {
|
||||
panel.current.style.height = `${panel.current.scrollHeight}px`;
|
||||
setTimeout(() => {panel.current.style.height = `0`}, 1);
|
||||
setTimeout(() => {
|
||||
panel.current.style.height = `0`;
|
||||
}, 1);
|
||||
}}
|
||||
beforeEnter={() => {
|
||||
panel.current.style.height = `0px`;
|
||||
setTimeout(() => {panel.current.style.height = `${panel.current.scrollHeight}px`}, 1);
|
||||
setTimeout(() => {
|
||||
panel.current.style.height = `${panel.current.scrollHeight}px`;
|
||||
}, 1);
|
||||
}}
|
||||
>
|
||||
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
|
||||
<ErrorBoundary>
|
||||
<List bookmarks={group.bookmarks} />
|
||||
<List bookmarks={bookmarks.bookmarks} layout={layout} />
|
||||
</ErrorBoundary>
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
|
@ -1,8 +1,17 @@
|
||||
import classNames from "classnames";
|
||||
|
||||
import { columnMap } from "../../utils/layout/columns";
|
||||
|
||||
import Item from "components/bookmarks/item";
|
||||
|
||||
export default function List({ bookmarks }) {
|
||||
export default function List({ bookmarks, layout }) {
|
||||
return (
|
||||
<ul className="mt-3 flex flex-col">
|
||||
<ul
|
||||
className={classNames(
|
||||
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
|
||||
"mt-3"
|
||||
)}
|
||||
>
|
||||
{bookmarks.map((bookmark) => (
|
||||
<Item key={`${bookmark.name}-${bookmark.href}`} bookmark={bookmark} />
|
||||
))}
|
||||
|
@ -1,18 +1,8 @@
|
||||
import classNames from "classnames";
|
||||
|
||||
import Item from "components/services/item";
|
||||
import { columnMap } from "../../utils/layout/columns";
|
||||
|
||||
const columnMap = [
|
||||
"grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
|
||||
"grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-2",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-5",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-6",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-7",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-8",
|
||||
];
|
||||
import Item from "components/services/item";
|
||||
|
||||
export default function List({ group, services, layout }) {
|
||||
return (
|
||||
|
@ -209,7 +209,7 @@ function Home({ initialSettings }) {
|
||||
searchProvider = searchProviders[searchWidget.options?.provider];
|
||||
}
|
||||
}
|
||||
const headerStyle = initialSettings?.headerStyle || "underlined";
|
||||
const headerStyle = settings?.headerStyle || "underlined";
|
||||
|
||||
useEffect(() => {
|
||||
function handleKeyDown(e) {
|
||||
@ -233,12 +233,12 @@ function Home({ initialSettings }) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{initialSettings.title || "Homepage"}</title>
|
||||
{initialSettings.base && <base href={initialSettings.base} />}
|
||||
{initialSettings.favicon ? (
|
||||
<title>{settings.title || "Homepage"}</title>
|
||||
{settings.base && <base href={settings.base} />}
|
||||
{settings.favicon ? (
|
||||
<>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href={initialSettings.favicon} />
|
||||
<link rel="icon" href={initialSettings.favicon} />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href={settings.favicon} />
|
||||
<link rel="icon" href={settings.favicon} />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
@ -248,11 +248,8 @@ function Home({ initialSettings }) {
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png?v=4" />
|
||||
</>
|
||||
)}
|
||||
<meta
|
||||
name="msapplication-TileColor"
|
||||
content={themes[initialSettings.color || "slate"][initialSettings.theme || "dark"]}
|
||||
/>
|
||||
<meta name="theme-color" content={themes[initialSettings.color || "slate"][initialSettings.theme || "dark"]} />
|
||||
<meta name="msapplication-TileColor" content={themes[settings.color || "slate"][settings.theme || "dark"]} />
|
||||
<meta name="theme-color" content={themes[settings.color || "slate"][settings.theme || "dark"]} />
|
||||
</Head>
|
||||
<div className="relative container m-auto flex flex-col justify-start z-10 h-full">
|
||||
<QuickLaunch
|
||||
@ -267,7 +264,7 @@ function Home({ initialSettings }) {
|
||||
className={classNames(
|
||||
"flex flex-row flex-wrap justify-between",
|
||||
headerStyles[headerStyle],
|
||||
initialSettings.cardBlur !== undefined && headerStyle === "boxed" && `backdrop-blur${initialSettings.cardBlur.length ? '-' : ""}${initialSettings.cardBlur}`
|
||||
settings.cardBlur !== undefined && headerStyle === "boxed" && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`
|
||||
)}
|
||||
>
|
||||
{widgets && (
|
||||
@ -275,7 +272,7 @@ function Home({ initialSettings }) {
|
||||
{widgets
|
||||
.filter((widget) => !rightAlignedWidgets.includes(widget.type))
|
||||
.map((widget, i) => (
|
||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: false, cardBlur: initialSettings.cardBlur }} />
|
||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: false, cardBlur: settings.cardBlur }} />
|
||||
))}
|
||||
|
||||
<div className={classNames(
|
||||
@ -285,7 +282,7 @@ function Home({ initialSettings }) {
|
||||
{widgets
|
||||
.filter((widget) => rightAlignedWidgets.includes(widget.type))
|
||||
.map((widget, i) => (
|
||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: true, cardBlur: initialSettings.cardBlur }} />
|
||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: true, cardBlur: settings.cardBlur }} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
@ -293,39 +290,42 @@ function Home({ initialSettings }) {
|
||||
</div>
|
||||
|
||||
{services?.length > 0 && (
|
||||
<div className="flex flex-wrap p-4 sm:p-8 sm:pt-4 items-start pb-2">
|
||||
<div key="services" className="flex flex-wrap p-4 sm:p-8 sm:pt-4 items-start pb-2">
|
||||
{services.map((group) => (
|
||||
<ServicesGroup
|
||||
key={group.name}
|
||||
group={group.name}
|
||||
services={group}
|
||||
layout={initialSettings.layout?.[group.name]}
|
||||
layout={settings.layout?.[group.name]}
|
||||
fiveColumns={settings.fiveColumns}
|
||||
disableCollapse={settings.disableCollapse} />
|
||||
disableCollapse={settings.disableCollapse}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bookmarks?.length > 0 && (
|
||||
<div className={`grow flex flex-wrap pt-0 p-4 sm:p-8 gap-2 grid-cols-1 lg:grid-cols-2 lg:grid-cols-${Math.min(6, bookmarks.length)}`}>
|
||||
<div key="bookmarks" className="flex flex-wrap p-4 sm:p-8 sm:pt-4 items-start pb-2">
|
||||
{bookmarks.map((group) => (
|
||||
<BookmarksGroup
|
||||
key={group.name}
|
||||
group={group}
|
||||
disableCollapse={settings.disableCollapse} />
|
||||
bookmarks={group}
|
||||
layout={settings.layout?.[group.name]}
|
||||
disableCollapse={settings.disableCollapse}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col mt-auto p-8 w-full">
|
||||
<div className="flex w-full justify-end">
|
||||
{!initialSettings?.color && <ColorToggle />}
|
||||
{!settings?.color && <ColorToggle />}
|
||||
<Revalidate />
|
||||
{!initialSettings?.theme && <ThemeToggle />}
|
||||
{!settings.theme && <ThemeToggle />}
|
||||
</div>
|
||||
|
||||
<div className="flex mt-4 w-full justify-end">
|
||||
{!initialSettings?.hideVersion && <Version />}
|
||||
{!settings.hideVersion && <Version />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -34,6 +34,16 @@ export async function bookmarksResponse() {
|
||||
|
||||
if (!bookmarks) return [];
|
||||
|
||||
let initialSettings;
|
||||
|
||||
try {
|
||||
initialSettings = await getSettings();
|
||||
} catch (e) {
|
||||
console.error("Failed to load settings.yaml, please check for errors");
|
||||
if (e) console.error(e.toString());
|
||||
initialSettings = {};
|
||||
}
|
||||
|
||||
// map easy to write YAML objects into easy to consume JS arrays
|
||||
const bookmarksArray = bookmarks.map((group) => ({
|
||||
name: Object.keys(group)[0],
|
||||
@ -43,7 +53,21 @@ export async function bookmarksResponse() {
|
||||
})),
|
||||
}));
|
||||
|
||||
return bookmarksArray;
|
||||
const sortedGroups = [];
|
||||
const unsortedGroups = [];
|
||||
const definedLayouts = initialSettings.layout ? Object.keys(initialSettings.layout) : null;
|
||||
|
||||
bookmarksArray.forEach((group) => {
|
||||
if (definedLayouts) {
|
||||
const layoutIndex = definedLayouts.findIndex(layout => layout === group.name);
|
||||
if (layoutIndex > -1) sortedGroups[layoutIndex] = group;
|
||||
else unsortedGroups.push(group);
|
||||
} else {
|
||||
unsortedGroups.push(group);
|
||||
}
|
||||
});
|
||||
|
||||
return [...sortedGroups.filter(g => g), ...unsortedGroups];
|
||||
}
|
||||
|
||||
export async function widgetsResponse() {
|
||||
|
12
src/utils/layout/columns.js
Normal file
12
src/utils/layout/columns.js
Normal file
@ -0,0 +1,12 @@
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const columnMap = [
|
||||
"grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
|
||||
"grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-2",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-5",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-6",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-7",
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-8",
|
||||
];
|
@ -59,5 +59,16 @@ module.exports = {
|
||||
'backdrop-brightness-125',
|
||||
'backdrop-brightness-150',
|
||||
'backdrop-brightness-200',
|
||||
'grid-cols-1',
|
||||
'md:grid-cols-1',
|
||||
'md:grid-cols-2',
|
||||
'lg:grid-cols-1',
|
||||
'lg:grid-cols-2',
|
||||
'lg:grid-cols-3',
|
||||
'lg:grid-cols-4',
|
||||
'lg:grid-cols-5',
|
||||
'lg:grid-cols-6',
|
||||
'lg:grid-cols-7',
|
||||
'lg:grid-cols-8',
|
||||
],
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user