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 = (
<>
@@ -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}{' '}
+
+ {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}
-
>
)
diff --git a/web/src/pages/Home.tsx b/web/src/pages/Home.tsx
index 47db55e63..e39ceee77 100644
--- a/web/src/pages/Home.tsx
+++ b/web/src/pages/Home.tsx
@@ -1,27 +1,26 @@
-import React, { useEffect, useState } from 'react'
-
-import { useProjects } from '../data-providers/ProjectDataProvider'
-import { ErrorOutline } from '@mui/icons-material'
-import { type Project } from '../models/ProjectsResponse'
-import { useLocation } from 'react-router'
-import { useSearch } from '../data-providers/SearchProvider'
-
-import ProjectRepository from '../repositories/ProjectRepository'
-import Help from './Help'
-import UploadButton from '../components/UploadButton'
-import ClaimButton from '../components/ClaimButton'
-import DeleteButton from '../components/DeleteButton'
-import ProjectList from '../components/ProjectList'
-import Header from '../components/Header'
-import Footer from '../components/Footer'
-import LoadingPage from './LoadingPage'
-
-import styles from './../style/pages/Home.module.css'
+import { useEffect, useState } from 'react';
+
+import { Delete, ErrorOutline, FileUpload, Lock } from '@mui/icons-material';
+import { useLocation } from 'react-router';
+import { useProjects } from '../data-providers/ProjectDataProvider';
+import { useSearch } from '../data-providers/SearchProvider';
+import { type Project } from '../models/ProjectsResponse';
+
+import Footer from '../components/Footer';
+import Header from '../components/Header';
+import ProjectList from '../components/ProjectList';
+import ProjectRepository from '../repositories/ProjectRepository';
+import LoadingPage from './LoadingPage';
+
+import { Box, Button, IconButton, Tooltip, Typography } from '@mui/material';
+import SearchBar from '../components/SearchBar';
+import styles from './../style/pages/Home.module.css';
+
export default function Home(): JSX.Element {
const { loadingFailed } = useProjects()
- const { filteredProjects: projects, query } = useSearch()
- const [nonFavoriteProjects, setNonFavoriteProjects] = useState([])
+ const { filteredProjects: projects, query, setQuery } = useSearch()
+ const [showAll, setShowAll] = useState(false);
const [favoriteProjects, setFavoriteProjects] = useState([])
const location = useLocation()
@@ -37,7 +36,7 @@ export default function Home(): JSX.Element {
}
window.location.replace(`/#${nonHostPart}`)
- }, [location])
+ }, [location, setQuery, projects])
const updateFavorites = (): void => {
if (projects == null) return
@@ -45,9 +44,10 @@ export default function Home(): JSX.Element {
setFavoriteProjects(
projects.filter((project) => ProjectRepository.isFavorite(project.name))
)
- setNonFavoriteProjects(
- projects.filter((project) => !ProjectRepository.isFavorite(project.name))
- )
+ }
+
+ const onShowFavourites = (all: boolean): void => {
+ setShowAll(all);
}
useEffect(() => {
@@ -67,54 +67,93 @@ export default function Home(): JSX.Element {
)
}
- // no results for query
- if (projects != null && projects.length === 0 && query.length > 0) {
- return (
-
-
-
- No results for ‘{query}’
-
-
-
-
-
-
- )
- }
-
if (projects == null) {
return
}
- // no projects
- if (projects.length === 0) {
- return
- }
-
return (
+
-
{
- updateFavorites()
- }}
- />
- {nonFavoriteProjects.length > 0 && favoriteProjects.length > 0 && (
-
- )}
- {
- updateFavorites()
- }}
- />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { projects.length === 0 ?
+ <>{ query !== "" ?
+
+ Couldn't find any docs
+ :
+
+ Looks like you don't have any docs yet.
+
+
+ }> :
+ <>
+ { (query || showAll) ?
+ {
+ updateFavorites()
+ }}
+ />
+ :
+ <>
+ FAVOURITES
+ { (favoriteProjects.length === 0) ?
+
+ No docs favourited at the moment, search for docs or
+
+
+ :
+ {
+ updateFavorites()
+ }}
+ />
+ }
+ >
+ }
+ >
+ }
+
-
-
-
)
diff --git a/web/src/repositories/ProjectRepository.ts b/web/src/repositories/ProjectRepository.ts
index f4593a1dc..d12776525 100644
--- a/web/src/repositories/ProjectRepository.ts
+++ b/web/src/repositories/ProjectRepository.ts
@@ -32,9 +32,16 @@ function escapeSlashesInUrl(
return projectAndVersion + '/' + path
}
+function dateTimeReviver(key: string, value: any) {
+ if (key === 'timestamp') {
+ return new Date(value)
+ }
+ return value;
+}
+
function filterHiddenVersions(allProjects: Project[]): Project[] {
// create deep-copy first
- const projects = JSON.parse(JSON.stringify(allProjects)) as Project[]
+ const projects = JSON.parse(JSON.stringify(allProjects), dateTimeReviver) as Project[]
projects.forEach((p) => {
p.versions = p.versions.filter((v) => !v.hidden)
diff --git a/web/src/style/components/Footer.module.css b/web/src/style/components/Footer.module.css
index 7fa1e76a8..8e2c215ea 100644
--- a/web/src/style/components/Footer.module.css
+++ b/web/src/style/components/Footer.module.css
@@ -1,18 +1,37 @@
-.footer{
- border-top: 1px solid var(--secondary-foreground);
- width: 100%;
+.footer {
+ margin-top: 32px;
padding: 15px 0 15px 0;
- text-align: center;
}
-.help-link{
+.help-link {
+ font-weight: 200;
text-decoration: none;
- color: black;
- font-size: 15px;
+ font-size: 20px;
+ padding-left: 8px;
}
.version-info {
- font-size: 12px;
+ font-weight: 200;
+ font-size: 14px;
margin-top: 0.8em;
color: var(--primary-foreground);
+ padding-left: 8px;
+}
+
+@media only screen and (min-width: 1000px) {
+ .footer {
+ padding-left: calc(15% + 16px);
+ }
+}
+
+@media only screen and (max-width: 1000px) {
+ .footer {
+ padding-left: 30px;
+ }
+}
+
+@media only screen and (max-width: 300px) {
+ .footer {
+ padding-left: 10px;
+ }
}
diff --git a/web/src/style/components/Header.module.css b/web/src/style/components/Header.module.css
index 0ca7b857e..399330edb 100644
--- a/web/src/style/components/Header.module.css
+++ b/web/src/style/components/Header.module.css
@@ -1,9 +1,9 @@
.header {
- --header-height: 64px;
+ --header-height: 74px;
min-width: 230px;
height: var(--header-height);
- background-color: var(--background);
+ border-bottom: 1px solid var(--secondary-foreground);
}
@media only screen and (min-width: 1000px) {
@@ -34,5 +34,5 @@ h1 {
margin-top: calc(var(--header-height) / 2 - 15px);
margin-left: 10px;
font-size: 30px;
- font-weight: 800;
+ font-weight: 00;
}
diff --git a/web/src/style/components/NavigationTitle.module.css b/web/src/style/components/NavigationTitle.module.css
index 3d50da6bf..234e40c49 100644
--- a/web/src/style/components/NavigationTitle.module.css
+++ b/web/src/style/components/NavigationTitle.module.css
@@ -7,8 +7,6 @@
@media only screen and (min-width: 1400px) {
.nav-title {
width: 50%;
- margin-left: auto;
- margin-right: auto;
}
}
diff --git a/web/src/style/components/Project.module.css b/web/src/style/components/Project.module.css
index f01e3162e..ad57051cd 100644
--- a/web/src/style/components/Project.module.css
+++ b/web/src/style/components/Project.module.css
@@ -1,48 +1,40 @@
.project-card {
- border-radius: 4px;
- margin: 0 16px 10px 16px;
- padding: 16px 0 16px 16px;
- border: 1px solid var(--secondary-foreground);
+ max-width: 800px;
+ margin-left: 24px;
+ margin-bottom: 8px;
+ margin-top: 8px;
}
-.project-card-header {
- display: inline-block;
- width: 90%;
- height: 40px;
+.secondary-typography {
+ color: var(--primary-foreground);
+ opacity: 0.6;
}
-.subhead {
- color: var(--primary-foreground);
- opacity: 0.54;
- font-size: 14px;
- letter-spacing: 0.01em;
- line-height: 20px;
+.project-header {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 6px;
}
-.project-card-title,
-.project-card-title-with-logo {
- font-weight: lighter;
- display: inline-block;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- padding-top: 0.25em;
+.project-footer {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 6px;
}
-.project-card-version {
+.subhead {
color: var(--primary-foreground);
opacity: 0.54;
+ font-size: 16px;
}
.project-card-title {
- width: calc(100% - 30px);
-}
-
-.project-card-title-with-logo {
- width: calc(100% - 86px);
+ font-weight: 400;
+ font-size: 1.1em;
}
.project-logo {
+ float: left;
width: 40px;
height: 40px;
border-radius: 50%;
diff --git a/web/src/style/components/ProjectList.module.css b/web/src/style/components/ProjectList.module.css
index 079959868..c951a662f 100644
--- a/web/src/style/components/ProjectList.module.css
+++ b/web/src/style/components/ProjectList.module.css
@@ -2,30 +2,7 @@
display: grid;
}
-/* 1 column */
-@media only screen and (max-width: 450px) {
- .project-list {
- grid-template-columns: repeat(auto-fill, 100%);
- }
-}
-
-/* 2 columns */
-@media only screen and (min-width: 450px) {
- .project-list {
- grid-template-columns: repeat(auto-fill, calc(100% / 2));
- }
-}
-
-/* 3 columns */
-@media only screen and (min-width: 750px) {
- .project-list {
- grid-template-columns: repeat(auto-fill, calc(100% / 3));
- }
-}
-
-/* 4 columns */
-@media only screen and (min-width: 1100px) {
- .project-list {
- grid-template-columns: repeat(auto-fill, calc(100% / 4));
- }
+.project-list {
+ min-width: 250px;
+ width: 80%;
}
diff --git a/web/src/style/components/StyledForm.module.css b/web/src/style/components/StyledForm.module.css
index baa4ad8d8..2ac81fdd2 100644
--- a/web/src/style/components/StyledForm.module.css
+++ b/web/src/style/components/StyledForm.module.css
@@ -12,8 +12,6 @@
@media only screen and (min-width: 1400px) {
.form {
width: 50%;
- margin-left: auto;
- margin-right: auto;
}
}
diff --git a/web/src/style/pages/Help.module.css b/web/src/style/pages/Help.module.css
index c97e8dae6..04be5b47f 100644
--- a/web/src/style/pages/Help.module.css
+++ b/web/src/style/pages/Help.module.css
@@ -60,6 +60,7 @@
font-size: 16px;
line-height: 1.5;
word-wrap: break-word;
+ max-width: 800px;
}
.markdown-container .octicon {
diff --git a/web/src/style/pages/Home.module.css b/web/src/style/pages/Home.module.css
index f690e1712..86f889a9a 100644
--- a/web/src/style/pages/Home.module.css
+++ b/web/src/style/pages/Home.module.css
@@ -22,6 +22,22 @@
flex-direction: column;
}
+.card {
+ border: 1px solid var(--secondary-foreground);
+ border-radius: 5px;
+ width: 250px;
+ padding: 16px;
+ margin-left: 16px;
+}
+
+.clear {
+ clear: both;
+}
+
+.card-header {
+ margin-top: 8px;
+}
+
@media only screen and (min-width: 1000px) {
.project-overview {
margin: 20px 15%;
diff --git a/web/src/tests/repositories/ProjectRepository.test.ts b/web/src/tests/repositories/ProjectRepository.test.ts
index 7fb8b80e0..1c58a96e2 100644
--- a/web/src/tests/repositories/ProjectRepository.test.ts
+++ b/web/src/tests/repositories/ProjectRepository.test.ts
@@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/require-await, @typescript-eslint/no-floating-promises */
// -> we need any for our mocks, and we need to disable require-await because we need to mock async functions that throw errors
-import ProjectRepository from '../../repositories/ProjectRepository'
import ProjectDetails from '../../models/ProjectDetails'
import { type Project } from '../../models/ProjectsResponse'
+import ProjectRepository from '../../repositories/ProjectRepository'
const mockFetchData = (fetchData: any): void => {
global.fetch = vi.fn().mockImplementation(
async () =>
@@ -40,7 +40,7 @@ describe('get versions', () => {
const projectName = 'test'
const versions = ['1.0.0', '2.0.0']
const responseData = versions.map(
- (version) => new ProjectDetails(version, ['tag'], false)
+ (version) => new ProjectDetails(version, ['tag'], false, new Date())
)
mockFetchData({ versions: responseData })
@@ -338,13 +338,15 @@ describe('filterHiddenVersions', () => {
const shownVersion: ProjectDetails = {
name: 'v-2',
tags: ['stable'],
- hidden: false
+ hidden: false,
+ timestamp: new Date()
}
const hiddenVersion: ProjectDetails = {
name: 'v-1',
tags: ['latest'],
- hidden: true
+ hidden: true,
+ timestamp: new Date()
}
const allProjects: Project[] = [
@@ -374,7 +376,8 @@ describe('filterHiddenVersions', () => {
{
name: 'v-1',
tags: ['latest'],
- hidden: true
+ hidden: true,
+ timestamp: new Date()
}
],
logo: true
@@ -392,12 +395,14 @@ describe('getLatestVersion', () => {
{
name: '1.0.0',
hidden: false,
- tags: []
+ tags: [],
+ timestamp: new Date()
},
{
name: '2.0.0',
hidden: false,
- tags: []
+ tags: [],
+ timestamp: new Date()
}
]
@@ -410,12 +415,14 @@ describe('getLatestVersion', () => {
{
name: '1.0.0',
hidden: false,
- tags: []
+ tags: [],
+ timestamp: new Date()
},
{
name: 'latest',
hidden: false,
- tags: []
+ tags: [],
+ timestamp: new Date()
}
]
@@ -428,12 +435,14 @@ describe('getLatestVersion', () => {
{
name: '1.0.0',
hidden: false,
- tags: ['latest']
+ tags: ['latest'],
+ timestamp: new Date()
},
{
name: '2.0.0',
hidden: false,
- tags: []
+ tags: [],
+ timestamp: new Date()
}
]
@@ -446,12 +455,14 @@ describe('getLatestVersion', () => {
{
name: 'latest',
hidden: false,
- tags: []
+ tags: [],
+ timestamp: new Date()
},
{
name: '1.0.0',
hidden: false,
- tags: ['latest']
+ tags: ['latest'],
+ timestamp: new Date()
}
]