Skip to content

Commit

Permalink
Feature/terms of use (#26)
Browse files Browse the repository at this point in the history
* Simplify component AcceptTermsOfuse

* add termsOfUseService to services

* add use-on-sreen hook

* remove background animation temporarily

* clean initial export values

* put env file env variable to default

* add scrollable terms of use with button enabled only when the whole page has been "read"

* add contents from src/content/pagesContents collection as MD pages

* working

see #28
  • Loading branch information
danieleguido authored Oct 16, 2024
1 parent e3f33ba commit cacc6d9
Show file tree
Hide file tree
Showing 18 changed files with 250 additions and 34 deletions.
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ PUBLIC_IMPRESSO_DATALAB_SITE=http://localhost
PUBLIC_IMPRESSO_API_HOST=http://localhost
PUBLIC_IMPRESSO_API_PATH=/public-api
PUBLIC_IMPRESSO_WS_API_HOST=http://localhost
PUBLIC_IMPRESSO_WS_API_PATH=/api/socket.io
PUBLIC_IMPRESSO_WS_API_PATH=/socket.io

PUBLIC_IMPRESSO_PROXY_API_PATH=/public-api
PUBLIC_IMPRESSO_PROXY_WS_API_PATH=/api/socket.io
PUBLIC_IMPRESSO_PROXY_WS_API_PATH=/socket.io
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ static/data/
!static/data/.gitkeep
src/styles/fonts.css
impresso-datalab.code-workspace
.env.development
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ run-dev:
PUBLIC_BUILD_DATE=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') \
PUBLIC_GIT_REMOTE=$(shell git config --get remote.origin.url) \
PUBLIC_IMPRESSO_API_PATH="/public-api" \
PUBLIC_IMPRESSO_WS_API_PATH="/api/socket.io" \
PUBLIC_IMPRESSO_WS_API_PATH="/socket.io" \
PUBLIC_IMPRESSO_DATALAB_BASE="/datalab" \
PUBLIC_IMPRESSO_DATALAB_SITE="https://impresso-project.ch" \
npm run dev
Expand Down
13 changes: 10 additions & 3 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@ const PublicApiTarget =
const PublicApiPath = process.env.PUBLIC_IMPRESSO_API_PATH ?? "/public-api"

// these values are relevant only when the proxy is used with different paths, e.g; for a local instance of impresso middle layer
const ProxyPublicApiPath =
process.env.PUBLIC_IMPRESSO_PROXY_API_PATH ?? "/public-api"
const ProxyPublicApiPath = process.env.PUBLIC_IMPRESSO_API_PATH ?? "/public-api"
const ProxyWsApiPath =
process.env.PUBLIC_IMPRESSO_PROXY_WS_API_PATH ?? "/api/socket.io"
process.env.PUBLIC_IMPRESSO_WS_API_PATH ?? "/api/socket.io"

if (process.env.NODE_ENV === "development") {
console.log("WsApiTarget:", WsApiTarget)
console.log("WsApiPath:", WsApiPath)
console.log("PublicApiTarget:", PublicApiTarget)
console.log("PublicApiPath:", PublicApiPath)
console.log("ProxyPublicApiPath:", ProxyPublicApiPath)
console.log("ProxyWsApiPath:", ProxyWsApiPath)
}
// https://astro.build/config
export default defineConfig({
integrations: [react(), mdx()],
Expand Down
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@astrojs/react": "^3.6.2",
"@astrolib/seo": "^1.0.0-beta.6",
"@codemirror/lang-python": "^6.1.6",
"@custom-react-hooks/use-on-screen": "^1.5.1",
"@feathersjs/authentication-client": "^5.0.30",
"@feathersjs/feathers": "^5.0.30",
"@feathersjs/socketio-client": "^5.0.30",
Expand Down
19 changes: 16 additions & 3 deletions src/components/AboutModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import { Col, Container, Row } from "react-bootstrap"
import MarkdownSnippet from "./MarkdownSnippet"
import Page from "./Page"

const AboutModal: React.FC = () => {
const AboutModal: React.FC<{ content: string }> = ({
content,
}: {
content: string
}) => {
return (
<Page title="About- Impresso Datalab" fullscreen="xl-down" size="xl">
<h1>About</h1>
<Page title="About - Impresso Datalab" fullscreen="xl-down" size="xl">
<Container>
<Row>
<h1 className="my-3">About</h1>
<Col className="mt-3">
<MarkdownSnippet value={content} />
</Col>
</Row>
</Container>
</Page>
)
}
Expand Down
28 changes: 18 additions & 10 deletions src/components/AcceptTermsOfUse.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
import { useState } from "react"
import { Form } from "react-bootstrap"
import type { FC, ChangeEvent } from "react"

const AcceptTermsOfUse = () => {
const [accepted, setAccepted] = useState(false)

const handleAccept = () => {
setAccepted((accepted) => !accepted)
}
interface AcceptTermsOfUseProps {
disabled?: boolean
checked?: boolean
onChange?: (event: ChangeEvent<HTMLInputElement>) => void
}

const AcceptTermsOfUse: FC<AcceptTermsOfUseProps> = ({
disabled = false,
checked = false,
onChange = () => {
console.log("AcceptTermsOfUse.onChange")
},
}) => {
return (
<Form.Check>
<Form.Check.Input
type="checkbox"
id="terms-of-use"
checked={accepted}
onChange={handleAccept}
checked={checked}
onChange={onChange}
disabled={disabled}
/>
<Form.Check.Label htmlFor="terms-of-use">
I accept the terms of use
I accept the terms of use {disabled ? "(disabled)" : ""}
</Form.Check.Label>
</Form.Check>
)
}

export default AcceptTermsOfUse
4 changes: 2 additions & 2 deletions src/components/Background.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { a, config, useSpring } from "@react-spring/web"
const Background = () => {
const windowWidth = useRef(window.innerWidth)
const windowHeight = useRef(window.innerHeight)
const [{ x, y }, api] = useSpring(() => ({
const [{ x, y }] = useSpring(() => ({
x: window.innerWidth / 2,
y: window.innerHeight / 2,
config: config.molasses,
Expand All @@ -19,7 +19,7 @@ const Background = () => {
const mouseMoveEvent = (e: MouseEvent) => {
const x = e.pageX - windowWidth.current / 2
const y = e.pageY - windowHeight.current / 2
api.start({ x, y })
// api.start({ x, y })
}
useEffect(() => {
document.addEventListener("mousemove", mouseMoveEvent)
Expand Down
7 changes: 6 additions & 1 deletion src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ const Header: React.FC = () => {
</Nav.Item>
<Nav.Item>
<Link to="/notebooks" className="nav-link ">
browse Ipynb notebooks
browse notebooks
</Link>
</Nav.Item>
<Nav.Item>
<Link to="/about" className="nav-link ">
about
</Link>
</Nav.Item>
<Nav.Item>
Expand Down
4 changes: 2 additions & 2 deletions src/components/MarkdownSnippet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface MarkdownSnippetProps {
className?: string
}

const MarkdownSnipped: React.FC<MarkdownSnippetProps> = ({
const MarkdownSnippet: React.FC<MarkdownSnippetProps> = ({
value = "",
className = "",
}) => {
Expand All @@ -18,4 +18,4 @@ const MarkdownSnipped: React.FC<MarkdownSnippetProps> = ({
)
}

export default MarkdownSnipped
export default MarkdownSnippet
129 changes: 125 additions & 4 deletions src/components/TermsOfUseModal.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,139 @@
import { useEffect, useRef, useState, type ChangeEvent } from "react"
import AcceptTermsOfUse from "./AcceptTermsOfUse"
import Page from "./Page"
import { Container, Row } from "react-bootstrap"
import { Col, Container, Row } from "react-bootstrap"
import { useBrowserStore, usePersistentStore } from "../store"
import { accountDetailsService } from "../services"
import { DateTime } from "luxon"
import { useOnScreen } from "@custom-react-hooks/use-on-screen"
import MarkdownSnippet from "./MarkdownSnippet"

const TermsOfUseModal: React.FC = () => {
const TermsOfUseModal: React.FC<{ content: string }> = ({
content,
}: {
content: string
}) => {
const { ref: bottomRef, isIntersecting } = useOnScreen(
{ threshold: 0.5 },
false,
)

const wsStatus = useBrowserStore((state) => state.wsStatus)
const [token] = usePersistentStore((state) => [state.token, state.user])
const [isBusy, setIsBusy] = useState<boolean>(false)

const [acceptedTermsDate, setAcceptedTermsDate] = useState<DateTime | null>(
null,
)

const [enableAcceptTermsButton, setEnableAcceptTermsButton] =
useState<boolean>(false)

useEffect(
() => {
if (wsStatus !== "connected") {
console.debug(
"[TermsOfUseModal] @useEffect - ws not connected, current status",
wsStatus,
)
return
}
if (token === null) {
return
}
console.debug(
"[TermsOfUseModal] @useEffect - ws connected, call accountDetails.find() ...",
)
setIsBusy(true)
accountDetailsService
.find()
.then((data) => {
console.debug(
"[TermsOfUseModal] @useEffect accountDetails.find() success:",
data,
)
setAcceptedTermsDate(DateTime.fromISO(data.dateAcceptedTerms))
setIsBusy(false)
})
.catch((err) => {
console.error("[TermsOfUseModal] @useEffect - error", err)
setIsBusy(false)
})
},
// eslint-disable-next-line
[wsStatus, token],
)

useEffect(() => {
if (!enableAcceptTermsButton && isIntersecting) {
setEnableAcceptTermsButton(true)
}
}, [enableAcceptTermsButton, isIntersecting])

const AcceptTermsOfUseOnChangeHandler = (
event: ChangeEvent<HTMLInputElement>,
) => {
if (isBusy) {
console.debug("[TermsOfUseModal] AcceptTermsOfUse@onChange - isBusy")
return
}
console.debug(
"[TermsOfUseModal] AcceptTermsOfUse@onChange call accountDetails.patch() ...",
)
setIsBusy(true)
accountDetailsService
.patch(null, {
acceptTerms: event.target.checked,
})
.then((data) => {
console.debug(
"[TermsOfUseModal] AcceptTermsOfUse@onChange call accountDetails.patch() success:",
data,
)
})
.finally(() => {
setIsBusy(false)
})
}
return (
<Page
title="Terms Of Use - Impresso Datalab"
fullscreen="xl-down"
size="xl"
footer={<AcceptTermsOfUse />}
modalBodyClassName="pt-0 px-2"
footer={
<AcceptTermsOfUse
checked={acceptedTermsDate?.isValid}
onChange={AcceptTermsOfUseOnChangeHandler}
disabled={!enableAcceptTermsButton}
/>
}
>
<Container>
<Row>
<h1>Terms of Use</h1>
<h1 className="my-3">Terms of Use</h1>
<Col className="position-sticky top-0 bg-light m-0 py-2">
{acceptedTermsDate?.isValid ? (
<p className="m-0">
You have accepted the terms of use:{" "}
<b>
{acceptedTermsDate
?.setLocale("en-GB")
.toLocaleString(DateTime.DATETIME_FULL) ?? "N/A"}
</b>
</p>
) : (
<p className="m-0">
You have not accepted the terms of use yet. Please read the{" "}
<b>entire</b> terms of use document carefully and accept it at
the bottom to continue.
</p>
)}
</Col>
<div style={{ minHeight: "100vh" }}>
<MarkdownSnippet value={content} />
</div>
<div ref={bottomRef as React.RefObject<HTMLDivElement>}>bottom</div>
</Row>
</Container>
</Page>
Expand Down
8 changes: 8 additions & 0 deletions src/content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ const series = defineCollection({
notebooks: z.array(reference("notebooks")),
}),
})

const pagesContents = defineCollection({
type: "content",
schema: z.object({
title: z.string(),
}),
})
// 3. Export a single `collections` object to register your collection(s)
// This key should match your collection directory name in "src/content"
export const collections = {
Expand All @@ -78,4 +85,5 @@ export const collections = {
series,
associatedPartners,
plans,
pagesContents,
}
28 changes: 28 additions & 0 deletions src/content/pagesContents/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
title: About
---

The Impresso Datalab is an infrastructure for programmatic data access and annotation services and is developed by the [Impresso project](https://impresso-project.ch) which strives to create meaningful links across historical media collections. The Datalab enables custom analyses of the Impresso corpus and the semantic indexation of external document collections also with the help of models created by the project.

The Datalab offers access to our corpus, data and models via the Impresso Public API, a dedicated Python library and via [HuggingFace](https://huggingface.co/impresso-project). To keep the learning curve manageable, the Datalab includes Jupyter notebooks for documentation and templates to kickstart computational analysis, visualisation and enrichment.

## Motivations for the Impresso Datalab

With the creation of the Datalab, we reflect changing scholarly practices for the interaction with digitised cultural heritage collections. Its design and development is driven by five objectives:

Complement generic data exploration via the Impresso Web App with objective-driven analysis and enrichment of datasets for specific research and teaching use cases.
Enable the semantic indexation of historical documents outside the Impresso corpus using models generated by the Impresso project.
Facilitate the linking of external research data with the Impresso corpus on the level of semantic enrichments.
Reflect changing research practices which rely on executable notebooks for the documentation and reproduction of data-driven research.
Offer accessible educational resources and notebook templates to researchers at any level of coding proficiency.

Overall, the Datalab supports researchers who are confronted with digitised collections with variable depth of annotation and seek to overcome the limitations of off-the-shelf graphical user interfaces.

## Access management

The Impresso project works with a consortium of partnering libraries and archives on the grounds of legal agreements which respect diverse copyright regulations. The Impresso Terms of Use describe which data is available and how it may be used.
Our User Plans reflect variations in access rights for the general public, students and researchers. Note that user plans will evolve in the course of the project and make sure to consult our corpus overview page to understand which data is currently available.

## Continuous development and feedback

The Datalab will remain in constant development throughout the Impresso project. We appreciate any kind of feedback on its usage and look forward to proposals for additional notebooks via info (at) impresso-project.ch.
5 changes: 5 additions & 0 deletions src/content/pagesContents/terms-of-use.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Terms of use
---

The Impresso Datalab is an infrastructure for programmatic data access and annotation services and is developed by the [Impresso project](https://impresso-project.ch) which strives to create meaningful links across historical media collections. The Datalab enables custom analyses of the Impresso corpus and the semantic indexation of external document collections also with the help of models created by the project.
Loading

0 comments on commit cacc6d9

Please sign in to comment.