Skip to content

Commit

Permalink
Add a page with basic details about the logged-in user
Browse files Browse the repository at this point in the history
Refs #976
  • Loading branch information
thewilkybarkid committed Jun 2, 2023
1 parent ba069a5 commit 88fdb28
Show file tree
Hide file tree
Showing 37 changed files with 360 additions and 3 deletions.
30 changes: 30 additions & 0 deletions assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -596,9 +596,39 @@ dl {
column-gap: var(--space-3xs-2xs);
}
}

@nest main > & {
margin-block-start: var(--space-m);
max-inline-size: 64ch;

& > div {
display: flex;
flex-wrap: wrap;
column-gap: var(--space-xs-m);
row-gap: var(--space-4xs);
margin-block-start: var(--space-2xs);

& + div {
border-block-start: var(--width-divider-narrow) solid var(--color-divider-light);
padding-block-start: var(--space-2xs);
}

@media screen {
@media (width < 30em) {
flex-direction: column;
}
}
}

& dt {
min-inline-size: 20ch;
}
}
}

dt {
font-weight: 500;

@nest header & {
font-weight: 700;
-moz-osx-font-smoothing: grayscale;
Expand Down
20 changes: 20 additions & 0 deletions integration/log-in.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { areLoggedIn, canLogIn, expect, test } from './base'

test.extend(canLogIn).extend(areLoggedIn)('can view my details', async ({ javaScriptEnabled, page }) => {
await page.goto('/my-details')

await expect(page.getByRole('heading', { level: 1 })).toHaveText('My details')
await expect(page).toHaveScreenshot()

await page.keyboard.press('Tab')

await expect(page.getByRole('link', { name: 'Skip to main content' })).toBeFocused()
await expect(page).toHaveScreenshot()

await page.keyboard.press('Enter')

if (javaScriptEnabled) {
await expect(page.getByRole('main')).toBeFocused()
}
await expect(page).toHaveScreenshot()
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
import { getPreprintIdFromLegacyPreviewUuid, getProfileIdFromLegacyPreviewUuid } from './legacy-prereview'
import { legacyRoutes } from './legacy-routes'
import { authenticate, authenticateError, logIn, logOut } from './log-in'
import { myDetails } from './my-details'
import { getNameFromOrcid } from './orcid'
import type { FathomEnv, PhaseEnv } from './page'
import { partners } from './partners'
Expand All @@ -68,6 +69,7 @@ import {
homeMatch,
logInMatch,
logOutMatch,
myDetailsMatch,
orcidCodeMatch,
orcidErrorMatch,
partnersMatch,
Expand Down Expand Up @@ -367,6 +369,28 @@ export const router: P.Parser<RM.ReaderMiddleware<AppEnv, StatusOpen, ResponseEn
})),
),
),
pipe(
myDetailsMatch.parser,
P.map(() => myDetails),
P.map(
R.local((env: AppEnv) => ({
...env,
/*getName: flip(getNameFromOrcid)(env),
getPrereviews: flip(getPrereviewsForProfileFromZenodo)({
...env,
getPreprintTitle: flow(
flip(getPreprintTitle)(env),
TE.mapLeft(error =>
match(error)
.with('not-a-preprint', () => 'not-found' as const)
.otherwise(identity),
),
),
}),*/
getUser: () => pipe(getSession(), chainOptionKW(() => 'no-session' as const)(getUserFromSession))(env),
})),
),
),
pipe(
profileMatch.parser,
P.map(({ profile: profileId }) => profile(profileId)),
Expand Down
76 changes: 76 additions & 0 deletions src/my-details.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import type { Reader } from 'fp-ts/Reader'
import { pipe } from 'fp-ts/function'
import { type ResponseEnded, Status, type StatusOpen } from 'hyper-ts'
import type { OAuthEnv } from 'hyper-ts-oauth'
import * as RM from 'hyper-ts/lib/ReaderMiddleware'
import { P, match } from 'ts-pattern'
import { html, plainText, sendHtml } from './html'
import { logInAndRedirect } from './log-in'
import { serviceUnavailable } from './middleware'
import { type FathomEnv, type PhaseEnv, page } from './page'
import type { PublicUrlEnv } from './public-url'
import { myDetailsMatch } from './routes'
import { getUser } from './user'
import type { GetUserEnv, User } from './user'

export const myDetails = pipe(
getUser,
chainReaderKW(createPage),
RM.ichainFirst(() => RM.status(Status.OK)),
RM.ichainMiddlewareKW(sendHtml),
RM.orElseW(error =>
match(error)
.with(
'no-session',
() =>
logInAndRedirect(myDetailsMatch.formatter, {}) as RM.ReaderMiddleware<
GetUserEnv & FathomEnv & PhaseEnv & PublicUrlEnv & OAuthEnv,
StatusOpen,
ResponseEnded,
never,
void
>,
)
.with(P.instanceOf(Error), () => serviceUnavailable)
.exhaustive(),
),
)

function createPage(user: User) {
return page({
title: plainText`My details`,
content: html`
<main id="main-content">
<h1>My details</h1>
<dl>
<div>
<dt>ORCID iD</dt>
<dd><a href="https://orcid.org/${user.orcid}" class="orcid">${user.orcid}</a></dd>
</div>
<div>
<dt>PREreview pseudonym</dt>
<dd>${user.pseudonym}</dd>
</div>
</dl>
</main>
`,
skipLinks: [[html`Skip to main content`, '#main-content']],
user,
})
}

// https://github.com/DenisFrezzato/hyper-ts/pull/85
function fromReaderK<R, A extends ReadonlyArray<unknown>, B, I = StatusOpen, E = never>(
f: (...a: A) => Reader<R, B>,
): (...a: A) => RM.ReaderMiddleware<R, I, I, E, B> {
return (...a) => RM.rightReader(f(...a))
}

// https://github.com/DenisFrezzato/hyper-ts/pull/85
function chainReaderKW<R2, A, B>(
f: (a: A) => Reader<R2, B>,
): <R1, I, E>(ma: RM.ReaderMiddleware<R1, I, I, E, A>) => RM.ReaderMiddleware<R1 & R2, I, I, E, B> {
return RM.chainW(fromReaderK(f))
}
6 changes: 3 additions & 3 deletions src/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,18 @@ export function page({
<title>${title}</title>
${scripts.map(file => html`<script src="${assets[file].path}" type="module"></script>`)}
${scripts.map(file => html` <script src="${assets[file].path}" type="module"></script>`)}
<link href="${assets['style.css']}" rel="stylesheet" />
${scripts.flatMap(
flow(
file => assets[file].preload as ReadonlyArray<string>,
RA.map(preload => html`<link href="${preload}" rel="preload" fetchpriority="low" as="script" />`),
RA.map(preload => html` <link href="${preload}" rel="preload" fetchpriority="low" as="script" />`),
),
)}
${fathomId
? html`<script src="https://cdn.usefathom.com/script.js" data-site="${fathomId}" defer></script>`
? html` <script src="https://cdn.usefathom.com/script.js" data-site="${fathomId}" defer></script>`
: ''}
<link rel="icon" href="${assets['favicon.ico']}" sizes="any" />
Expand Down
2 changes: 2 additions & 0 deletions src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ export const orcidErrorMatch = pipe(
P.then(P.end),
)

export const myDetailsMatch = pipe(P.lit('my-details'), P.then(P.end))

export const profileMatch = pipe(P.lit('profiles'), P.then(type('profile', ProfileIdC)), P.then(P.end))

export const preprintReviewsMatch = pipe(P.lit('preprints'), P.then(type('id', PreprintIdC)), P.then(P.end))
Expand Down
Loading

0 comments on commit 88fdb28

Please sign in to comment.