Utstillingsløsning
Nansen
Eksisterende system
(utelukker "spesialistsystem")
Hva er galt med ?
- Kan brukes headless... men fokuserer på tekst i ren html
- Mange plugins... men mange går i beina på hverandre
- Vanskelig å vite hvilke sideeffekter som kommer med
- Ukjent utviklingsprosess
- Driftes på IT... men vi har lite kontroll
- Kommer med en milliard themes... men unødvendig vanskelig å lage egne
spesial.w.uib.no ble, slik jeg ser det, beholdt fordi vi ikke hadde tilsvarende funksjonalitet i Protégé/Marcus. Planen har alltid vært å migrere innhold.
Hva er galt med ?
- Kan brukes headless... men PHP gjør at DU må håndtere to språk for én side
- Mange modules... men mange går i beina på hverandre
- Vanskelig å vite hvilke sideeffekter som kommer med
- Ukjent utviklingsprosess
- Driftes på IT... men vi har lite kontroll
- Kommer med en milliard themes... men unødvendig vanskelig å lage egne
Hva er galt med ?
- Kan brukes headless... men PHP gjør at DU må håndtere to språk for én side
- Mange modules... men mange går i beina på hverandre
- Vanskelig å vite hvilke sideeffekter som kommer med
- Ukjent utviklingsprosess
- Tilpassbar datamodel med domain-range... men håndhever den ikke
- Laget for nettutstillinger... men unødvendig dersom vi allerede må lage en løsning for Marcus?
Hva er galt med ?
- Er en frontend over en "headless CMS"... men PHP gjør at DU må håndtere to språk for én side
- PHP er serverside... må skrive JS for klienten
- Query-based template-engine... men håpløst utdatert
Kort sagt
- De har et gammelt driftskonsept
Et annet "systemlandskap"?
Birgitta
DEV
PROD
build
preview
data
build
trigger
ETL BUS
marcus.uib.no/
exhibition/nansen
npm i -g @sanity/cli
sanity init
project
Sanity
@seidhr/sanity-template-muna
marcus-monorepo
???
/api
/studio
/shared/ui-components
Felles git repositorie med felles komponenter som kan gjenbrukes og oppdateres på tvers av ulike frontends
/exhibitions
/
/search
Javascript
Hvilket rammeverk?
Basics
/pages
/pages/id
/pages/id/index.js
/pages/id/[id].js
/pages/actor/index.js
/pages/actor/[id].js
/pages/blog/index.js
/pages/blog/[id].js
...
/pages/api/manifest/index.js
/pages/api/manifest/[id].js
...
/components
/components/Footer.js
/components/Header.js
/components/Nav.js
/components/Sections
/components/Sections/index.js
/components/Sections/Hero.js
Next folder structure under pages equals URI paths
Components breaks the UI into smaller parts that can be reused on any page or on other sites if shared as a NPM package
API endpoints created in same manner as pages
Concepts.js
...
import {getAllConcepts} from '../../lib/api'
import Layout from '../../components/Layout'
import Header from '../../components/Header'
import {Container, List, ListItem} from '@chakra-ui/react'
import Link from '../../components/Link'
export default function Concepts({data, preview}) {
return (
<>
<Layout preview={preview}>
<Head>
<title>{CMS_NAME}</title>
</Head>
<Header menu={data.defaultNavMenu} />
<Container maxW="xl">
{data.items && (
<List>
{data.items
.filter((item) => item.count > 0)
.map((item) => (
<ListItem key={item._id}>
<Link href={`/id/${item._id}`}>{item.label.nor}</Link> <span>{item.count}</span>
</ListItem>
))}
</List>
)}
</Container>
</Layout>
</>
)
}
export async function getStaticProps({preview = false}) {
const data = await getAllConcepts(preview)
return {
props: {data, preview},
}
}
Component
import dynamic from 'next/dynamic'
import {Grid, Container, Box, Center, Heading, Text} from '@chakra-ui/react'
import PortableTextBlock from '../PortableTextBlock'
const MiradorWithNoSSR = dynamic(() => import('../Mirador'), {ssr: false})
export default function SingleObject(props) {
if (!props) { return null }
return (
<Container maxW="xl" centerContent>
<Grid
w="full"
p={5}
gridGap={5}
alignContent="start"
gridTemplateAreas={{xl: '"image image metadata"', base: '"image" "metadata"'}}
gridTemplateColumns={{xl: '6fr 6fr 2fr', base: '100%'}}
>
<Box gridArea="metadata">
<Heading fontSize="sm" mb={1} color="gray.600">
{props.heading}
</Heading>
{props?.description && (
<Box fontSize="xs" fontFamily="Montserrat" fontWeight="200">
<PortableTextBlock blocks={props.description} />
</Box>
)}
</Box>
{props?.item.manifest && (
<Box gridArea="image">
<MiradorWithNoSSR manifest={[props.item.manifest]} />
</Box>
)}
</Grid>
</Container>
)
}
/blog
data: Wordpress
func: getStaticProps
/
data: Sanity
func: getStaticProps
/id/*
data: API ? API : Sparql
func: getServerSideProps
/exhibition
data: Sanity
func: getStaticProps
export async function getStaticProps({preview = false}) {
const data = await getFrontpage(preview)
return {
props: {data, preview},
}
}
export async function getStaticProps({preview = false}) {
const data = await getWpBlogPosts(preview)
return {
props: {data, preview},
}
}
export async function getStaticProps({preview = false}) {
const data = await getPage(preview)
return {
props: {data, preview},
}
}
export async function getServerSideProps({preview = false}) {
const data = await getObject(preview)
return {
props: {data, preview},
}
}
//marcus.uib.no/
Fetching data
export async function getAllActors() {
const data = await client.fetch(`{
"items": *[_type in ["actor", "group"]] | order(label, desc){
"id": _id,
_type,
label,
hasType[]-> {
_id,
label
},
mainRepresentation,
"count": count(*[references(^._id)]),
},
${defaultNavMenu}
}`)
return data
}
{
@id: "0cdad732-e877-4609-b61a-7e780a9a9bba",
@type: "MadeObject",
hasType: [
{
@id: "bf229013-1d51-4666-8219-3ed7edcae4c1",
@type: "Type",
label: {
no: "Manuskript",
en: "Manuscript",
}
}
],
identifidBy: [
{
@id: "99d104c5-e569-4632-9d39-323e9b64c041",
@type: "Identifier",
content: "ubb-ms-0149-01",
}
],
title: "Håndskrevet bok, bestående av tre innførte bøker.",
hasThumbnail: {
@type: "http://www.w3.org/2001/XMLSchema#anyuri",
value: "https://api.ub.uib.no/iiif/image/b0383825-9151-4c34-accb-98e9e7651fa4",
},
subjectOfManifest: "https://api.ub.uib.no/iiif/manifest/0cdad732-e877-4609-b61a-7e780a9a9bba",
subject: [{
@id: "8749a213-48ba-441d-afbe-df0a63b0518d"
}],
description: `
En liden nyttig Eungeliske Epitoliske Haandbog
af Rasmus Suendsøn, Ottense (Odense).
`
}
{
@id: "55d8206d-6d38-46e6-86a3-fda8b44b8ea0",
@type: "linguisticObject",
hasType: [
{
@id: "58e6136e-4f1f-48a5-ba56-4267c6db58e6",
@type: "Type",
label: {
no: "Kort beskrivelse",
en: "Short description",
}
}
],
title: "Denne boken er for lang!",
refersTo: {
@id: "marcus:0cdad732-e877-4609-b61a-7e780a9a9bba"
},
content: "Åh, himmel og hav! Denne bok tar jo aldri slutt!",
}
Sanity JSON to JSON-LD
function toJSONids(arr) {
return arr.map((o) =>
rename(o, function (key) {
if (key === "_id" || key === "_ref" || key === "_key") return "id";
return key;
})
);
}
// All PortableText must be converted to html
const pt2html = madeObjects.map((o) =>
({
...o,
referredToBy: o.referredToBy.map(b => ({
...b,
body: blocksToHtml({
blocks: b.body,
serializers: serializers,
})
}))
})
)
const fixIDs = toJSONids(pt2html)
const removedRev = fixIDs.map(o => {return removeKey(o, "_rev")});
const removeUnderscore = removedRev.map((o) =>
rename(o, function (key) {
if (key.startsWith('_')) {
return key.substring(1)
};
return key;
})
)
const result = filterObject(removeUnderscore, "type", "reference");
const json = {
...context,
"@graph": [...result],
};
API
Document api structure before coding
Infrastructure scrible
Utstillingsløsning
By Tarje Lavik
Utstillingsløsning
- 282