Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"build": "tsc && vite build",
"preview": "vite preview",
"test": "vitest --watch=false",
"lint": "eslint ."
"lint": "eslint .",
"format": "prettier --write **/*.{ts,tsx}"
},
"browserslist": {
"production": [
Expand Down
2 changes: 1 addition & 1 deletion web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React from 'react'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import { ConfigDataProvider } from './data-providers/ConfigDataProvider'
import { MessageBannerProvider } from './data-providers/MessageBannerProvider'
Expand Down
14 changes: 8 additions & 6 deletions web/src/components/DocumentControlButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ interface Props {
onVersionChange: (version: string) => void
}

export default function DocumentControlButtons(props: Props): React.JSX.Element {
export default function DocumentControlButtons(
props: Props
): React.JSX.Element {
const buttonStyle = { width: '25px', height: '25px' }

const [shareModalOpen, setShareModalOpen] = useState<boolean>(false)
Expand Down Expand Up @@ -61,12 +63,12 @@ export default function DocumentControlButtons(props: Props): React.JSX.Element
<FormControl>
<Select
sx={{
"&.MuiOutlinedInput-root": {
"&:hover fieldset": {
borderColor: "rgba(0, 0, 0, 0.33)"
'&.MuiOutlinedInput-root': {
'&:hover fieldset': {
borderColor: 'rgba(0, 0, 0, 0.33)'
},
"&.Mui-focused fieldset": {
borderColor: "rgba(0, 0, 0, 0.33)"
'&.Mui-focused fieldset': {
borderColor: 'rgba(0, 0, 0, 0.33)'
}
}
}}
Expand Down
17 changes: 11 additions & 6 deletions web/src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import { useConfig } from '../data-providers/ConfigDataProvider'
import styles from './../style/components/Footer.module.css'

export default function Footer(): JSX.Element {

const defaultFooter = (
<></>
)
const defaultFooter = <></>

const [footer, setFooter] = useState<JSX.Element>(defaultFooter)
const config = useConfig()
Expand All @@ -24,12 +21,20 @@ export default function Footer(): JSX.Element {
HELP
</Link>

<Box sx={{ fontSize: '1.05em', fontWeight: 300, opacity: 0.6, marginLeft: '8px', marginTop: 1 }}>
<Box
sx={{
fontSize: '1.05em',
fontWeight: 300,
opacity: 0.6,
marginLeft: '8px',
marginTop: 1
}}
>
{footer}
</Box>

<div className={styles['version-info']}>
<Link to="https://github.com/docat-org/docat" target='_blank'>
<Link to="https://github.com/docat-org/docat" target="_blank">
VERSION{' '}
{import.meta.env.VITE_DOCAT_VERSION ?? 'unknown'}
</Link>
Expand Down
1 change: 0 additions & 1 deletion web/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { useConfig } from '../data-providers/ConfigDataProvider'
import docatLogo from '../assets/logo.png'
import styles from './../style/components/Header.module.css'


export default function Header(): JSX.Element {
const defaultHeader = (
<>
Expand Down
9 changes: 7 additions & 2 deletions web/src/components/IFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ export default function IFrame(props: Props): React.JSX.Element {
iFrameRef.current.contentDocument
?.querySelectorAll('a')
.forEach((a: HTMLAnchorElement) => {
if (typeof a.href === 'string' && !a.href.startsWith(window.location.origin)) {
if (
typeof a.href === 'string' &&
!a.href.startsWith(window.location.origin)
) {
a.setAttribute('target', '_blank')
return
}
Expand Down Expand Up @@ -95,7 +98,9 @@ export default function IFrame(props: Props): React.JSX.Element {
props.onFaviconChanged?.(favicon)
}

const extractFaviconUrl = (doc: Document | null | undefined): string | null => {
const extractFaviconUrl = (
doc: Document | null | undefined
): string | null => {
if (doc == null) {
return null
}
Expand Down
6 changes: 3 additions & 3 deletions web/src/components/InfoBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ interface Props {

export default function Banner(props: Props): React.JSX.Element {
const [show, setShow] = useState<boolean>(false)
const [prevMessage, setPrevMessage] = useState(props.message);
const [prevMessage, setPrevMessage] = useState(props.message)

if (props.message !== prevMessage) {
setPrevMessage(props.message);
setShow(true);
setPrevMessage(props.message)
setShow(true)
}

return (
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/NavigationTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React from 'react'
import { ArrowBackIos } from '@mui/icons-material'
import { Link } from 'react-router-dom'

Expand Down
82 changes: 51 additions & 31 deletions web/src/components/Project.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React from 'react'
import { Link } from 'react-router-dom'
import { type Project as ProjectType } from '../models/ProjectsResponse'
import ProjectRepository from '../repositories/ProjectRepository'
Expand All @@ -13,51 +13,54 @@ interface Props {
}

function timeSince(date: Date) {
const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000);
let interval = seconds / 31536000;
const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000)
let interval = seconds / 31536000

if (interval > 1) {
return Math.floor(interval) + " years";
return Math.floor(interval) + ' years'
}
interval = seconds / 2592000;
interval = seconds / 2592000
if (interval > 1) {
return Math.floor(interval) + " months";
return Math.floor(interval) + ' months'
}
interval = seconds / 86400;
interval = seconds / 86400
if (interval > 1) {
return Math.floor(interval) + " days";
return Math.floor(interval) + ' days'
}
interval = seconds / 3600;
interval = seconds / 3600
if (interval > 1) {
return Math.floor(interval) + " hours";
return Math.floor(interval) + ' hours'
}
interval = seconds / 60;
interval = seconds / 60
if (interval > 1) {
return Math.floor(interval) + " minutes";
return Math.floor(interval) + ' minutes'
}
return Math.floor(seconds) + " seconds";
return Math.floor(seconds) + ' seconds'
}

export default function Project(props: Props): React.JSX.Element {
const latestVersion = ProjectRepository.getLatestVersion(props.project.versions)
const latestVersion = ProjectRepository.getLatestVersion(
props.project.versions
)

return (
<div className={styles['project-card']}>

{props.project.logo ?
<>
<Link to={`${props.project.name}/latest`}>
<img
className={styles['project-logo']}
src={ProjectRepository.getProjectLogoURL(props.project.name)}
alt={`${props.project.name} project logo`}
/>
</Link>
</> : <></>
}
{props.project.logo ? (
<>
<Link to={`${props.project.name}/latest/`}>
<img
className={styles['project-logo']}
src={ProjectRepository.getProjectLogoURL(props.project.name)}
alt={`${props.project.name} project logo`}
/>
</Link>
</>
) : (
<></>
)}

<div className={styles['project-header']}>
<Link to={`${props.project.name}/latest`}>
<Link to={`${props.project.name}/latest/`}>
<div className={styles['project-card-title']}>
{props.project.name}{' '}
<span className={styles['secondary-typography']}>
Expand All @@ -66,13 +69,23 @@ export default function Project(props: Props): React.JSX.Element {
</div>
</Link>

<Tooltip title={new Date(latestVersion.timestamp).toISOString().slice(0, -8).replace('T', ' ')} placement="left" arrow >
<Box sx={{
<Tooltip
title={new Date(latestVersion.timestamp)
.toISOString()
.slice(0, -8)
.replace('T', ' ')}
placement="left"
arrow
>
<Box
sx={{
display: {
xs: 'none',
sm: 'inherit'
}
}} className={styles['secondary-typography']}>
}}
className={styles['secondary-typography']}
>
{timeSince(new Date(latestVersion.timestamp))} ago
</Box>
</Tooltip>
Expand All @@ -82,7 +95,14 @@ export default function Project(props: Props): React.JSX.Element {
{props.project.versions.length === 1
? `${props.project.versions.length} version`
: `${props.project.versions.length} versions`}
<Typography sx={{ marginLeft: 1.5 }} fontSize={'0.9em'} component={'span'} fontWeight={300}>{props.project.storage}</Typography>
<Typography
sx={{ marginLeft: 1.5 }}
fontSize={'0.9em'}
component={'span'}
fontWeight={300}
>
{props.project.storage}
</Typography>
</div>

<FavoriteStar
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/ProjectList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React from 'react'
import Project from './Project'

import { type Project as ProjectType } from '../models/ProjectsResponse'
Expand Down
47 changes: 26 additions & 21 deletions web/src/components/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,47 @@
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';

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): React.JSX.Element {
const [showFavourites, setShowFavourites] = useState(true);
const [searchParams, setSearchParams] = useSearchParams();
const [showFavourites, setShowFavourites] = useState(true)
const [searchParams, setSearchParams] = useSearchParams()

const { query, setQuery } = useSearch()
const [searchQuery, setSearchQuery] = useState<string>(query)


const updateSearch = (q: string) => {
setSearchQuery(q)
setQuery(q)

if (q) {
setSearchParams({q})
setSearchParams({ q })
} else {
setSearchParams({})
}
}

useEffect(() => {
const q = searchParams.get("q")
const q = searchParams.get('q')
if (q) {
updateSearch(q)
}
setShowFavourites(props.showFavourites)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.showFavourites]);
}, [props.showFavourites])

const onFavourites = (show: boolean): void => {
setSearchParams({})
setSearchQuery("")
setQuery("")
setSearchQuery('')
setQuery('')

setShowFavourites(show)
props.onShowFavourites(!show)
Expand All @@ -62,7 +60,7 @@ export default function SearchBar(props: Props): React.JSX.Element {
display: 'flex',
alignItems: 'center',
maxWidth: 600,
marginLeft: '16px',
marginLeft: '16px'
}}
>
<InputBase
Expand All @@ -77,15 +75,22 @@ export default function SearchBar(props: Props): React.JSX.Element {
setQuery(searchQuery)
}
}}

/>
<IconButton type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
</IconButton>
<Divider sx={{ height: 28, m: 0.5 }} orientation="vertical" />
<Tooltip title={`Show ${showFavourites ? 'all docs' : 'favourites only'}`} placement="right" arrow>
<IconButton onClick={() => onFavourites(!showFavourites)} sx={{ p: '10px' }} aria-label="directions">
{ showFavourites ? <StarIcon /> : <StarBorderIcon /> }
<Tooltip
title={`Show ${showFavourites ? 'all docs' : 'favourites only'}`}
placement="right"
arrow
>
<IconButton
onClick={() => onFavourites(!showFavourites)}
sx={{ p: '10px' }}
aria-label="directions"
>
{showFavourites ? <StarIcon /> : <StarBorderIcon />}
</IconButton>
</Tooltip>
</Paper>
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/StyledForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React from 'react'
import styles from './../style/components/StyledForm.module.css'

interface Props {
Expand Down
3 changes: 2 additions & 1 deletion web/src/data-providers/MessageBannerProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export const Context = React.createContext<MessageBannerState>({

export function MessageBannerProvider({ children }: any): JSX.Element {
// We need to store the last timeout, so we can clear when a new message is shown
const [lastTimeout, setLastTimeout] = useState<ReturnType<typeof setTimeout>>()
const [lastTimeout, setLastTimeout] =
useState<ReturnType<typeof setTimeout>>()
const [message, setMessage] = useState<Message>({
content: undefined,
type: 'success',
Expand Down
8 changes: 7 additions & 1 deletion web/src/data-providers/ProjectDataProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
We need any, because we don't know the type of the children
*/

import React, { createContext, useContext, useEffect, useState, JSX } from 'react'
import React, {
createContext,
useContext,
useEffect,
useState,
JSX
} from 'react'
import { type Project } from '../models/ProjectsResponse'
import type ProjectsResponse from '../models/ProjectsResponse'
import { useMessageBanner } from './MessageBannerProvider'
Expand Down
Loading
Loading