diff --git a/web/src/components/ClaimButton.tsx b/web/src/components/ClaimButton.tsx deleted file mode 100644 index 4818877c0..000000000 --- a/web/src/components/ClaimButton.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react' -import { Link } from 'react-router-dom' -import { Lock } from '@mui/icons-material' -import { Tooltip } from '@mui/material' - -import styles from './../style/components/ControlButtons.module.css' - -interface Props { - isSingleButton?: boolean -} - -export default function ClaimButton(props: Props): JSX.Element { - return ( - <> - - - - - - - ) -} diff --git a/web/src/components/DeleteButton.tsx b/web/src/components/DeleteButton.tsx deleted file mode 100644 index 8a5ed4d66..000000000 --- a/web/src/components/DeleteButton.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { Link } from 'react-router-dom' -import { Delete } from '@mui/icons-material' -import { Tooltip } from '@mui/material' -import React from 'react' - -import styles from './../style/components/ControlButtons.module.css' - -interface Props { - isSingleButton?: boolean -} - -export default function DeleteButton(props: Props): JSX.Element { - return ( - <> - - - - - - - ) -} diff --git a/web/src/components/FavoriteStar.tsx b/web/src/components/FavoriteStar.tsx index ba022d7fd..08e1d30e8 100644 --- a/web/src/components/FavoriteStar.tsx +++ b/web/src/components/FavoriteStar.tsx @@ -1,5 +1,5 @@ import { Star, StarOutline } from '@mui/icons-material' -import React, { useState } from 'react' +import { useState } from 'react' import ProjectRepository from '../repositories/ProjectRepository' interface Props { @@ -24,7 +24,7 @@ export default function FavoriteStar(props: Props): JSX.Element { return ( ) diff --git a/web/src/components/Footer.tsx b/web/src/components/Footer.tsx index 7bcfb30c2..f0cbb9f60 100644 --- a/web/src/components/Footer.tsx +++ b/web/src/components/Footer.tsx @@ -1,17 +1,18 @@ import { Link } from 'react-router-dom' import styles from './../style/components/Footer.module.css' -import React from 'react' export default function Footer(): JSX.Element { return (
- Help + HELP
- Docat Version{' '} - {import.meta.env.VITE_DOCAT_VERSION ?? 'unknown'} + + VERSION{' '} + {import.meta.env.VITE_DOCAT_VERSION ?? 'unknown'} +
) diff --git a/web/src/components/Header.tsx b/web/src/components/Header.tsx index 0173868fa..505165fa5 100644 --- a/web/src/components/Header.tsx +++ b/web/src/components/Header.tsx @@ -1,17 +1,13 @@ -import React, { useState } from 'react' +import { useState } from 'react' import { Link } from 'react-router-dom' -import SearchBar from './SearchBar' import { useConfig } from '../data-providers/ConfigDataProvider' import docatLogo from '../assets/logo.png' import styles from './../style/components/Header.module.css' -interface Props { - showSearchBar?: boolean -} -export default function Header(props: Props): JSX.Element { +export default function Header(): JSX.Element { const defaultHeader = ( <> docat logo @@ -30,7 +26,6 @@ export default function Header(props: Props): JSX.Element { return (
{header} - {props.showSearchBar !== false && }
) } diff --git a/web/src/components/NavigationTitle.tsx b/web/src/components/NavigationTitle.tsx index 5de13a09e..87d3778d5 100644 --- a/web/src/components/NavigationTitle.tsx +++ b/web/src/components/NavigationTitle.tsx @@ -1,6 +1,5 @@ import { ArrowBackIos } from '@mui/icons-material' import { Link } from 'react-router-dom' -import React from 'react' import styles from './../style/components/NavigationTitle.module.css' diff --git a/web/src/components/PageLayout.tsx b/web/src/components/PageLayout.tsx index f58644cbb..d9fb00ec4 100644 --- a/web/src/components/PageLayout.tsx +++ b/web/src/components/PageLayout.tsx @@ -2,7 +2,6 @@ import styles from './../style/components/PageLayout.module.css' import Footer from './Footer' import Header from './Header' import NavigationTitle from './NavigationTitle' -import React from 'react' interface Props { title: string @@ -14,7 +13,7 @@ interface Props { export default function PageLayout(props: Props): JSX.Element { return ( <> -
+
{props.children} diff --git a/web/src/components/Project.tsx b/web/src/components/Project.tsx index 9a9505f4a..eab7f7f06 100644 --- a/web/src/components/Project.tsx +++ b/web/src/components/Project.tsx @@ -1,64 +1,88 @@ -import React from 'react' import { Link } from 'react-router-dom' +import { type Project as ProjectType } from '../models/ProjectsResponse' import ProjectRepository from '../repositories/ProjectRepository' import styles from './../style/components/Project.module.css' -import { type Project as ProjectType } from '../models/ProjectsResponse' -import FavoriteStar from './FavoriteStar' import { Tooltip } from '@mui/material' +import FavoriteStar from './FavoriteStar' interface Props { project: ProjectType onFavoriteChanged: () => void } +function timeSince(date: Date) { + const seconds = Math.floor((new Date().getUTCMilliseconds() - date.getUTCMilliseconds()) / 1000); + let interval = seconds / 31536000; + + if (interval > 1) { + return Math.floor(interval) + " years"; + } + interval = seconds / 2592000; + if (interval > 1) { + return Math.floor(interval) + " months"; + } + interval = seconds / 86400; + if (interval > 1) { + return Math.floor(interval) + " days"; + } + interval = seconds / 3600; + if (interval > 1) { + return Math.floor(interval) + " hours"; + } + interval = seconds / 60; + if (interval > 1) { + return Math.floor(interval) + " minutes"; + } + return Math.floor(seconds) + " seconds"; +} + export default function Project(props: Props): JSX.Element { + const latestVersion = ProjectRepository.getLatestVersion(props.project.versions) + return (
-
- - - {props.project.logo ? ( - <> + + {props.project.logo ? + <> + {`${props.project.name} + + : <> + } + +
+ +
+ {props.project.name}{' '} + + {latestVersion.name} + +
+ -
- {props.project.name}{' '} - - { - ProjectRepository.getLatestVersion(props.project.versions) - .name - } - -
- - ) : ( -
- {props.project.name}{' '} - - { - ProjectRepository.getLatestVersion(props.project.versions) - .name - } - -
- )} - + +
+ {timeSince(new Date(latestVersion.timestamp))} ago +
+
+
+
+ {props.project.versions.length === 1 + ? `${props.project.versions.length} version` + : `${props.project.versions.length} versions`} +
+
-
- {props.project.versions.length === 1 - ? `${props.project.versions.length} version` - : `${props.project.versions.length} versions`} -
) } diff --git a/web/src/components/ProjectList.tsx b/web/src/components/ProjectList.tsx index 028ef616f..a6a7d8c37 100644 --- a/web/src/components/ProjectList.tsx +++ b/web/src/components/ProjectList.tsx @@ -1,8 +1,7 @@ import Project from './Project' -import React from 'react' -import styles from './../style/components/ProjectList.module.css' import { type Project as ProjectType } from '../models/ProjectsResponse' +import styles from './../style/components/ProjectList.module.css' interface Props { projects: ProjectType[] diff --git a/web/src/components/SearchBar.tsx b/web/src/components/SearchBar.tsx index 6987187f2..932934ded 100644 --- a/web/src/components/SearchBar.tsx +++ b/web/src/components/SearchBar.tsx @@ -1,31 +1,74 @@ -import _ from 'lodash' -import { TextField } from '@mui/material' -import React, { useCallback } from 'react' -import styles from '../style/components/SearchBar.module.css' -import { useSearch } from '../data-providers/SearchProvider' +import SearchIcon from '@mui/icons-material/Search'; +import StarIcon from '@mui/icons-material/Star'; +import StarBorderIcon from '@mui/icons-material/StarBorder'; +import { Divider, IconButton, InputBase, Paper, Tooltip } from '@mui/material'; +import React, { useEffect, useState } from 'react'; +import { useSearchParams } from 'react-router-dom'; +import { useSearch } from '../data-providers/SearchProvider'; + + +interface Props { + showFavourites: boolean + onShowFavourites: (all: boolean) => void +} + +export default function SearchBar(props: Props): JSX.Element { + const [showFavourites, setShowFavourites] = useState(true); + const [searchParams, setSearchParams] = useSearchParams(); -export default function SearchBar(): JSX.Element { const { query, setQuery } = useSearch() const [searchQuery, setSearchQuery] = React.useState(query) - const updateSearchQueryInDataProvider = useCallback( - _.debounce((query: string): void => { - setQuery(query) - }, 500), - [] - ) + + const updateSearch = (q: string) => { + setSearchQuery(q) + setQuery(q) + + if (q) { + setSearchParams({q}) + } else { + setSearchParams({}) + } + } + + useEffect(() => { + const q = searchParams.get("q") + if (q) { + updateSearch(q) + } + setShowFavourites(props.showFavourites) + }, [props.showFavourites]); + + const onFavourites = (show: boolean): void => { + setSearchParams({}) + setSearchQuery("") + setQuery("") + + setShowFavourites(show) + props.onShowFavourites(!show) + } const onSearch = (e: React.ChangeEvent): void => { - setSearchQuery(e.target.value) - updateSearchQueryInDataProvider.cancel() - updateSearchQueryInDataProvider(e.target.value) + updateSearch(e.target.value) } return ( -
- + { @@ -34,8 +77,17 @@ export default function SearchBar(): JSX.Element { setQuery(searchQuery) } }} - variant="standard" - > -
+ + /> + + + + + + onFavourites(!showFavourites)} sx={{ p: '10px' }} aria-label="directions"> + { showFavourites ? : } + + + ) } diff --git a/web/src/components/StyledForm.tsx b/web/src/components/StyledForm.tsx index 8b12da998..5d1b87a12 100644 --- a/web/src/components/StyledForm.tsx +++ b/web/src/components/StyledForm.tsx @@ -1,5 +1,4 @@ import styles from './../style/components/StyledForm.module.css' -import React from 'react' interface Props { children: JSX.Element[] diff --git a/web/src/components/UploadButton.tsx b/web/src/components/UploadButton.tsx deleted file mode 100644 index 88e110120..000000000 --- a/web/src/components/UploadButton.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react' -import { FileUpload } from '@mui/icons-material' -import { Link } from 'react-router-dom' -import { Tooltip } from '@mui/material' - -import styles from './../style/components/ControlButtons.module.css' - -interface Props { - isSingleButton?: boolean -} - -export default function UploadButton(props: Props): JSX.Element { - return ( - <> - - - - - - - ) -} diff --git a/web/src/index.css b/web/src/index.css index ebe842dc4..d20ed693f 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -1,13 +1,12 @@ * { margin: 0; padding: 0; - font-family: "Avenir", Helvetica, Arial, sans-serif; + font-family: "Roboto", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; --primary-foreground: #383838; --secondary-foreground: #e8e8e8; - --background: #ececec; --button-primary: #2c3e50; --icons: #505050; } diff --git a/web/src/models/ProjectDetails.ts b/web/src/models/ProjectDetails.ts index cbfb3a929..7221ddbf6 100644 --- a/web/src/models/ProjectDetails.ts +++ b/web/src/models/ProjectDetails.ts @@ -1,11 +1,13 @@ export default class ProjectDetails { name: string hidden: boolean + timestamp: Date tags: string[] - constructor(name: string, tags: string[], hidden: boolean) { + constructor(name: string, tags: string[], hidden: boolean, timestamp: Date) { this.name = name this.tags = tags this.hidden = hidden + this.timestamp = timestamp } } diff --git a/web/src/pages/Help.tsx b/web/src/pages/Help.tsx index 6be7ace88..06e8164b5 100644 --- a/web/src/pages/Help.tsx +++ b/web/src/pages/Help.tsx @@ -1,12 +1,11 @@ -import React, { useEffect, useState } from 'react' +import { useEffect, useState } from 'react' import ReactMarkdown from 'react-markdown' // @ts-expect-error ts can't read symbols from a md file import gettingStarted from './../assets/getting-started.md' -import UploadButton from '../components/UploadButton' -import Header from '../components/Header' import Footer from '../components/Footer' +import Header from '../components/Header' import LoadingPage from './LoadingPage' import styles from './../style/pages/Help.module.css' @@ -62,7 +61,6 @@ export default function Help(): JSX.Element { {content} -