From a47f201fff2390264d21215d5984299cb9cf6dad Mon Sep 17 00:00:00 2001 From: Sean Edmunds Date: Thu, 15 Aug 2024 15:12:05 -0500 Subject: [PATCH] Styled Homepage --- src/App.css | 40 ------ src/App.tsx | 60 ++++++--- src/DataTable/DataTable.tsx | 7 -- src/DataTable/columns/ApplicationColumns.tsx | 20 ++- src/DataTable/columns/BookmarkColumns.tsx | 14 +-- src/DataTable/columns/CategoryColumns.tsx | 67 ++++++++++ src/DataTable/columns/MessagesColumns.tsx | 11 +- .../columns/PersonalizationColumns.tsx | 11 +- .../columns/SearchProviderColumns.tsx | 63 ++++++++++ src/components/ThemeProvider.tsx | 11 ++ src/index.css | 79 +----------- src/main.tsx | 16 ++- src/pages/homepage/Homepage.tsx | 19 ++- .../homepage/components/Applications.tsx | 4 +- src/pages/homepage/components/Bookmarks.tsx | 6 +- src/pages/homepage/components/Header.tsx | 1 + src/pages/homepage/components/Search.tsx | 4 +- .../homepage/components/SettingsButton.tsx | 53 +++----- src/pages/settings/Settings.tsx | 17 +-- .../settings/components/Applications.tsx | 2 +- src/pages/settings/components/Bookmarks.tsx | 4 +- src/pages/settings/components/Categories.tsx | 59 +++++++++ src/pages/settings/components/Messages.tsx | 2 +- .../settings/components/Personalization.tsx | 2 +- .../settings/components/SearchProviders.tsx | 59 +++++++++ src/pages/settings/components/Themes.tsx | 87 +++++++++++++ src/styles/Button.module.css | 5 + src/styles/Menu.module.css | 12 +- src/styles/NavLink.module.css | 42 +++---- src/styles/Select.module.css | 35 +++++- src/styles/Stack.module.css | 2 +- src/styles/Text.module.css | 15 ++- src/styles/TextInput.module.css | 114 ++++++++---------- 33 files changed, 588 insertions(+), 355 deletions(-) delete mode 100644 src/App.css create mode 100644 src/DataTable/columns/CategoryColumns.tsx create mode 100644 src/DataTable/columns/SearchProviderColumns.tsx create mode 100644 src/components/ThemeProvider.tsx create mode 100644 src/pages/settings/components/SearchProviders.tsx diff --git a/src/App.css b/src/App.css deleted file mode 100644 index 6ea83fe..0000000 --- a/src/App.css +++ /dev/null @@ -1,40 +0,0 @@ -#root { - width: 100%; - height: 100%; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} diff --git a/src/App.tsx b/src/App.tsx index 1503a63..cfedfdc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,43 +1,65 @@ -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import './App.css' import Homepage from './pages/homepage/Homepage' -import { MantineProvider } from '@mantine/core' +import { MantineProvider, DEFAULT_THEME, createTheme, mergeMantineTheme } from '@mantine/core' import { Route, createBrowserRouter, createRoutesFromElements, RouterProvider, - Navigate, } from "react-router-dom"; import Settings from './pages/settings/Settings'; +import { ModalsProvider } from '@mantine/modals'; +import { useLocalStorage } from '@mantine/hooks'; +import { useEffect, useState } from 'react'; +import { useQueryAPI } from './hooks/useAPI'; +import ThemeProvider from './components/ThemeProvider'; +import '@mantine/core/styles.css'; //import Mantine V7 styles needed by MRT +import '@mantine/dates/styles.css'; //if using mantine date picker features +import 'mantine-react-table/styles.css'; //import MRT styles function App() { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - gcTime: 1000 * 60 * 60 * 24, // 24 hours - staleTime: 1000 * 60 * 1, // 1 min - }, - }, + + const { data, isFetched } = useQueryAPI({ + endpoint: "api/themes", + }); + + const [themeName, setThemeName] = useLocalStorage({ + key: 'theme', + defaultValue: 'blackboard', + }); + + const [currentTheme, setCurrentTheme] = useState({}); + + const overrides = createTheme({ + white:currentTheme.colorbackground, + fontFamily: '-apple-system,Jost,BlinkMacSystemFont,Helvetica Neue,Roboto,sans-serif', }); + const mantineTheme = mergeMantineTheme(DEFAULT_THEME, overrides); + + useEffect(() => { + if(data && themeName) { + let temp = data.find((t: any) => t.name === themeName) + setCurrentTheme(temp); + } + }, [isFetched, themeName]) + const router = createBrowserRouter( createRoutesFromElements( - }> - }> + } /> + } /> , ), ); return ( - - - + + + + + + - ) } diff --git a/src/DataTable/DataTable.tsx b/src/DataTable/DataTable.tsx index bb0d90f..17a1758 100644 --- a/src/DataTable/DataTable.tsx +++ b/src/DataTable/DataTable.tsx @@ -1,10 +1,5 @@ -import { ModalsProvider } from "@mantine/modals"; import { MantineReactTable, useMantineReactTable } from "mantine-react-table" import { memo } from "react"; -// import '../dataTableStyles.css'; -import '@mantine/core/styles.css'; //import Mantine V7 styles needed by MRT -import '@mantine/dates/styles.css'; //if using mantine date picker features -import 'mantine-react-table/styles.css'; //import MRT styles export function DataTableComponent({ columns, @@ -88,9 +83,7 @@ export function DataTableComponent({ // }, }); return ( - - ); } diff --git a/src/DataTable/columns/ApplicationColumns.tsx b/src/DataTable/columns/ApplicationColumns.tsx index 804c9da..8304424 100644 --- a/src/DataTable/columns/ApplicationColumns.tsx +++ b/src/DataTable/columns/ApplicationColumns.tsx @@ -1,4 +1,4 @@ -import { MRT_ColumnDef } from "mantine-react-table"; +import type { MRT_ColumnDef } from "mantine-react-table"; import { useMemo } from "react"; export default function ApplicationColumns() { @@ -8,9 +8,8 @@ export default function ApplicationColumns() { accessorFn: (row) => { if (row.id) { return `${row.id}`; - } else { - return ""; } + return ""; }, enableEditing: false, id: "id", @@ -27,9 +26,8 @@ export default function ApplicationColumns() { accessorFn: (row) => { if (row.name) { return `${row.name}`; - } else { - return ""; } + return ""; }, id: "name", header: "Name", @@ -44,9 +42,8 @@ export default function ApplicationColumns() { accessorFn: (row) => { if (row.url) { return `${row.url}`; - } else { - return ""; } + return ""; }, id: "url", header: "Url", @@ -61,9 +58,8 @@ export default function ApplicationColumns() { accessorFn: (row) => { if (row.icon) { return `${row.icon}`; - } else { - return ""; } + return ""; }, id: "icon", header: "Icon", @@ -78,9 +74,8 @@ export default function ApplicationColumns() { accessorFn: (row) => { if (row.urlbase) { return `${row.urlbase}`; - } else { - return ""; } + return ""; }, id: "urlbase", header: "Base Url", @@ -95,9 +90,8 @@ export default function ApplicationColumns() { accessorFn: (row) => { if (row.category) { return `${row.category}`; - } else { - return ""; } + return ""; }, id: "category", header: "Category", diff --git a/src/DataTable/columns/BookmarkColumns.tsx b/src/DataTable/columns/BookmarkColumns.tsx index 17ca569..1956123 100644 --- a/src/DataTable/columns/BookmarkColumns.tsx +++ b/src/DataTable/columns/BookmarkColumns.tsx @@ -1,4 +1,4 @@ -import { MRT_ColumnDef } from "mantine-react-table"; +import type { MRT_ColumnDef } from "mantine-react-table"; import { useMemo } from "react"; export default function ApplicationColumns(groups: any, groupData: any) { @@ -8,9 +8,8 @@ export default function ApplicationColumns(groups: any, groupData: any) { accessorFn: (row) => { if (row.id) { return `${row.id}`; - } else { - return ""; } + return ""; }, enableEditing: false, id: "id", @@ -27,9 +26,8 @@ export default function ApplicationColumns(groups: any, groupData: any) { accessorFn: (row) => { if (row.name) { return `${row.name}`; - } else { - return ""; } + return ""; }, id: "name", header: "Name", @@ -44,9 +42,8 @@ export default function ApplicationColumns(groups: any, groupData: any) { accessorFn: (row) => { if (row.url) { return `${row.url}`; - } else { - return ""; } + return ""; }, id: "url", header: "Url", @@ -62,9 +59,8 @@ export default function ApplicationColumns(groups: any, groupData: any) { const index: number = row.category; if (index !== null && index !== undefined) { return `${index}`; - } else { - return "N/A"; } + return "N/A"; }, id: "category", header: "Category", diff --git a/src/DataTable/columns/CategoryColumns.tsx b/src/DataTable/columns/CategoryColumns.tsx new file mode 100644 index 0000000..fcc466e --- /dev/null +++ b/src/DataTable/columns/CategoryColumns.tsx @@ -0,0 +1,67 @@ +import type { MRT_ColumnDef } from "mantine-react-table"; +import { useMemo } from "react"; + +export default function CategoryColumns() { + const columns = useMemo[]>( + () => [ + { + accessorFn: (row) => { + if (row.id) { + return `${row.id}`; + } + return ""; + }, + enableEditing: false, + id: "id", + header: "ID", + size: 50, + Cell: ({ renderedCellValue, row }) => renderedCellValue, + Header: ({ column }) => column.columnDef.header, + }, + { + accessorFn: (row) => { + if (row.category_name) { + return `${row.category_name}`; + } + return ""; + }, + id: "category_name", + header: "Name", + size: 50, + Cell: ({ renderedCellValue, row }) => renderedCellValue, + Header: ({ column }) => column.columnDef.header, + }, + { + accessorFn: (row) => { + if (row.category_index > -1) { + return `${row.category_index}`; + } + return ""; + }, + enableEditing: false, + id: "category_index", + header: "Index", + size: 50, + Cell: ({ renderedCellValue, row }) => renderedCellValue, + Header: ({ column }) => column.columnDef.header, + }, + { + accessorFn: (row) => { + if (row.column_filter) { + return `${row.column_filter}`; + } + return ""; + }, + id: "column_filter", + header: "Filter Name", + size: 50, + Cell: ({ renderedCellValue, row }) => renderedCellValue, + Header: ({ column }) => column.columnDef.header, + }, + ], + [], + ); + + return columns; +} + diff --git a/src/DataTable/columns/MessagesColumns.tsx b/src/DataTable/columns/MessagesColumns.tsx index fc05810..7438d32 100644 --- a/src/DataTable/columns/MessagesColumns.tsx +++ b/src/DataTable/columns/MessagesColumns.tsx @@ -1,4 +1,4 @@ -import { MRT_ColumnDef } from "mantine-react-table"; +import type { MRT_ColumnDef } from "mantine-react-table"; import { useMemo } from "react"; export default function MessagesColumns() { @@ -8,9 +8,8 @@ export default function MessagesColumns() { accessorFn: (row) => { if (row.id) { return `${row.id}`; - } else { - return ""; } + return ""; }, enableEditing: false, id: "id", @@ -27,9 +26,8 @@ export default function MessagesColumns() { accessorFn: (row) => { if (row.message) { return `${row.message}`; - } else { - return ""; } + return ""; }, id: "message", header: "Message", @@ -44,9 +42,8 @@ export default function MessagesColumns() { accessorFn: (row) => { if (row.easteregg) { return `${row.easteregg}`; - } else { - return ""; } + return ""; }, id: "easteregg", header: "Easter Egg?", diff --git a/src/DataTable/columns/PersonalizationColumns.tsx b/src/DataTable/columns/PersonalizationColumns.tsx index 89deac2..25a05b7 100644 --- a/src/DataTable/columns/PersonalizationColumns.tsx +++ b/src/DataTable/columns/PersonalizationColumns.tsx @@ -1,4 +1,4 @@ -import { MRT_ColumnDef } from "mantine-react-table"; +import type { MRT_ColumnDef } from "mantine-react-table"; import { useMemo } from "react"; export default function PersonalizationColumns() { @@ -8,9 +8,8 @@ export default function PersonalizationColumns() { accessorFn: (row: any) => { if (row.firstname) { return `${row.firstname}`; - } else { - return ""; } + return ""; }, id: "firstname", header: "First Name", @@ -26,9 +25,8 @@ export default function PersonalizationColumns() { accessorFn: (row: any) => { if (row.lastname) { return `${row.lastname}`; - } else { - return ""; } + return ""; }, id: "lastname", header: "Last Name", @@ -43,9 +41,8 @@ export default function PersonalizationColumns() { accessorFn: (row: any) => { if (row.email) { return `${row.email}`; - } else { - return ""; } + return ""; }, id: "email", header: "Email", diff --git a/src/DataTable/columns/SearchProviderColumns.tsx b/src/DataTable/columns/SearchProviderColumns.tsx new file mode 100644 index 0000000..3af0045 --- /dev/null +++ b/src/DataTable/columns/SearchProviderColumns.tsx @@ -0,0 +1,63 @@ +import type { MRT_ColumnDef } from "mantine-react-table"; +import { useMemo } from "react"; + +export default function SearchProviderColumns() { + const columns = useMemo[]>( + () => [ + { + accessorFn: (row) => { + if (row.id) { + return `${row.id}`; + } + return ""; + }, + enableEditing: false, + id: "id", + header: "ID", + size: 50, + Cell: ({ renderedCellValue, row }) => renderedCellValue, + Header: ({ column }) => column.columnDef.header, + }, + { + accessorFn: (row) => { + if (row.name) { + return `${row.name}`; + } + return ""; + }, + id: "name", + header: "Name", + Cell: ({ renderedCellValue, row }) => renderedCellValue, + Header: ({ column }) => column.columnDef.header, + }, + { + accessorFn: (row) => { + if (row.url) { + return `${row.url}`; + } + return ""; + }, + id: "url", + header: "Url", + Cell: ({ renderedCellValue, row }) => renderedCellValue, + Header: ({ column }) => column.columnDef.header, + }, + { + accessorFn: (row) => { + if (row.prefix) { + return `${row.prefix}`; + } + return ""; + }, + id: "prefix", + header: "Prefix", + Cell: ({ renderedCellValue, row }) => renderedCellValue, + Header: ({ column }) => column.columnDef.header, + }, + ], + [], + ); + + return columns; +} + diff --git a/src/components/ThemeProvider.tsx b/src/components/ThemeProvider.tsx new file mode 100644 index 0000000..4a1cb29 --- /dev/null +++ b/src/components/ThemeProvider.tsx @@ -0,0 +1,11 @@ +import { Box } from '@mantine/core'; + +export default function ThemeProvider({ theme, children }: { theme: any, children: React.ReactNode }) { + return {children}; +} \ No newline at end of file diff --git a/src/index.css b/src/index.css index 79453b2..f2eb3d0 100644 --- a/src/index.css +++ b/src/index.css @@ -1,78 +1 @@ -@import url('https://fonts.googleapis.com/css2?family=Jost:ital,wght@0,100;0,200;0,400;1,100;1,200&display=swap'); - -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -#settings-container { - justify-content: left; -} - -#settings-nav { - width: 25vw; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} +@import url('https://fonts.googleapis.com/css2?family=Jost:ital,wght@0,100;0,200;0,400;1,100;1,200&display=swap'); \ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx index 3d7150d..b8f20d8 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,22 @@ import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' -import './index.css' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + gcTime: 1000 * 60 * 60 * 24, // 24 hours + staleTime: 1000 * 60 * 1, // 1 min + }, + }, +}); ReactDOM.createRoot(document.getElementById('root')!).render( + - + + + , ) diff --git a/src/pages/homepage/Homepage.tsx b/src/pages/homepage/Homepage.tsx index 15ee344..ae42bdb 100644 --- a/src/pages/homepage/Homepage.tsx +++ b/src/pages/homepage/Homepage.tsx @@ -6,16 +6,14 @@ import Header from './components/Header'; import Applications from './components/Applications'; import Bookmarks from './components/Bookmarks'; import SettingsButton from './components/SettingsButton'; -import { useAtom } from 'jotai'; -import { HomepageFilters } from '../../contexts/HomepageFilters'; import { useEffect, useState } from 'react'; +import '../../index.css'; +import { useLocalStorage } from '@mantine/hooks'; - -export default function Homepage() { +export default function Homepage({theme}:any) { const { data, isFetching } = useQueryAPI({ endpoint: 'api/messages' }); const [displayedGreeting, setDisplayedGreeting] = useState(''); - const [homepageFilter, setHomepageFilter] = useAtom(HomepageFilters); - + const [contentType, setContentType] = useLocalStorage({ key: 'contenttype', defaultValue: 'All' }); function date() { const currentDate = new Date(); const dateOptions: Intl.DateTimeFormatOptions = { @@ -27,7 +25,6 @@ export default function Homepage() { const date = currentDate.toLocaleDateString('en-GB', dateOptions); return date; } - function greet(list: any) { const currentTime = new Date(); const greet = Math.floor(currentTime.getHours() / 6); @@ -54,12 +51,12 @@ export default function Homepage() { }, [isFetching]); return ( - +
- - - + + + ); } diff --git a/src/pages/homepage/components/Applications.tsx b/src/pages/homepage/components/Applications.tsx index 961281e..6a85bdb 100644 --- a/src/pages/homepage/components/Applications.tsx +++ b/src/pages/homepage/components/Applications.tsx @@ -4,16 +4,14 @@ import {useQueryAPI} from '../../../hooks/useAPI'; import texts from '../../../styles/Text.module.css'; import AppItem from './AppItem'; -function Applications() { +function Applications({contentType}: any) { const { data, isFetching } = useQueryAPI({ endpoint: 'api/apps' }); const [applications, setApplications] = useState([]); - const contentType = localStorage.getItem('contenttype'); useEffect(() => { if (!isFetching) { setApplications(data); } }, [isFetching]); - return ( Applications diff --git a/src/pages/homepage/components/Bookmarks.tsx b/src/pages/homepage/components/Bookmarks.tsx index 3c4609b..43ff6bc 100644 --- a/src/pages/homepage/components/Bookmarks.tsx +++ b/src/pages/homepage/components/Bookmarks.tsx @@ -4,7 +4,7 @@ import {useQueryAPI} from '../../../hooks/useAPI'; import texts from '../../../styles/Text.module.css'; import LinkGroups from './LinkGroups'; -function Links() { +function Links({contentType}: any) { const { data: linkData, isFetched: linksIsFetched } = useQueryAPI({ endpoint: 'api/links', }); @@ -38,8 +38,8 @@ function Links() { > {categories.map((category: any) => { if ( - category.column_filter === localStorage.getItem('contenttype') || - localStorage.getItem('contenttype') === 'All' + category.column_filter === contentType || + contentType === 'All' ) { return ( diff --git a/src/pages/homepage/components/Search.tsx b/src/pages/homepage/components/Search.tsx index 1365f5a..a41dc06 100644 --- a/src/pages/homepage/components/Search.tsx +++ b/src/pages/homepage/components/Search.tsx @@ -53,10 +53,10 @@ export default function Search() { }} > { if(item.target.value.startsWith('/')) { setProviderLabel(providers?.find((p: any) => p.prefix === item.target.value.split(' ')[0]).name); diff --git a/src/pages/homepage/components/SettingsButton.tsx b/src/pages/homepage/components/SettingsButton.tsx index 263ddd8..691c5ed 100644 --- a/src/pages/homepage/components/SettingsButton.tsx +++ b/src/pages/homepage/components/SettingsButton.tsx @@ -1,4 +1,4 @@ -import { Button, Menu, NavLink, Select, Stack } from '@mantine/core'; +import { Button, Menu, NavLink, Select } from '@mantine/core'; import { useEffect, useState } from 'react'; import { FiMenu, FiMonitor } from 'react-icons/fi'; import {useQueryAPI} from '../../../hooks/useAPI'; @@ -6,25 +6,14 @@ import button from '../../../styles/Button.module.css'; import menu from '../../../styles/Menu.module.css'; import navLink from '../../../styles/NavLink.module.css'; import selectClasses from '../../../styles/Select.module.css'; -import { useAtom } from 'jotai'; -import { HomepageFilters } from '../../../contexts/HomepageFilters'; -function SettingsButton() { +function SettingsButton({contentType, setContentType, theme}: any) { const { data, isFetched } = useQueryAPI({ endpoint: 'api/appCategories' }); const [categories, setCategories] = useState([{value: 'All', label: 'All'}]); - const [homepageFilter, setHomepageFilter] = useAtom(HomepageFilters); - const classNames = { - root: navLink.root, - body: navLink.body, - section: navLink.section, - label: navLink.label, - description: navLink.description, - chevron: navLink.chevron, - }; useEffect(() => { if(data) { - let list: [any] = data.map((category: any) => {return {value: category.category, label: category.category}}) || []; + const list: [any] = data.map((category: any) => {return {value: category.category, label: category.category}}) || []; list.unshift({value: 'All', label: 'All'}); setCategories(list); } @@ -39,18 +28,10 @@ function SettingsButton() { } return ( - + } onClick={() => runWakeCommand()} - classNames={classNames} + className={navLink.defaultNavLink} + classNames={navLink} />