Skip to content

Commit

Permalink
Merge pull request #973 from research-software-directory/955-improve-…
Browse files Browse the repository at this point in the history
…performance

955 improve performance
  • Loading branch information
dmijatovic authored Sep 1, 2023
2 parents 37d25da + 136f411 commit 07104a4
Show file tree
Hide file tree
Showing 28 changed files with 280 additions and 219 deletions.
6 changes: 4 additions & 2 deletions database/002-create-image-table.sql
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
-- SPDX-FileCopyrightText: 2022 - 2023 Netherlands eScience Center
-- SPDX-FileCopyrightText: 2022 Dusan Mijatovic (dv4all)
-- SPDX-FileCopyrightText: 2022 Ewan Cahen (Netherlands eScience Center) <[email protected]>
-- SPDX-FileCopyrightText: 2022 Netherlands eScience Center
-- SPDX-FileCopyrightText: 2022 dv4all
-- SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
--
-- SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -41,6 +42,7 @@ CREATE TRIGGER sanitise_update_image BEFORE UPDATE ON image FOR EACH ROW EXECUTE

-- ----------------------------------------
-- RPC to get image by id => sha-1 of data
-- cache incrased to 1 year based on lighthouse audit
-- ----------------------------------------

CREATE FUNCTION get_image(uid VARCHAR(40)) RETURNS BYTEA STABLE LANGUAGE plpgsql AS
Expand All @@ -52,7 +54,7 @@ BEGIN
SELECT format(
'[{"Content-Type": "%s"},'
'{"Content-Disposition": "inline; filename=\"%s\""},'
'{"Cache-Control": "max-age=259200"}]',
'{"Cache-Control": "max-age=31536001"}]',
mime_type,
uid)
FROM image WHERE id = uid INTO headers;
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ services:
# dockerfile to use for build
dockerfile: Dockerfile
# update version number to correspond to frontend/package.json
image: rsd/frontend:2.0.0
image: rsd/frontend:2.0.1
environment:
# it uses values from .env file
- POSTGREST_URL
Expand Down
6 changes: 4 additions & 2 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# SPDX-FileCopyrightText: 2021 - 2022 Dusan Mijatovic (dv4all)
# SPDX-FileCopyrightText: 2021 - 2022 dv4all
# SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
# SPDX-FileCopyrightText: 2023 Netherlands eScience Center
#
# SPDX-License-Identifier: Apache-2.0

Expand All @@ -10,7 +12,7 @@
# ----------------------------------------
# 1. Install dependencies only when needed
# ----------------------------------------
FROM node:18.5-buster-slim AS deps
FROM node:20.5-slim AS deps

WORKDIR /app

Expand Down Expand Up @@ -45,7 +47,7 @@ RUN yarn build
# ----------------------------------------
# 3. Production image (standalone mode)
# ----------------------------------------
FROM node:18.5-buster-slim AS runner
FROM node:20.5-slim AS runner

# optional install updates
# RUN apt-get upgrade -y
Expand Down
33 changes: 27 additions & 6 deletions frontend/auth/api/useLoginProviders.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
// SPDX-FileCopyrightText: 2022 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2022 dv4all
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 Netherlands eScience Center
//
// SPDX-License-Identifier: Apache-2.0

import {useEffect, useState} from 'react'

import {Provider} from 'pages/api/fe/auth'

// save info after initial call
let loginProviders:Provider[] = []

export default function useLoginProviders() {
const [providers, setProviders] = useState<Provider[]>([])

// console.group('useLoginProviders')
// console.log('providers...', providers)
// console.log('loginProviders...', loginProviders)
// console.groupEnd()

useEffect(() => {
let abort = false

async function getProviders() {
const url = '/api/fe/auth'
const resp = await fetch(url)
if (resp.status === 200 && abort === false) {
const providers: Provider[] = await resp.json()
if (abort) return
setProviders(providers)
if (loginProviders.length === 0){
const url = '/api/fe/auth'
const resp = await fetch(url)
if (resp.status === 200 && abort === false) {
const providers: Provider[] = await resp.json()
if (abort) return
setProviders(providers)
// api response is the same once the app is started
// because the info eventually comes from .env file
// to avoid additional api calls we save api response
// into the loginProviders variable and reuse it
loginProviders = [
...providers
]
}
}else if (abort===false){
setProviders(loginProviders)
}
}
if (abort === false) {
Expand Down
16 changes: 14 additions & 2 deletions frontend/components/AppHeader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,20 @@ export default function AppHeader() {
className="flex-1 flex flex-col px-4 xl:flex-row items-start lg:container lg:mx-auto">
<div className="w-full flex-1 flex items-center justify-between">
<Link href="/" passHref className="hover:text-inherit" aria-label="Link to home page">
<LogoApp className="hidden 2xl:block"/>
<LogoAppSmall className="block 2xl:hidden"/>
<LogoApp
className="hidden 2xl:block"
loading='eager'
// lighthouse audit requires explicit width and height
width="100%"
height="1.5rem"
/>
<LogoAppSmall
className="2xl:hidden"
loading='eager'
// lighthouse audit requires explicit width and height
width="100%"
height="1.5rem"
/>
</Link>

<GlobalSearchAutocomplete className="hidden xl:block ml-12 mr-6"/>
Expand Down
3 changes: 3 additions & 0 deletions frontend/components/layout/ImageWithPlaceholder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ export default function ImageWithPlaceholder({
title={placeholder ?? alt}
role="img"
src={src}
// lighthouse audit requires explicit width and height
height="100%"
width="100%"
style={{
objectFit: bgSize,
objectPosition: bgPosition
Expand Down
7 changes: 5 additions & 2 deletions frontend/components/layout/LogoAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// SPDX-FileCopyrightText: 2022 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2022 dv4all
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 Netherlands eScience Center
//
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -19,13 +21,14 @@ export default function LogoAvatar({name,src,sx,...props}:LogoAvatarProps) {
alt={name}
src={src}
sx={{
// lighthouse audit requires explicit width and height
width: '100%',
height: '100%',
fontSize: '3rem',
'& img': {
height: 'auto',
// height: 'auto',
maxHeight: '100%',
width: 'auto',
// width: 'auto',
maxWidth: '100%'
},
...sx
Expand Down
2 changes: 0 additions & 2 deletions frontend/components/login/LoginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ import useLoginProviders from '~/auth/api/useLoginProviders'
import {getUserMenuItems} from '~/config/userMenuItems'
import UserMenu from '~/components/layout/UserMenu'
import LoginDialog from './LoginDialog'
import useRsdSettings from '~/config/useRsdSettings'

export default function LoginButton() {
const {host} = useRsdSettings()
const providers = useLoginProviders()
const {session} = useAuth()
const status = session?.status || 'loading'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2022 - 2023 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2022 - 2023 Dusan Mijatovic (dv4all) (dv4all)
// SPDX-FileCopyrightText: 2022 - 2023 dv4all
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 Ewan Cahen (Netherlands eScience Center) <[email protected]>
// SPDX-FileCopyrightText: 2023 Netherlands eScience Center
//
Expand All @@ -21,7 +22,7 @@ import projectState from '../__mocks__/editProjectState'

const mockGetImpactForProject = jest.fn((props) => Promise.resolve(mockImpactForProject))
jest.mock('~/utils/getProjects', () => ({
getImpactForProject: jest.fn((props)=>mockGetImpactForProject(props))
getMentionsForProject: jest.fn((props)=>mockGetImpactForProject(props))
}))

const mockGetMentionByDoiFromRsd = jest.fn((props) => Promise.resolve([] as any))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2023 Ewan Cahen (Netherlands eScience Center) <[email protected]>
// SPDX-FileCopyrightText: 2023 Netherlands eScience Center
Expand All @@ -10,7 +11,7 @@ import ImportMentions from '~/components/mention/ImportMentions/index'
import ImportMentionsInfoPanel from '~/components/mention/ImportMentions/ImportMentionsInfoPanel'
import useEditMentionReducer from '~/components/mention/useEditMentionReducer'
import useProjectContext from '~/components/projects/edit/useProjectContext'
import {getImpactForProject} from '~/utils/getProjects'
import {getMentionsForProject} from '~/utils/getProjects'
import {cfgImpact as config} from './config'

export default function ImportProjectImpact() {
Expand All @@ -20,7 +21,7 @@ export default function ImportProjectImpact() {

async function reloadImpact() {
setLoading(true)
const data = await getImpactForProject({project: project.id, token: token, frontend: true})
const data = await getMentionsForProject({project: project.id,table:'impact_for_project',token: token})
setMentions(data)
setLoading(false)
}
Expand Down
11 changes: 6 additions & 5 deletions frontend/components/projects/edit/impact/useImpactForProject.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// SPDX-FileCopyrightText: 2022 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2022 Dusan Mijatovic (dv4all) (dv4all)
// SPDX-FileCopyrightText: 2022 dv4all
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 Netherlands eScience Center
//
// SPDX-License-Identifier: Apache-2.0

import {useEffect, useState} from 'react'
import {getImpactForProject} from '~/utils/getProjects'
import {getMentionsForProject} from '~/utils/getProjects'

import {sortOnNumProp} from '~/utils/sortFn'
import useEditMentionReducer from '~/components/mention/useEditMentionReducer'
Expand All @@ -24,11 +26,10 @@ export default function useImpactForProject({project, token}: ImpactForProjectPr
let abort = false
async function getImpactFromApi() {
setLoading(true)
// TODO! this request is made two times, investigate
const mentionsForProject = await getImpactForProject({
const mentionsForProject = await getMentionsForProject({
project,
token,
frontend: true
table:'impact_for_project',
token
})
if (mentionsForProject && abort === false) {
const mentions:MentionItemProps[] = mentionsForProject.sort((a, b) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (dv4all) (dv4all)
// SPDX-FileCopyrightText: 2023 Ewan Cahen (Netherlands eScience Center) <[email protected]>
Expand All @@ -22,7 +23,7 @@ import outputForProject from './__mocks__/outputForProject.json'
// MOCK getOutputForProject
const mockGetOutputForProject = jest.fn((props) => Promise.resolve(outputForProject))
jest.mock('~/utils/getProjects', () => ({
getOutputForProject: jest.fn((props)=>mockGetOutputForProject(props))
getMentionsForProject: jest.fn((props)=>mockGetOutputForProject(props))
}))
// MOCK getMentionByDoiFromRsd
const mockGetMentionByDoiFromRsd = jest.fn((props) => Promise.resolve([] as any))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// SPDX-License-Identifier: Apache-2.0

import {useSession} from '~/auth'
import {getOutputForProject} from '~/utils/getProjects'
import {getMentionsForProject} from '~/utils/getProjects'
import ImportMentions from '~/components/mention/ImportMentions/index'
import ImportMentionsInfoPanel from '~/components/mention/ImportMentions/ImportMentionsInfoPanel'
import useEditMentionReducer from '~/components/mention/useEditMentionReducer'
Expand All @@ -21,7 +21,7 @@ export default function ImportProjectOutput() {

async function reloadOutput() {
setLoading(true)
const data = await getOutputForProject({project: project.id, token: token, frontend: true})
const data = await getMentionsForProject({project: project.id,table:'output_for_project',token: token})
setMentions(data)
setLoading(false)
}
Expand Down
17 changes: 7 additions & 10 deletions frontend/components/projects/edit/output/useOutputForProject.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// SPDX-FileCopyrightText: 2022 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2022 dv4all
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 Netherlands eScience Center
//
// SPDX-License-Identifier: Apache-2.0

import {useEffect, useState} from 'react'
import useEditMentionReducer from '~/components/mention/useEditMentionReducer'
import {MentionItemProps} from '~/types/Mention'
import {getOutputForProject} from '~/utils/getProjects'
import {getMentionsForProject} from '~/utils/getProjects'
import {sortOnNumProp} from '~/utils/sortFn'

type OutputForProjectProps = {
Expand All @@ -22,10 +24,10 @@ export default function useOutputForProject({project, token}: OutputForProjectPr
let abort = false
async function getImpact() {
setLoading(true)
const mentions = await getOutputForProject({
const mentions = await getMentionsForProject({
project,
token,
frontend: true
table:'output_for_project',
token
})
const output:MentionItemProps[] = mentions.sort((a, b) => {
// sort mentions on publication year, newest at the top
Expand All @@ -41,12 +43,7 @@ export default function useOutputForProject({project, token}: OutputForProjectPr
if (project && token && project!==loadedProject) {
getImpact()
}
// else {
// console.group('skip request useOutputForProject')
// console.log('project...', project)
// console.log('loadedProject...', loadedProject)
// console.groupEnd()
// }

return () => { abort = true }
// we skip setMentions and setLoading methods in the deps to avoid loop
// TODO! try wrapping methods of useEditMentionReducer in useCallback?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 Netherlands eScience Center
//
// SPDX-License-Identifier: Apache-2.0

import useValidateImageSrc from '~/utils/useValidateImageSrc'

export default function ListImageWithGradientPlaceholder({imgSrc,alt}:{imgSrc:string|null, alt:string|null}) {
const validImg = useValidateImageSrc(imgSrc)

// console.group('ListItemImageWithGradientPlaceholder')
// console.log('imgSrc...', imgSrc)
// console.log('validImg...', validImg)
// console.groupEnd()

if (validImg === false || imgSrc === null){
// return gradient square as placeholder
return (
<div
className="w-12 self-stretch bg-gradient-to-br from-base-300 from-0% via-base-100 via-50% to-base-100"
/>
)
}

return (
<img
src={`${imgSrc ?? ''}`}
alt={alt ?? 'Image'}
className="w-12 max-h-[3.5rem] text-base-content-disabled p-2 object-contain object-center"
// lighthouse audit requires explicit width and height
height="2.5rem"
width="100%"
/>
)
}
Loading

0 comments on commit 07104a4

Please sign in to comment.