mirror of
https://github.com/navikt/aksel.git
synced 2026-10-13 17:22:02 +00:00
Compare commits
129
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51bbeb00b0 | ||
|
|
79773ff44b | ||
|
|
1e7633e692 | ||
|
|
ba22ba7b70 | ||
|
|
ccedba0132 | ||
|
|
2dbc5125d6 | ||
|
|
bdf83d447f | ||
|
|
da9445389e | ||
|
|
c0601bb510 | ||
|
|
e20df992ec | ||
|
|
d42200b61f | ||
|
|
4e5f422693 | ||
|
|
2c77e103f9 | ||
|
|
45e9e5f564 | ||
|
|
6b1f9f1560 | ||
|
|
eb50604788 | ||
|
|
5ca140d4f7 | ||
|
|
7943489380 | ||
|
|
82cdd68d00 | ||
|
|
76af311b63 | ||
|
|
b624bff400 | ||
|
|
d5ab822973 | ||
|
|
c8b230fc1c | ||
|
|
d35f7326d7 | ||
|
|
eb07f63d12 | ||
|
|
df42875d41 | ||
|
|
404274003c | ||
|
|
fc9c5170b9 | ||
|
|
dc2f1958ff | ||
|
|
fc9196ad6f | ||
|
|
9cfc03fe6b | ||
|
|
9b8ed2d985 | ||
|
|
728dd2ead3 | ||
|
|
71fbe7d7f2 | ||
|
|
2a4447b6e7 | ||
|
|
aaad005455 | ||
|
|
3bb4a2e36f | ||
|
|
f346a4694c | ||
|
|
51c0883255 | ||
|
|
45e67d5b50 | ||
|
|
6739d29074 | ||
|
|
189858a9d7 | ||
|
|
f1731730fa | ||
|
|
1b37aad4dc | ||
|
|
323018a935 | ||
|
|
7b6e5f2e60 | ||
|
|
5557fc2ef0 | ||
|
|
6c07afe963 | ||
|
|
ac217adaa6 | ||
|
|
5c50658036 | ||
|
|
8ab100dfb3 | ||
|
|
3ac20c695c | ||
|
|
72f1ab0c85 | ||
|
|
2c57117098 | ||
|
|
f6ba5e1219 | ||
|
|
1c53160a2a | ||
|
|
22527c073f | ||
|
|
5b41ecac4c | ||
|
|
14e07e4ca6 | ||
|
|
545864553f | ||
|
|
3b2f10fb91 | ||
|
|
bec7d5945f | ||
|
|
f32bd408a2 | ||
|
|
7ba8c466f4 | ||
|
|
bede18133c | ||
|
|
81e65cc0ab | ||
|
|
5acdbe33c1 | ||
|
|
727999ba72 | ||
|
|
7ad82450b4 | ||
|
|
a72e965785 | ||
|
|
e3fd48728b | ||
|
|
89c3603765 | ||
|
|
03f7034fca | ||
|
|
527ba00287 | ||
|
|
b3831f0b1c | ||
|
|
0549ad19b6 | ||
|
|
7d1095fd96 | ||
|
|
acb1d0b955 | ||
|
|
4fc51e00b5 | ||
|
|
310974b3c3 | ||
|
|
73b30a8ea7 | ||
|
|
790e70a90d | ||
|
|
4114cecd93 | ||
|
|
797f48a9fb | ||
|
|
13d3007293 | ||
|
|
c0cb5a02b3 | ||
|
|
66badd5df5 | ||
|
|
7360426aef | ||
|
|
b71d407396 | ||
|
|
ca7c4964a2 | ||
|
|
5e078db3fd | ||
|
|
eb32b0a80b | ||
|
|
b56f83bf50 | ||
|
|
b55bfac1c3 | ||
|
|
de2dcdcc15 | ||
|
|
12e95d063a | ||
|
|
643ae3bc15 | ||
|
|
73f5f9fbfd | ||
|
|
527fe4f0c1 | ||
|
|
1a9214e328 | ||
|
|
8c0b2363e0 | ||
|
|
6d38b7bbdd | ||
|
|
936e794e2f | ||
|
|
500eecc43d | ||
|
|
2ac73a7812 | ||
|
|
451dacb14a | ||
|
|
e6228c103d | ||
|
|
572d913718 | ||
|
|
c0cd0dd66f | ||
|
|
613e20eb12 | ||
|
|
4bf0506362 | ||
|
|
5997db2b38 | ||
|
|
9f18063fe5 | ||
|
|
b037114863 | ||
|
|
e47521d6e5 | ||
|
|
61357fb40a | ||
|
|
5678d4cf10 | ||
|
|
d403c09b1a | ||
|
|
deff5b25b2 | ||
|
|
31e60deea8 | ||
|
|
847142dc72 | ||
|
|
a5b3ad81a7 | ||
|
|
fe1ac779bf | ||
|
|
064b2fc612 | ||
|
|
5d57586dc1 | ||
|
|
e8d012b82d | ||
|
|
4e90102efd | ||
|
|
02c55aaa0f | ||
|
|
8d4ee29d78 |
No files matched your search
@@ -9,6 +9,34 @@ env:
|
||||
IMAGE: ghcr.io/navikt/designsystemet
|
||||
|
||||
jobs:
|
||||
snyk-monitor:
|
||||
name: monitor dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Run Snyk to check for vulnerabilities
|
||||
continue-on-error: true
|
||||
uses: snyk/actions/node@master
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
with:
|
||||
command: monitor
|
||||
args: --org=designsystemet --severity-threshold=high
|
||||
snyk-test:
|
||||
name: analyze dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Run Snyk to check for vulnerabilities
|
||||
uses: snyk/actions/node@master
|
||||
continue-on-error: true
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
with:
|
||||
command: test
|
||||
args: --org=designsystemet --severity-threshold=high
|
||||
build_and_deploy:
|
||||
name: Build and deploy to dev-gcp
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -17,8 +45,6 @@ jobs:
|
||||
with:
|
||||
node-version: "14"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: "next"
|
||||
- name: add tokens to .env
|
||||
run: |
|
||||
echo "SANITY_WRITE_KEY=${{ secrets.SANITY_FEEDBACK_WRITE_KEY }}" >> aksel.nav.no/website/.env
|
||||
@@ -40,11 +66,10 @@ jobs:
|
||||
- name: Build application
|
||||
run: |
|
||||
yarn boot
|
||||
yarn docgen
|
||||
yarn workspace aksel.nav.no build:next
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@ab80d026d4753220c4243394c07c7d80f9638d06 # Use commit-sha1 instead of tag for security concerns
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # Use commit-sha1 instead of tag for security concerns
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
||||
@@ -10,9 +10,68 @@ env:
|
||||
IMAGE: ghcr.io/navikt/designsystemet
|
||||
|
||||
jobs:
|
||||
snyk-monitor:
|
||||
name: monitor dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Run Snyk to check for vulnerabilities
|
||||
continue-on-error: true
|
||||
uses: snyk/actions/node@master
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
with:
|
||||
command: monitor
|
||||
args: --org=designsystemet --severity-threshold=high
|
||||
snyk-test:
|
||||
name: analyze dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Run Snyk to check for vulnerabilities
|
||||
uses: snyk/actions/node@master
|
||||
continue-on-error: true
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
with:
|
||||
command: test
|
||||
args: --org=designsystemet --severity-threshold=high
|
||||
sync_data_with_sanity:
|
||||
name: Update component data
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "14"
|
||||
- uses: actions/checkout@v2
|
||||
- name: add tokens to .env
|
||||
run: |
|
||||
echo "SANITY_WRITE_KEY=${{ secrets.SANITY_FEEDBACK_WRITE_KEY }}" >> aksel.nav.no/website/.env
|
||||
|
||||
- name: Restore cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-prod-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-prod-
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
- name: Run docgen
|
||||
run: |
|
||||
yarn boot
|
||||
yarn docgen
|
||||
|
||||
- name: Update sanity sync
|
||||
run: yarn workspace aksel.nav.no sanity:update
|
||||
|
||||
build_and_deploy:
|
||||
name: Build and deploy to prod-gcp
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
@@ -36,25 +95,17 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
- name: build packages
|
||||
run: |
|
||||
yarn boot
|
||||
yarn docgen
|
||||
- name: Build packages
|
||||
run: yarn boot
|
||||
|
||||
- name: Tests
|
||||
run: yarn workspace aksel.nav.no test
|
||||
|
||||
- name: E2E
|
||||
run: NEXT_PUBLIC_TEST=true yarn workspace website e2e
|
||||
|
||||
- name: Update sanity sync
|
||||
run: yarn workspace aksel.nav.no sanity:update
|
||||
|
||||
- name: Build application
|
||||
run: yarn workspace aksel.nav.no build:next
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@ab80d026d4753220c4243394c07c7d80f9638d06 # Use commit-sha1 instead of tag for security concerns
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # Use commit-sha1 instead of tag for security concerns
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -65,6 +116,13 @@ jobs:
|
||||
run: echo "DOCKER_TAG=${{ env.IMAGE }}:${{ env.TAG }}" >> $GITHUB_ENV
|
||||
- name: Build docker image
|
||||
run: docker build -t ${{ env.DOCKER_TAG }} . -f aksel.nav.no/Dockerfile
|
||||
- name: Wait for e2e-tests to succeed
|
||||
uses: lewagon/wait-on-check-action@v1.2.0
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
check-name: "Smoketest Aksel"
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
wait-interval: 10
|
||||
- name: Push docker image
|
||||
run: |
|
||||
docker push ${{ env.DOCKER_TAG }}
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
node-version: "14"
|
||||
- uses: actions/checkout@v2
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@ab80d026d4753220c4243394c07c7d80f9638d06 # Use commit-sha1 instead of tag for security concerns
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # Use commit-sha1 instead of tag for security concerns
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
||||
@@ -12,6 +12,8 @@ on:
|
||||
jobs:
|
||||
playwright:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mcr.microsoft.com/playwright:v1.30.0-focal
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
@@ -36,15 +38,15 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
- name: build packages
|
||||
- name: Build packages
|
||||
run: |
|
||||
yarn boot
|
||||
yarn docgen
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install --with-deps
|
||||
- name: Build application
|
||||
run: yarn workspace aksel.nav.no build:next
|
||||
|
||||
- name: Run Playwright tests
|
||||
run: yarn workspace website e2e:full
|
||||
run: yarn workspace website e2e:ci-full
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
name: Smoketest aksel.nav.no
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- "aksel.nav.no/**"
|
||||
|
||||
env:
|
||||
IMAGE: ghcr.io/navikt/designsystemet
|
||||
|
||||
jobs:
|
||||
smoketest:
|
||||
name: Smoketest Aksel
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mcr.microsoft.com/playwright:v1.30.0-focal
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "14"
|
||||
- uses: actions/checkout@v2
|
||||
- name: add tokens to .env
|
||||
run: |
|
||||
echo "SANITY_WRITE_KEY=${{ secrets.SANITY_FEEDBACK_WRITE_KEY }}" >> aksel.nav.no/website/.env
|
||||
echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> aksel.nav.no/website/.env
|
||||
echo "SANITY_PREVIEW_TOKEN=${{ secrets.SANITY_PREVIEW_TOKEN }}" >> aksel.nav.no/website/.env
|
||||
echo "SANITY_PRIVATE_NO_DRAFTS=${{ secrets.SANITY_PRIVATE_NO_DRAFTS }}" >> aksel.nav.no/website/.env
|
||||
|
||||
- name: Restore cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-prod-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-prod-
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
- name: build packages
|
||||
run: |
|
||||
yarn boot
|
||||
|
||||
- name: Build application
|
||||
run: yarn workspace aksel.nav.no build:next
|
||||
|
||||
- name: E2E smoketest
|
||||
run: yarn workspace website e2e:ci
|
||||
@@ -39,8 +39,7 @@
|
||||
|
||||
aksel.nav.no/
|
||||
├── website # NEXT.JS app (v12)
|
||||
├── website/sanity # Sanity CMS-app (v3)
|
||||
└── sanity # Sanity CMS-app (deprecated v2)
|
||||
└── website/sanity # Sanity CMS-app (v3)
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:16.4-alpine3.14
|
||||
FROM node:16.13.1-alpine3.14
|
||||
RUN apk add --no-cache libc6-compat
|
||||
|
||||
ENV NODE_ENV production
|
||||
@@ -8,7 +8,6 @@ COPY aksel.nav.no/website/package.json .
|
||||
COPY aksel.nav.no/website/.next/ .next/
|
||||
COPY aksel.nav.no/website/public/ public
|
||||
COPY aksel.nav.no/website/.env .
|
||||
COPY aksel.nav.no/website/redirects.json .
|
||||
COPY aksel.nav.no/website/next.config.js .
|
||||
COPY node_modules/ node_modules/
|
||||
COPY @navikt/ @navikt/
|
||||
|
||||
@@ -19,7 +19,7 @@ Det publiserte studioet finner man på [aksel.nav.no/admin](https://aksel.nav.no
|
||||
|
||||
### Bidrag
|
||||
|
||||
Branch `master` blir pusher rett til prod -> aksel.nav.no. For å utvikle nye features brukes branch `next` som ved push publiseres til devmiljø aksel.dev.nav.no (krever naisdevice).
|
||||
Branch `master` blir pusher rett til prod -> aksel.nav.no. For å utvikle nye features brukes branch `next` som ved push publiseres til devmiljø aksel.dev.nav.no (krever naisdevice). Kan også publisere andre branches til dev ved bruk av workflow-dispatch.
|
||||
|
||||
### Nettside (localhost:3000)
|
||||
|
||||
|
||||
@@ -12,24 +12,11 @@ spec:
|
||||
- "https://aksel.dev.nav.no"
|
||||
liveness:
|
||||
path: /api/isAlive
|
||||
initialDelay: 20
|
||||
timeout: 1
|
||||
periodSeconds: 5
|
||||
failureThreshold: 10
|
||||
readiness:
|
||||
path: /api/isAlive
|
||||
initialDelay: 20
|
||||
timeout: 1
|
||||
replicas:
|
||||
min: 1
|
||||
max: 1
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
accessPolicy:
|
||||
outbound:
|
||||
external:
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
.yarn/cache
|
||||
*.tar.gz
|
||||
@@ -1,46 +0,0 @@
|
||||
// https://www.sanity.io/schemas/make-a-field-read-only-after-publishing-once-d87bf5f6
|
||||
import { useState, useEffect } from "react";
|
||||
import { useDocumentOperation, useValidationStatus } from "@sanity/react-hooks";
|
||||
import PublishIcon from "part:@sanity/base/publish-icon";
|
||||
|
||||
export default function SetAndPublishAction(props) {
|
||||
const { patch, publish }: any = useDocumentOperation(props.id, props.type);
|
||||
const { isValidating, markers }: any = useValidationStatus(
|
||||
props.id,
|
||||
props.type
|
||||
);
|
||||
const [isPublishing, setIsPublishing] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// if the isPublishing state was set to true and the draft has changed
|
||||
// to become `null` the document has been published
|
||||
if (isPublishing && !props.draft) {
|
||||
setIsPublishing(false);
|
||||
}
|
||||
}, [props.draft]);
|
||||
|
||||
return {
|
||||
disabled:
|
||||
publish.disabled ||
|
||||
isValidating ||
|
||||
markers.some((x) => x?.level === "error"),
|
||||
label: isPublishing ? "Publishing…" : "Publish",
|
||||
color: "success",
|
||||
icon: PublishIcon,
|
||||
|
||||
onHandle: () => {
|
||||
// This will update the button text
|
||||
setIsPublishing(true);
|
||||
|
||||
// Set publishedAt to current date and time
|
||||
!props.published &&
|
||||
patch.execute([{ set: { publishedAt: new Date().toISOString() } }]);
|
||||
|
||||
// Perform the publish
|
||||
publish.execute();
|
||||
|
||||
// Signal that the action is completed
|
||||
props.onComplete();
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
import { EyeScreened } from "@navikt/ds-icons";
|
||||
import { BodyLong, Button } from "@navikt/ds-react";
|
||||
import React from "react";
|
||||
const sanityClient = require("@sanity/client");
|
||||
const SanityConfig = require("../../sanity.json");
|
||||
|
||||
const client = sanityClient({
|
||||
projectId: SanityConfig.api.projectId,
|
||||
dataset: SanityConfig.api.dataset,
|
||||
apiVersion: "2021-08-21",
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
export default function SetPrivateAction(props) {
|
||||
const [isDialogOpen, setDialogOpen] = React.useState(false);
|
||||
|
||||
const isPrivate =
|
||||
props?.published?.tilgang?.privat ?? props?.draft?.tilgang?.privat;
|
||||
|
||||
const handlePatch = async (dir: boolean) => {
|
||||
props?.published &&
|
||||
(await client
|
||||
.patch(props.id)
|
||||
.set({ tilgang: { privat: dir } })
|
||||
.commit()
|
||||
.catch((err) => {
|
||||
console.error(err.message);
|
||||
}));
|
||||
props?.draft &&
|
||||
(await client
|
||||
.patch(props.draft._id)
|
||||
.set({ tilgang: { privat: dir } })
|
||||
.commit()
|
||||
.catch((err) => {
|
||||
console.error(err.message);
|
||||
}));
|
||||
props.onComplete();
|
||||
};
|
||||
|
||||
return {
|
||||
label: isPrivate ? "Åpne side for alle" : "Skjul side bak innlogging",
|
||||
/* color: "success",
|
||||
icon: PublishIcon, */
|
||||
icon: EyeScreened,
|
||||
|
||||
onHandle: async () => {
|
||||
setDialogOpen(true);
|
||||
},
|
||||
dialog: isDialogOpen && {
|
||||
type: "modal",
|
||||
onClose: props.onComplete,
|
||||
header: isPrivate
|
||||
? "Åpne innhold for alle"
|
||||
: "Gjemme innhold bak innlogging",
|
||||
content: (
|
||||
<div>
|
||||
{isPrivate ? (
|
||||
<BodyLong spacing>
|
||||
Innholdet gjøres nå tilgjengelig for alle utenfor NAV! Dette kan
|
||||
medføre konsekvenser siden innholdet i artikkelen blir
|
||||
tilgjengelig for alle. Innhold som NAV potensielt ikke ønsker å
|
||||
dele offentlig kan medføre eks omdømmetap og uønsket oppmerksomhet
|
||||
utenfra. Dobbelsjekk med temaansvarlig og andre som har skrevet
|
||||
artikkelen før du velger å åpne innholdet for alle. Er du usikker
|
||||
er det bare å sende en melding på #Aksel-designsystemet eller
|
||||
#aksel-redaktører på Slack.
|
||||
</BodyLong>
|
||||
) : (
|
||||
<>
|
||||
<BodyLong spacing>
|
||||
Innholdet gjøres nå bare tilgjengelig for NAV-ansatte. Alt
|
||||
utenom "innhold" vil fortsatt være tilgjengelig for alle. Dette
|
||||
inkluderer alle bilder som er lastet opp til sanity også! Husk
|
||||
at ingen "sikker" data skal skrives i Aksel, og at
|
||||
innloggings-barrieren er ment for å kunne dele innhold som vi
|
||||
ikke er helt trygg på å dele med alle.
|
||||
</BodyLong>
|
||||
Dette vil fortsatt være åpent for alle
|
||||
<ul>
|
||||
<li>Sidetittel</li>
|
||||
<li>Ingress</li>
|
||||
<li>Redaktører</li>
|
||||
<li>Bilder/filer</li>
|
||||
<li>SEO</li>
|
||||
</ul>
|
||||
Dette vil bare være tilgjengelig for NAV-ansatte
|
||||
<ul>
|
||||
<li>"Innhold"-blokken</li>
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
<div style={{ display: "flex", gap: "6px", marginTop: 8 }}>
|
||||
{isPrivate ? (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setDialogOpen(false);
|
||||
handlePatch(false);
|
||||
}}
|
||||
>
|
||||
Åpne innholdet for alle
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
setDialogOpen(false);
|
||||
props.onComplete();
|
||||
}}
|
||||
>
|
||||
Avbryt
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setDialogOpen(false);
|
||||
handlePatch(true);
|
||||
}}
|
||||
>
|
||||
Skjul innholdet bak innlogging
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
setDialogOpen(false);
|
||||
props.onComplete();
|
||||
}}
|
||||
>
|
||||
Avbryt
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import MediaAssetSource from "part:sanity-plugin-media/asset-source";
|
||||
import Unsplash from "part:sanity-plugin-asset-source-unsplash/image-asset-source";
|
||||
export default [MediaAssetSource, Unsplash];
|
||||
@@ -1,53 +0,0 @@
|
||||
import { Send } from "@navikt/ds-icons";
|
||||
import { BodyLong, Button, Heading, Modal } from "@navikt/ds-react";
|
||||
import React, { useRef, useState } from "react";
|
||||
|
||||
const BundleChecker = () => {
|
||||
const [inc, setInc] = useState(0);
|
||||
const interval = useRef(null);
|
||||
|
||||
const start = () => {
|
||||
interval.current = setInterval(() => {
|
||||
setInc((x) => x + 0.4);
|
||||
}, 10);
|
||||
};
|
||||
if (inc > 99) {
|
||||
clearInterval(interval.current);
|
||||
window.location.replace("https://aksel.nav.no/admin");
|
||||
}
|
||||
|
||||
document.body.style.opacity = `${100 - inc}%`;
|
||||
document.body.style.scale = `${1 - inc / 150}`;
|
||||
document.body.style.rotate = `${inc ** 1.3}deg`;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
aria-labelledby="modal-heading"
|
||||
closeButton={false}
|
||||
open
|
||||
onClose={() => null}
|
||||
>
|
||||
<Modal.Content style={{ minWidth: "20rem", maxWidth: "40rem" }}>
|
||||
<Heading spacing id="modal-heading" size="medium" level="1">
|
||||
Studioet er flyttet!
|
||||
</Heading>
|
||||
|
||||
<BodyLong spacing>
|
||||
Vi har oppdatert studioet og flyttet det til ny url:
|
||||
aksel.nav.no/admin. Hvis noe ikke fungerer, ta kontakt på slack
|
||||
#aksel-redaksjonen! Husk å logge inn med samme login-provider. For de
|
||||
fleste vil dette være NAV SSO.
|
||||
</BodyLong>
|
||||
<Button
|
||||
onClick={() => start()}
|
||||
icon={<Send aria-hidden />}
|
||||
iconPosition="right"
|
||||
>
|
||||
Gå til nytt studio
|
||||
</Button>
|
||||
</Modal.Content>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default BundleChecker;
|
||||
@@ -1,44 +0,0 @@
|
||||
import { allDocumentTypes } from "../config";
|
||||
|
||||
export default {
|
||||
widgets: [
|
||||
{
|
||||
name: "document-list",
|
||||
options: {
|
||||
title: "Drafts for God Praksis",
|
||||
query: '*[_type in $types && (_id in path("drafts.**"))]',
|
||||
queryParams: {
|
||||
types: allDocumentTypes.filter((x) => x.startsWith("gp")),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "document-list",
|
||||
options: {
|
||||
title: "Drafts for Designsystemet",
|
||||
query: '*[_type in $types && (_id in path("drafts.**"))]',
|
||||
queryParams: {
|
||||
types: allDocumentTypes.filter((x) => x.startsWith("ds")),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "outdated-documents-widget",
|
||||
options: {
|
||||
type: "warning",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "outdated-documents-widget",
|
||||
options: {
|
||||
type: "error",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "project-info",
|
||||
},
|
||||
{
|
||||
name: "project-users",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Picture } from "@navikt/ds-icons";
|
||||
import S from "@sanity/desk-tool/structure-builder";
|
||||
|
||||
import React from "react";
|
||||
|
||||
export const adminPanel = async (roles) =>
|
||||
roles.find((x) => x.name === "administrator") &&
|
||||
S.listItem()
|
||||
.title("Admin")
|
||||
.child(
|
||||
S.list()
|
||||
.title("Admin")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Standalone-sider")
|
||||
.child(S.documentTypeList("aksel_standalone")),
|
||||
S.listItem().title("Redirects").child(S.documentTypeList("redirect")),
|
||||
])
|
||||
);
|
||||
@@ -1,104 +0,0 @@
|
||||
import { prinsipper } from "@/lib";
|
||||
import { Facilitet } from "@navikt/ds-icons";
|
||||
import S from "@sanity/desk-tool/structure-builder";
|
||||
import documentStore from "part:@sanity/base/datastore/document";
|
||||
import React from "react";
|
||||
import { map } from "rxjs/operators";
|
||||
|
||||
const temaQuery = `*[_type == "aksel_tema" && count(*[references(^._id)]) > 0]`;
|
||||
|
||||
const AkselLogo = () => (
|
||||
<svg
|
||||
width="192px"
|
||||
height="192px"
|
||||
viewBox="0 0 192 192"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
focusable="false"
|
||||
aria-hidden="true"
|
||||
strokeLinecap="round"
|
||||
strokeWidth="10"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path d="m41.63 150.3 47.39-47.38" />
|
||||
<path d="M40.92 80.3 77.7 43.53c4.25-4.24 9.9-4.24 14.15 0l56.56 56.57c4.25 4.25 4.25 9.9 0 14.14l-36.77 36.77" />
|
||||
<path d="m40.92 80.3 38.19-38.18c3.53-3.54 6.72-3.18 13.79-3.18h48.79s0 0 0 0c6.36 0 11.31 4.95 11.31 11.31 0 0 0 0 0 0v48.8c0 7.06.35 10.24-3.18 13.78l-38.19 38.18" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const akselInnhold = async () => {
|
||||
return S.listItem()
|
||||
.title("Aksel")
|
||||
.icon(() => <AkselLogo />)
|
||||
.child(
|
||||
S.list()
|
||||
.title("Innhold")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Artikler")
|
||||
.child(() =>
|
||||
documentStore.listenQuery(temaQuery).pipe(
|
||||
map((tema: any) => {
|
||||
return S.list()
|
||||
.title("Artikler")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Alle artikler")
|
||||
.child(S.documentTypeList("aksel_artikkel")),
|
||||
S.listItem()
|
||||
.title("Uten tema")
|
||||
.child(
|
||||
S.documentTypeList("aksel_artikkel").filter(
|
||||
`_type == "aksel_artikkel" && !defined(tema)`
|
||||
)
|
||||
),
|
||||
...tema.map((tag) => {
|
||||
return S.listItem()
|
||||
.title(tag.title)
|
||||
.child(
|
||||
S.documentList()
|
||||
.title(tag.title)
|
||||
.filter(
|
||||
`_type == 'aksel_artikkel' && $tag in tema[]->title`
|
||||
)
|
||||
.params({ tag: tag.title })
|
||||
);
|
||||
}),
|
||||
]);
|
||||
})
|
||||
)
|
||||
),
|
||||
S.listItem()
|
||||
.title("Produktbloggen")
|
||||
.child(S.documentTypeList("aksel_blogg")),
|
||||
S.listItem()
|
||||
.title("Prinsipper")
|
||||
.child(
|
||||
S.list()
|
||||
.title("Prinsipper")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Alle artikler")
|
||||
.child(S.documentTypeList("aksel_prinsipp")),
|
||||
...prinsipper.map(({ value, title }) =>
|
||||
S.listItem()
|
||||
.title(title)
|
||||
.child(
|
||||
S.documentList()
|
||||
.title(title)
|
||||
.filter(
|
||||
`_type == 'aksel_prinsipp' && $value == prinsipp.prinsippvalg`
|
||||
)
|
||||
.params({ value })
|
||||
)
|
||||
),
|
||||
])
|
||||
),
|
||||
S.divider(),
|
||||
S.listItem()
|
||||
.title("Temasider")
|
||||
.icon(() => <Facilitet />)
|
||||
.child(S.documentTypeList("aksel_tema")),
|
||||
])
|
||||
);
|
||||
};
|
||||
@@ -1,92 +0,0 @@
|
||||
import { CoApplicant, Facilitet, Information, People } from "@navikt/ds-icons";
|
||||
import S from "@sanity/desk-tool/structure-builder";
|
||||
import userStore from "part:@sanity/base/user";
|
||||
import React from "react";
|
||||
import { createSuperPane } from "sanity-super-pane";
|
||||
import { ComponentPageWebPreview } from "../../web-previews/ComponentWebPreview";
|
||||
import { KomponentPreview } from "../../web-previews/KomponentPreview";
|
||||
import { PageWebPreview } from "../../web-previews/PageWebPreview";
|
||||
import { adminPanel } from "./admin";
|
||||
import { akselInnhold } from "./aksel";
|
||||
import { dsPanel } from "./ds";
|
||||
import { profilePanel } from "./profile";
|
||||
|
||||
export const getDefaultDocumentNode = ({ schemaType }) => {
|
||||
switch (schemaType) {
|
||||
case "komponent_artikkel":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(ComponentPageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "ds_artikkel":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "aksel_artikkel":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "aksel_blogg":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "aksel_prinsipp":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "aksel_standalone":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
const items = [
|
||||
S.divider(),
|
||||
S.listItem()
|
||||
.title("Redaktører")
|
||||
.icon(() => <People />)
|
||||
.child(createSuperPane("editor")),
|
||||
|
||||
S.divider(),
|
||||
];
|
||||
|
||||
export default () => {
|
||||
return userStore.getCurrentUser().then(async ({ roles, id }) => {
|
||||
const panels = [];
|
||||
const admin = await adminPanel(roles);
|
||||
|
||||
const profile = await profilePanel(id);
|
||||
const ds = await dsPanel(roles);
|
||||
const aksel = await akselInnhold();
|
||||
const intro = [];
|
||||
|
||||
profile && intro.push(profile);
|
||||
profile && intro.push(S.divider());
|
||||
|
||||
let struct = items;
|
||||
|
||||
if (ds) {
|
||||
struct = [ds, ...struct];
|
||||
}
|
||||
struct = [aksel, ...struct];
|
||||
if (admin) {
|
||||
struct = [...struct, admin];
|
||||
}
|
||||
|
||||
return S.list()
|
||||
.title("Aksel")
|
||||
.items([...intro, ...struct, ...panels]);
|
||||
});
|
||||
};
|
||||
@@ -1,115 +0,0 @@
|
||||
import {
|
||||
Facilitet,
|
||||
FileContent,
|
||||
Findout,
|
||||
Folder,
|
||||
Picture,
|
||||
Place,
|
||||
Ruler,
|
||||
Task,
|
||||
} from "@navikt/ds-icons";
|
||||
import S from "@sanity/desk-tool/structure-builder";
|
||||
import client from "part:@sanity/base/client";
|
||||
import React from "react";
|
||||
import { createSuperPane } from "sanity-super-pane";
|
||||
|
||||
export const dsPanel = async (roles) => {
|
||||
const role = roles.some(({ name }) => "aksel-editor" === name);
|
||||
|
||||
if (role) {
|
||||
return null;
|
||||
} else {
|
||||
return S.listItem()
|
||||
.title("Designsystemet")
|
||||
.icon(() => <Facilitet />)
|
||||
.child(
|
||||
S.list()
|
||||
.title("Designsystem")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Komponentsider")
|
||||
.icon(() => <Facilitet />)
|
||||
.child(createSuperPane("komponent_artikkel")),
|
||||
S.listItem()
|
||||
.title("Artikler")
|
||||
.icon(() => <FileContent />)
|
||||
.child(createSuperPane("ds_artikkel")),
|
||||
S.divider(),
|
||||
S.documentListItem()
|
||||
.title(`Navigasjon`)
|
||||
.schemaType(`ds_navigation`)
|
||||
.icon(() => <Place />)
|
||||
.id(`ds_navigationid`),
|
||||
|
||||
S.listItem()
|
||||
.title("Publiserte sider ikke i navigasjon")
|
||||
.child(async (): Promise<any> => {
|
||||
const doc = await client.fetch(
|
||||
`*[_id == 'ds_navigationid'][0]{
|
||||
headings[]{
|
||||
title,
|
||||
menu
|
||||
}
|
||||
}`
|
||||
);
|
||||
if (!doc.headings) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let allIds = "";
|
||||
try {
|
||||
allIds = doc.headings
|
||||
.map((heading) =>
|
||||
heading.menu
|
||||
.filter((item) => item._type === "item")
|
||||
.map((item) => item.link._ref)
|
||||
.map((x) => `"${x}"`)
|
||||
.join(",")
|
||||
)
|
||||
.join(",");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
return S.documentList()
|
||||
.title("Sider ikke i navigasjon")
|
||||
.filter(
|
||||
`!(_id in [${allIds}]) && !(_id in path('drafts.**')) && _type in ["komponent_artikkel", "ds_artikkel"]`
|
||||
);
|
||||
}),
|
||||
S.documentListItem()
|
||||
.title(`Forside`)
|
||||
.schemaType(`ds_frontpage`)
|
||||
.icon(() => <Picture />)
|
||||
.id(`frontpage_designsystem`),
|
||||
S.divider(),
|
||||
S.listItem()
|
||||
.title("Autogenerert data")
|
||||
.child(
|
||||
S.list()
|
||||
.title("Autogenerert data")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Eksempler")
|
||||
.icon(() => <span>{`EX`}</span>)
|
||||
.child(S.documentTypeList("kode_eksempler_fil")),
|
||||
S.listItem()
|
||||
.title("Props")
|
||||
.icon(() => <Folder />)
|
||||
.child(S.documentTypeList("ds_props")),
|
||||
S.listItem()
|
||||
.title("Token-kategorier")
|
||||
.icon(() => <Folder />)
|
||||
.child(S.documentTypeList("token_kategori")),
|
||||
])
|
||||
),
|
||||
S.divider(),
|
||||
S.documentListItem()
|
||||
.title(`Komponent-template`)
|
||||
.schemaType(`ds_component_template`)
|
||||
.icon(() => <Task />)
|
||||
.id(`ds_component_templateid`),
|
||||
])
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Picture } from "@navikt/ds-icons";
|
||||
import S from "@sanity/desk-tool/structure-builder";
|
||||
import userStore from "part:@sanity/base/user";
|
||||
import client from "part:@sanity/base/client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
export const profilePanel = async (id) => {
|
||||
const ids = await client.withConfig({ apiVersion: "2021-05-31" })
|
||||
.fetch(`*[_type == "editor"]{
|
||||
_id,
|
||||
user_id
|
||||
}`);
|
||||
|
||||
const editor = ids.find(({ user_id }) => user_id?.current === id);
|
||||
|
||||
if (editor) {
|
||||
return S.documentListItem()
|
||||
.title(`Profil`)
|
||||
.schemaType(`editor`)
|
||||
.icon(() => <Picture />)
|
||||
.id(editor._id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -1,53 +0,0 @@
|
||||
import React from "react";
|
||||
import { People } from "@navikt/ds-icons";
|
||||
import T from "@sanity/base/initial-value-template-builder";
|
||||
import userStore from "part:@sanity/base/user";
|
||||
|
||||
const sanityClient = require("@sanity/client");
|
||||
const sanityToken = process.env.SANITY_TOKEN;
|
||||
const SanityConfig = require("../sanity.json");
|
||||
|
||||
const client = sanityClient({
|
||||
projectId: SanityConfig.api.projectId,
|
||||
dataset: SanityConfig.api.dataset,
|
||||
apiVersion: "2020-06-19",
|
||||
/* Token er safe og har bare tillatelse til å lese template doc */
|
||||
token:
|
||||
"skt6kqEcXmRxUTGDzdEcw11g7HJi9DaHX2fyn8Z0Dearr1k67ykW2N64KTP9GxAPNN6P8TlzPjUdkfGsvbJkfmwfq0UNudKfMYOfyz9OeA666y15pPLRr6D7xnrJGEEBYwSvG6baLLiJI478YowWpjqp1Mz2U1PbAPnIMW4W5btTpdQbwPSD",
|
||||
useCdn: false,
|
||||
});
|
||||
|
||||
export default [
|
||||
...T.defaults().filter((x) => !["komponent_artikkel"].includes(x.spec.id)),
|
||||
|
||||
T.template({
|
||||
id: "komponent_artikkel_template",
|
||||
title: "Mal for Komponentsider",
|
||||
schemaType: "komponent_artikkel",
|
||||
value: async () => {
|
||||
const doc = await client.fetch(`*[_type == "ds_component_template"][0]`);
|
||||
return doc
|
||||
? Object.entries(doc).reduce((old, [key, val]) => {
|
||||
return key.startsWith("_") ? { ...old } : { ...old, [key]: val };
|
||||
}, {})
|
||||
: {};
|
||||
},
|
||||
}),
|
||||
T.template({
|
||||
id: "newEditor",
|
||||
title: "Editor",
|
||||
schemaType: "editor",
|
||||
icon: () => <People />,
|
||||
value: async () => {
|
||||
const { id, displayName } = await userStore.getUser("me");
|
||||
|
||||
return {
|
||||
title: displayName,
|
||||
user_id: {
|
||||
current: id,
|
||||
},
|
||||
_type: "editor",
|
||||
};
|
||||
},
|
||||
}),
|
||||
];
|
||||
@@ -1,38 +0,0 @@
|
||||
import S from "@sanity/base/structure-builder";
|
||||
|
||||
const docTypes = [
|
||||
{
|
||||
name: "aksel_artikkel",
|
||||
title: "Aksel Artikkel",
|
||||
},
|
||||
{
|
||||
name: "newEditor",
|
||||
title: "Bruker/redaktør",
|
||||
desc: "Lager en psuedo-bruker for deg som kan koble artikler til brukeren",
|
||||
},
|
||||
{
|
||||
name: "aksel_blogg",
|
||||
title: "Bloggpost",
|
||||
},
|
||||
{
|
||||
name: "ds_artikkel",
|
||||
title: "Designsystem Artikkel",
|
||||
desc: "Atikkel som legges under designsystemet",
|
||||
},
|
||||
{
|
||||
name: "komponent_artikkel_template",
|
||||
title: "Designsystem Komponentside",
|
||||
desc: "Atikkel som legges under designsystemet",
|
||||
},
|
||||
];
|
||||
|
||||
export default [
|
||||
...docTypes.map((doct) =>
|
||||
S.initialValueTemplateItem(doct.name)
|
||||
.id(`doc-${doct.name}`)
|
||||
.title(doct.title)
|
||||
.templateId(doct.name)
|
||||
.description(doct?.desc ?? "")
|
||||
),
|
||||
/* ...S.defaultInitialValueTemplateItems() */
|
||||
];
|
||||
@@ -1,15 +0,0 @@
|
||||
import defaultResolve, {
|
||||
PublishAction,
|
||||
} from "part:@sanity/base/document-actions";
|
||||
import SetAndPublishAction from "./actions/publishedAt";
|
||||
/* import SetPrivateAction from "./actions/set-private"; */
|
||||
import { allDocumentTypes } from "../config";
|
||||
|
||||
export default function resolveDocumentActions(props) {
|
||||
const [publish, ...rest] = defaultResolve(props).map((Action) => {
|
||||
return allDocumentTypes.includes(props.type) && Action === PublishAction
|
||||
? SetAndPublishAction
|
||||
: Action;
|
||||
});
|
||||
return [publish /* SetPrivateAction */, ...rest];
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import { Button, Card, Inline, Stack, Text } from "@sanity/ui";
|
||||
import moment from "moment";
|
||||
import PatchEvent, { set } from "part:@sanity/form-builder/patch-event";
|
||||
import React from "react";
|
||||
|
||||
const CustomDisplay = React.forwardRef((props, ref) => {
|
||||
const click = () => {
|
||||
props.onChange &&
|
||||
props.onChange(
|
||||
PatchEvent.from(set(new Date().toISOString().split("T")[0]))
|
||||
);
|
||||
};
|
||||
|
||||
const lastUpdate = moment(props.value);
|
||||
const daysSince = moment().diff(lastUpdate, "days");
|
||||
|
||||
return (
|
||||
<Stack tabIndex={0} space={4} ref={ref}>
|
||||
{daysSince > 90 && (
|
||||
<Card
|
||||
padding={[3, 3, 4]}
|
||||
radius={2}
|
||||
shadow={1}
|
||||
tone={daysSince > 180 ? "critical" : "caution"}
|
||||
>
|
||||
<Text align="center" size={[2, 2, 3]}>
|
||||
{daysSince > 180
|
||||
? "Innholdet er utdatert!"
|
||||
: "Innholdet er stagnert!"}
|
||||
</Text>
|
||||
</Card>
|
||||
)}
|
||||
<Stack space={4}>
|
||||
<Text size={1} weight="semibold">
|
||||
Sist oppdatert
|
||||
</Text>
|
||||
<Text size={2}>{props.value?.split("-").reverse().join("/")}</Text>
|
||||
</Stack>
|
||||
|
||||
<Inline space={[3, 3, 4]}>
|
||||
<Button
|
||||
onClick={() => click()}
|
||||
fontSize={[2]}
|
||||
mode="ghost"
|
||||
padding={[2, 2]}
|
||||
text="Oppdater"
|
||||
/>
|
||||
</Inline>
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
|
||||
export default CustomDisplay;
|
||||
@@ -1,30 +0,0 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { withDocument } from "part:@sanity/form-builder";
|
||||
import {
|
||||
TextInput,
|
||||
Stack,
|
||||
Label,
|
||||
Checkbox,
|
||||
Radio,
|
||||
Flex,
|
||||
Text,
|
||||
Box,
|
||||
Card,
|
||||
} from "@sanity/ui";
|
||||
import styled from "styled-components";
|
||||
/* TODO: Implement this. Issue now is that document returns null in props */
|
||||
const CustomDisplay = React.forwardRef((props, ref) => {
|
||||
const [doc, setDoc] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
doc && setDoc(props.document);
|
||||
}, [props]);
|
||||
|
||||
return (
|
||||
<Stack space={0} ref={ref}>
|
||||
<Card padding={0}>T</Card>
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
|
||||
export default withDocument(CustomDisplay);
|
||||
@@ -1,49 +0,0 @@
|
||||
import React from "react";
|
||||
import Preview from "part:@sanity/base/preview";
|
||||
import { IntentLink } from "part:@sanity/base/router";
|
||||
import schema from "part:@sanity/base/schema";
|
||||
import {
|
||||
Item as DefaultItem,
|
||||
List as DefaultList,
|
||||
} from "part:@sanity/components/lists/default";
|
||||
import styles from "./profile.css";
|
||||
|
||||
const ReferringDocumentsList = (props) => {
|
||||
const { documents } = props;
|
||||
return (
|
||||
<DefaultList className={styles.root}>
|
||||
{documents
|
||||
.sort(
|
||||
(a, b) =>
|
||||
new Date(b._updatedAt).getTime() - new Date(a._updatedAt).getTime()
|
||||
)
|
||||
.map((document) => {
|
||||
const schemaType = schema.get(document._type);
|
||||
return (
|
||||
<DefaultItem key={document._id} className={styles.item}>
|
||||
{schemaType ? (
|
||||
<IntentLink
|
||||
className={styles.link}
|
||||
intent="edit"
|
||||
params={{ id: document._id, type: document._type }}
|
||||
>
|
||||
<Preview value={document} type={schemaType} />
|
||||
{document._updatedAt
|
||||
.split("T")[0]
|
||||
.split("-")
|
||||
.reverse()
|
||||
.join("-")}
|
||||
</IntentLink>
|
||||
) : (
|
||||
<div>
|
||||
A document of the unknown type <em>{document._type}</em>
|
||||
</div>
|
||||
)}
|
||||
</DefaultItem>
|
||||
);
|
||||
})}
|
||||
</DefaultList>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReferringDocumentsList;
|
||||
@@ -1,18 +0,0 @@
|
||||
export const getUnpublished = (docs: Record<string, any>[]) =>
|
||||
docs.filter(
|
||||
(doc, i, arr) =>
|
||||
doc._id.startsWith("drafts.") &&
|
||||
!arr.find((x, y) => i !== y && doc._id.includes(x._id))
|
||||
);
|
||||
|
||||
export const getDrafts = (docs: Record<string, any>[]) =>
|
||||
docs.filter((doc, i, arr) =>
|
||||
arr.find((x, y) => i !== y && x._id.includes(doc._id))
|
||||
);
|
||||
|
||||
export const getPublished = (docs: Record<string, any>[]) =>
|
||||
docs
|
||||
.filter(
|
||||
(doc, i, arr) => !arr.find((x, y) => i !== y && x._id.includes(doc._id))
|
||||
)
|
||||
.filter((doc) => !doc._id.includes("drafts"));
|
||||
@@ -1,147 +0,0 @@
|
||||
import { Caseworker, Sandglass, Upload, Wrench } from "@navikt/ds-icons";
|
||||
import {
|
||||
BodyShort,
|
||||
Detail,
|
||||
Heading,
|
||||
HelpText,
|
||||
Label,
|
||||
Link,
|
||||
ReadMore,
|
||||
} from "@navikt/ds-react";
|
||||
import { SanityDocument } from "@sanity/client";
|
||||
import { Stack } from "@sanity/ui";
|
||||
import userStore from "part:@sanity/base/user";
|
||||
import { WithReferringDocuments } from "part:@sanity/base/with-referring-documents";
|
||||
import Spinner from "part:@sanity/components/loading/spinner";
|
||||
import { withDocument } from "part:@sanity/form-builder";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import ReferringDocumentsList from "./document-list";
|
||||
import styles from "../styles.css";
|
||||
import { getDrafts, getPublished, getUnpublished } from "./filter-docs";
|
||||
|
||||
type Props = {
|
||||
referringDocuments: Record<string, any>[];
|
||||
isLoading: boolean;
|
||||
published?: SanityDocument | null;
|
||||
type: any;
|
||||
document: any;
|
||||
};
|
||||
|
||||
const IntroPage = React.forwardRef<HTMLDivElement, Props>((props, ref) => {
|
||||
const { document } = props;
|
||||
const [user, setUser] = useState<any>({});
|
||||
|
||||
useEffect(() => {
|
||||
userStore.getCurrentUser().then((user) => setUser(user));
|
||||
}, []);
|
||||
|
||||
const EmptyState = () => (
|
||||
<Detail className={styles.detailsContent} size="small">
|
||||
Ingen sider her...
|
||||
</Detail>
|
||||
);
|
||||
if (
|
||||
!document._id ||
|
||||
(document?.user_id?.current !== user.id &&
|
||||
!user?.roles?.find((x) => x.name === "administrator"))
|
||||
)
|
||||
return null;
|
||||
|
||||
return (
|
||||
<Stack ref={ref} space={[3, 1, 2, 4]}>
|
||||
<Heading level="2" size="medium" spacing style={{ display: "flex" }}>
|
||||
Profil <Caseworker style={{ marginLeft: "0.5rem", fontSize: "2rem" }} />
|
||||
</Heading>
|
||||
{user?.roles && (
|
||||
<div>
|
||||
<Heading level="3" size="small" spacing>
|
||||
Roller/tilganger:
|
||||
</Heading>
|
||||
{user?.roles.map((x, i) => (
|
||||
<div key={i}>
|
||||
<Label size="small" spacing as="p">
|
||||
{x?.title}
|
||||
</Label>
|
||||
<BodyShort size="small">{x?.description}</BodyShort>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<BodyShort
|
||||
size="small"
|
||||
spacing
|
||||
as="span"
|
||||
style={{ display: "flex", gap: "0.5rem" }}
|
||||
>
|
||||
<ReadMore header="Har du ikke de rollene du trenger?">
|
||||
Send en melding til oss på{" "}
|
||||
<Link href="https://nav-it.slack.com/archives/C7NE7A8UF">
|
||||
#Aksel-designsystemet
|
||||
</Link>{" "}
|
||||
slack så fikser vi det.
|
||||
</ReadMore>
|
||||
</BodyShort>
|
||||
<div style={{ borderTop: "1px solid #bbb" }} />
|
||||
|
||||
<WithReferringDocuments id={document._id?.replace("drafts.", "")}>
|
||||
{({ referringDocuments, isLoading }) => {
|
||||
if (isLoading) {
|
||||
return <Spinner message="Looking for referring documents…" />;
|
||||
}
|
||||
if (!referringDocuments.length) return null;
|
||||
|
||||
const drafts = getDrafts(referringDocuments);
|
||||
const published = getPublished(referringDocuments);
|
||||
const unpublished = getUnpublished(referringDocuments);
|
||||
|
||||
return (
|
||||
<Stack space={2}>
|
||||
<Heading level="3" size="xsmall" style={{ display: "flex" }}>
|
||||
<Upload />
|
||||
Publiserte sider
|
||||
</Heading>
|
||||
|
||||
<ReadMore header={`Oppdaterte: ${published.length}`}>
|
||||
{published ? (
|
||||
<ReferringDocumentsList documents={published} />
|
||||
) : (
|
||||
<EmptyState />
|
||||
)}
|
||||
</ReadMore>
|
||||
<ReadMore header={`Med upubliserte endringer: ${drafts.length}`}>
|
||||
{drafts ? (
|
||||
<ReferringDocumentsList documents={drafts} />
|
||||
) : (
|
||||
<EmptyState />
|
||||
)}
|
||||
</ReadMore>
|
||||
<Heading level="3" size="xsmall" className={styles.headings}>
|
||||
<Wrench />
|
||||
Under arbeid
|
||||
</Heading>
|
||||
<ReadMore header={`Sider: ${unpublished.length}`}>
|
||||
{unpublished ? (
|
||||
<ReferringDocumentsList documents={unpublished} />
|
||||
) : (
|
||||
<EmptyState />
|
||||
)}
|
||||
</ReadMore>
|
||||
<Heading level="3" size="xsmall" className={styles.headings}>
|
||||
<Sandglass />
|
||||
Utdaterte sider
|
||||
</Heading>
|
||||
<ReadMore header={`Ikke oppdatert på over 90 dager: 0`}>
|
||||
<EmptyState />
|
||||
</ReadMore>
|
||||
<ReadMore header={`Ikke oppdatert på over 180 dager: 0`}>
|
||||
<EmptyState />
|
||||
</ReadMore>
|
||||
</Stack>
|
||||
);
|
||||
}}
|
||||
</WithReferringDocuments>
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
|
||||
export default withDocument(IntroPage);
|
||||
@@ -1,35 +0,0 @@
|
||||
/* ./cms/styles/ReferringDocumentsList.css */
|
||||
|
||||
@import "part:@sanity/base/theme/variables-style";
|
||||
|
||||
.root {
|
||||
composes: root from "part:@sanity/components/lists/default-style";
|
||||
}
|
||||
|
||||
.item {
|
||||
composes: lineBetween from "part:@sanity/components/lists/default-item-style";
|
||||
background: var(--white);
|
||||
border-radius: var(--border-radius-base);
|
||||
color: inherit;
|
||||
margin-bottom: var(--small-padding);
|
||||
border: 1px solid var(--list-border-color);
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background-color: var(--a-surface-action-subtle-hover, rgba(230, 240, 255, 1));
|
||||
}
|
||||
|
||||
.link {
|
||||
padding: var(--small-padding);
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.link:focus {
|
||||
border-radius: 2px;
|
||||
outline: none;
|
||||
box-shadow: var(--a-shadow-focus, var(--a-shadow-focus, 0 0 0 3px rgba(0, 52, 125, 1)));
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
@import "part:@sanity/base/theme/variables-style";
|
||||
|
||||
.link {
|
||||
composes: item from "part:@sanity/base/theme/layout/selectable-style";
|
||||
display: block;
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
outline: none;
|
||||
padding: 0.5rem 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.headings {
|
||||
margin-top: 1rem !important;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
p.detailsContent {
|
||||
margin-left: 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
import { Heading, Stack, Text } from "@sanity/ui";
|
||||
import { withDocument } from "part:@sanity/form-builder";
|
||||
import { getPublishedId } from "part:@sanity/base/util/draft-utils";
|
||||
import schema from "part:@sanity/base/schema";
|
||||
import React, { useEffect, useCallback, useState } from "react";
|
||||
import moment from "moment";
|
||||
import { IntentLink } from "part:@sanity/base/router";
|
||||
import { Item, List } from "part:@sanity/components/lists/default";
|
||||
import SanityPreview from "part:@sanity/base/preview";
|
||||
import styles from "./styles.css";
|
||||
const sanityClient = require("@sanity/client");
|
||||
const SanityConfig = require("../sanity.json");
|
||||
|
||||
const client = sanityClient({
|
||||
projectId: SanityConfig.api.projectId,
|
||||
dataset: SanityConfig.api.dataset,
|
||||
apiVersion: "2020-06-19",
|
||||
useCdn: false,
|
||||
});
|
||||
|
||||
const RelatedArticles = React.forwardRef((props, ref) => {
|
||||
const [userDocuments, setUserDocuments] = useState([]);
|
||||
|
||||
const getUserDocs = useCallback(async () => {
|
||||
const userDocs = await client
|
||||
.fetch(`*["${props.document._id}" == contact._ref]`)
|
||||
.catch((e) => console.error(e.message));
|
||||
userDocs && setUserDocuments(userDocs);
|
||||
}, [props.document]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.document) {
|
||||
return;
|
||||
}
|
||||
getUserDocs();
|
||||
}, [getUserDocs]);
|
||||
|
||||
const outdated = userDocuments.filter((doc) => {
|
||||
if (!doc?.metadata?.last_update) return false;
|
||||
const lastUpdate = moment(doc._updatedAt);
|
||||
const daysSince = moment().diff(lastUpdate, "days");
|
||||
return daysSince > 180;
|
||||
});
|
||||
|
||||
const stagnated = userDocuments.filter((doc) => {
|
||||
if (!doc?.metadata?.last_update) return false;
|
||||
const lastUpdate = moment(doc._updatedAt);
|
||||
const daysSince = moment().diff(lastUpdate, "days");
|
||||
return daysSince > 90 && daysSince <= 180;
|
||||
});
|
||||
|
||||
return (
|
||||
<Stack space={0} ref={ref} space={[3, 1, 2, 4]}>
|
||||
<details>
|
||||
<summary>Utdaterte sider: {outdated.length}</summary>
|
||||
<List>
|
||||
{outdated.map((doc) => (
|
||||
<Item key={doc._id}>
|
||||
<IntentLink
|
||||
intent="edit"
|
||||
params={{
|
||||
type: doc._type,
|
||||
id: getPublishedId(doc._id),
|
||||
}}
|
||||
className={styles.link}
|
||||
>
|
||||
<SanityPreview
|
||||
layout="default"
|
||||
type={schema.get(doc._type)}
|
||||
value={doc}
|
||||
key={doc._id}
|
||||
/>
|
||||
</IntentLink>
|
||||
</Item>
|
||||
))}
|
||||
</List>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Stagnerte sider: {stagnated.length}</summary>
|
||||
<List>
|
||||
{stagnated.map((doc) => (
|
||||
<Item key={doc._id}>
|
||||
<IntentLink
|
||||
intent="edit"
|
||||
params={{
|
||||
type: doc._type,
|
||||
id: getPublishedId(doc._id),
|
||||
}}
|
||||
className={styles.link}
|
||||
>
|
||||
<SanityPreview
|
||||
layout="default"
|
||||
type={schema.get(doc._type)}
|
||||
value={doc}
|
||||
key={doc._id}
|
||||
/>
|
||||
</IntentLink>
|
||||
</Item>
|
||||
))}
|
||||
</List>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Alle sider: {userDocuments.length}</summary>
|
||||
<List>
|
||||
{userDocuments.map((doc) => (
|
||||
<Item key={doc._id}>
|
||||
<IntentLink
|
||||
intent="edit"
|
||||
params={{
|
||||
type: doc._type,
|
||||
id: getPublishedId(doc._id),
|
||||
}}
|
||||
className={styles.link}
|
||||
>
|
||||
<SanityPreview
|
||||
layout="default"
|
||||
type={schema.get(doc._type)}
|
||||
value={doc}
|
||||
key={doc._id}
|
||||
/>
|
||||
</IntentLink>
|
||||
</Item>
|
||||
))}
|
||||
</List>
|
||||
</details>
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
|
||||
export default withDocument(RelatedArticles);
|
||||
@@ -1,41 +0,0 @@
|
||||
const teams = [
|
||||
{
|
||||
name: "designsystem",
|
||||
prefix: "ds",
|
||||
documents: ["komponent_artikkel", "ds_artikkel"],
|
||||
navigation: `navigation_designsystem`,
|
||||
},
|
||||
{
|
||||
name: "god_praksis",
|
||||
prefix: "gp",
|
||||
documents: ["aksel_artikkel", "aksel_blogg", "aksel_prinsipp"],
|
||||
},
|
||||
];
|
||||
|
||||
/* Collection of all document-pages to account for */
|
||||
const allDocumentTypes = teams.reduce(
|
||||
(docs, team) => [...docs, ...team.documents],
|
||||
[]
|
||||
);
|
||||
|
||||
/* Collection of all navigation-documents */
|
||||
const allNavDocumentIds = teams.map((x) => x?.navigation).filter((x) => x);
|
||||
|
||||
/**
|
||||
* Defines when a document of a spesific type is set to stagnant or expired
|
||||
* @returns [stagnant Date, expired Date]
|
||||
*/
|
||||
function getExpireDates() {
|
||||
const stagnantDate = new Date();
|
||||
const expiredDate = new Date();
|
||||
stagnantDate.setDate(stagnantDate.getDate() + 120);
|
||||
expiredDate.setDate(expiredDate.getDate() + 180);
|
||||
return [stagnantDate, expiredDate];
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
teams,
|
||||
allDocumentTypes,
|
||||
allNavDocumentIds,
|
||||
getExpireDates,
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"#": "Used by Sanity to keep track of configuration file checksums, do not delete or modify!",
|
||||
"@sanity/default-layout": "bb034f391ba508a6ca8cd971967cbedeb131c4d19b17b28a0895f32db5d568ea",
|
||||
"@sanity/default-login": "6fb6d3800aa71346e1b84d95bbcaa287879456f2922372bb0294e30b968cd37f",
|
||||
"@sanity/form-builder": "b38478227ba5e22c91981da4b53436df22e48ff25238a55a973ed620be5068aa",
|
||||
"@sanity/data-aspects": "d199e2c199b3e26cd28b68dc84d7fc01c9186bf5089580f2e2446994d36b3cb6",
|
||||
"@sanity/vision": "da5b6ed712703ecd04bf4df560570c668aa95252c6bc1c41d6df1bda9b8b8f60",
|
||||
"power-table": "922902575995e62af8f628e6abe652ecc5f3b1e1d2dec5859392e79e47707088",
|
||||
"table": "e56785cc6cecbacf8ebe6bb99ffae32b973e233503c0714497ac7df3042863f1"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"listOptions": {}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"toolSwitcher": {
|
||||
"order": [],
|
||||
"hidden": []
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"providers": {
|
||||
"mode": "append",
|
||||
"redirectOnSingle": false,
|
||||
"entries": [
|
||||
{
|
||||
"name": "saml",
|
||||
"title": "NAV SSO",
|
||||
"url": "https://api.sanity.io/v2021-10-01/auth/saml/login/f3270b37",
|
||||
"logo": "/static/navlogo.svg"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"images": {
|
||||
"directUploads": true
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"defaultApiVersion": "2021-10-21"
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
import { allDocumentTypes } from "../config";
|
||||
|
||||
export const editorField = {
|
||||
title: "Redaktører",
|
||||
description: "Legg til alle som har bidratt med denne siden!",
|
||||
name: "contributors",
|
||||
type: "array",
|
||||
of: [{ type: "reference", to: [{ type: "editor" }] }],
|
||||
group: "settings",
|
||||
validation: (Rule) => Rule.required(),
|
||||
};
|
||||
|
||||
export const privateField = {
|
||||
title: "Sidetilganger",
|
||||
name: "tilgang",
|
||||
type: "object",
|
||||
description: "Styrer tilgang for side-innhold",
|
||||
hidden: true,
|
||||
fields: [
|
||||
{
|
||||
title: "Privat",
|
||||
name: "privat",
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
initialValue: {
|
||||
privat: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const publishedAtField = {
|
||||
title: "Publiseringsdato",
|
||||
name: "publishedAt",
|
||||
type: "datetime",
|
||||
group: "settings",
|
||||
description: "Synlig bare for admins. Setter publiseringsdato for dokument",
|
||||
hidden: ({ currentUser }) =>
|
||||
!currentUser.roles.find((x) => x.name === "administrator"),
|
||||
};
|
||||
|
||||
export const titleField = {
|
||||
title: "Sidetittel",
|
||||
name: "heading",
|
||||
type: "string",
|
||||
group: "innhold",
|
||||
description:
|
||||
"Bruk en kort og konsis tittel om mulig. Blir satt som `<H1 />` på toppen av siden i URL.",
|
||||
validation: (Rule) =>
|
||||
Rule.required()
|
||||
.max(60)
|
||||
.error("Siden bør ha en kort og konsis heading (<h1>)"),
|
||||
};
|
||||
|
||||
export const ingressField = {
|
||||
title: "Ingress",
|
||||
name: "ingress",
|
||||
description: "Side, innganger og seo description-tag",
|
||||
type: "text",
|
||||
group: "innhold",
|
||||
rows: 3,
|
||||
validation: (Rule) =>
|
||||
Rule.required().max(210).error("Ingress kan ikke være på over 210 tegn"),
|
||||
};
|
||||
|
||||
export const innholdFieldNew = {
|
||||
title: "Innhold",
|
||||
name: "content",
|
||||
type: "riktekst_aksel",
|
||||
group: "innhold",
|
||||
};
|
||||
|
||||
export const innholdFieldPrinsipp = {
|
||||
title: "Innhold",
|
||||
name: "content",
|
||||
type: "riktekst_prinsipp",
|
||||
group: "innhold",
|
||||
};
|
||||
|
||||
export const relevanteArtiklerField = {
|
||||
title: "Relevante artikler",
|
||||
description:
|
||||
"Legg til relaterte artikler som du tenker er relevant å lese (maks 3)",
|
||||
name: "relevante_artikler",
|
||||
type: "array",
|
||||
group: "innhold",
|
||||
validation: (Rule) =>
|
||||
Rule.max(3).error("Kan ikke ha mer enn 3 relevante artikler lagt til"),
|
||||
of: [
|
||||
{
|
||||
type: "reference",
|
||||
weak: true,
|
||||
to: [...allDocumentTypes.map((x) => ({ type: x }))],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const innholdFieldNewNested = (name?: string, type?: string) => {
|
||||
const fields = {
|
||||
...innholdFieldNew,
|
||||
type: type ?? "riktekst_ds_artikkel",
|
||||
name: name ?? "content",
|
||||
};
|
||||
delete fields.group;
|
||||
return fields;
|
||||
};
|
||||
@@ -1,154 +0,0 @@
|
||||
export * from "./fields";
|
||||
export * from "./preview";
|
||||
export * from "./seo";
|
||||
import { Settings } from "@navikt/ds-icons";
|
||||
import sanityClient from "part:@sanity/base/client";
|
||||
|
||||
const client = sanityClient.withConfig({ apiVersion: "2020-06-19" });
|
||||
|
||||
export const prinsipper = [
|
||||
{ title: "Brukeropplevelse", value: "brukeropplevelse" },
|
||||
];
|
||||
|
||||
export function toPlainText(blocks = []) {
|
||||
return blocks
|
||||
.filter((block) => !(block._type !== "block" || !block.children))
|
||||
.map((block) => {
|
||||
return block.children.map((child) => child.text).join("");
|
||||
})
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
export const sanitySlug = (prefix: string, depth: number, source?: string) => ({
|
||||
title: "url",
|
||||
name: "slug",
|
||||
type: "slug",
|
||||
validation: (Rule) => validateSlug(Rule, prefix, depth ?? 3),
|
||||
group: "settings",
|
||||
options: {
|
||||
isUnique: isSlugUnique,
|
||||
source: source ?? "heading",
|
||||
slugify: (input) =>
|
||||
`${prefix}${input}`
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.slice(0, 80)
|
||||
.trim()
|
||||
.replace(/\s+/g, "-")
|
||||
.replace("--", "-")
|
||||
.replace("(", "")
|
||||
.replace(")", "")
|
||||
.replace("æ", "a")
|
||||
.replace("ø", "o")
|
||||
.replace("å", "a")
|
||||
.replace(".", "-"),
|
||||
},
|
||||
});
|
||||
|
||||
/* Checks that slug starts with prefix and is nested to x depth */
|
||||
export const validateSlug = (Rule, prefix, nesting) =>
|
||||
Rule.required().custom((slug) => {
|
||||
if (!slug.current.startsWith(prefix)) {
|
||||
return `Slug må starte med prefiks: ${prefix}`;
|
||||
}
|
||||
if ((slug.current.match(/\//g) || []).length > nesting - 1) {
|
||||
return `Siden kan bare være på ${nesting} nivå`;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
/* Checks every document for matching slug */
|
||||
export const isSlugUnique = (slug, options) => {
|
||||
const { document } = options;
|
||||
|
||||
const id = document._id.replace(/^drafts\./, "");
|
||||
const params = {
|
||||
draft: `drafts.${id}`,
|
||||
published: id,
|
||||
slug,
|
||||
};
|
||||
|
||||
const query = `!defined(*[!(_id in [$draft, $published]) && slug.current == $slug][0]._id)`;
|
||||
return client.fetch(query, params);
|
||||
};
|
||||
|
||||
export const isEditorUnique = (slug, options) => {
|
||||
const { document } = options;
|
||||
|
||||
const id = document._id.replace(/^drafts\./, "");
|
||||
const params = {
|
||||
draft: `drafts.${id}`,
|
||||
published: id,
|
||||
slug,
|
||||
};
|
||||
|
||||
const query = `!defined(*[!(_id in [$draft, $published]) && _type == "editor" && user_id.current == $slug][0]._id)`;
|
||||
return client.fetch(query, params);
|
||||
};
|
||||
|
||||
export const groups = [
|
||||
{
|
||||
name: "innhold",
|
||||
title: "Innhold",
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
name: "metadata",
|
||||
title: "Metadata",
|
||||
},
|
||||
{
|
||||
name: "settings",
|
||||
title: "Innstillinger",
|
||||
icon: Settings,
|
||||
},
|
||||
{
|
||||
name: "lenker",
|
||||
title: "Linking",
|
||||
},
|
||||
{
|
||||
name: "beta",
|
||||
title: "Beta",
|
||||
},
|
||||
{
|
||||
name: "seo",
|
||||
title: "SEO",
|
||||
},
|
||||
];
|
||||
|
||||
export const validateKategoriSlug = (Rule, prefix) =>
|
||||
Rule.required().custom((slug, { document }) => {
|
||||
if (!slug.current.startsWith(`${prefix}${document?.kategori}/`)) {
|
||||
return `Slug må starte med prefiks: ${prefix}${document?.kategori}`;
|
||||
}
|
||||
if ((slug.current.match(/\//g) || []).length > 3 - 1) {
|
||||
return `Siden kan bare være på ${3} nivå`;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
export const kategoriSlug = (prefix: string) => ({
|
||||
title: "url (v2)",
|
||||
name: "slug_v2",
|
||||
type: "slug",
|
||||
validation: (Rule) => validateKategoriSlug(Rule, prefix),
|
||||
group: "settings",
|
||||
options: {
|
||||
source: (s) => `${s?.kategori}/${s?.heading}`,
|
||||
slugify: (input) => {
|
||||
return (
|
||||
`${prefix}${input}`
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.slice(0, 200)
|
||||
.trim()
|
||||
.replace(/\s+/g, "-")
|
||||
.replace(/-+/gm, "-")
|
||||
.replace(/æ/g, "a")
|
||||
.replace(/å/g, "a")
|
||||
.replace(/ø/g, "o")
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
.replace(/[&\\#!,+()$~%.'"¨:*?<>{}]/g, "")
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Edit, Task } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export const defaultDocPreview = {
|
||||
preview: {
|
||||
select: {
|
||||
heading: "heading",
|
||||
status: "status",
|
||||
metadata: "metadata",
|
||||
id: "_id",
|
||||
type: "_type",
|
||||
tema: "tema.0.title",
|
||||
prinsipp: "prinsipp",
|
||||
},
|
||||
prepare(selection) {
|
||||
const { id, heading, type, tema, prinsipp } = selection;
|
||||
return {
|
||||
title: heading,
|
||||
subtitle: !!prinsipp
|
||||
? !!prinsipp?.hovedside
|
||||
? "Hovedside"
|
||||
: "Artikkel"
|
||||
: !!tema
|
||||
? `${tema}`
|
||||
: type.includes("_component_")
|
||||
? "Komponentside"
|
||||
: type.includes("_tabbed_")
|
||||
? "Artikkel m/tabs"
|
||||
: "Artikkel",
|
||||
media: id.includes("drafts.") ? (
|
||||
<Edit aria-hidden />
|
||||
) : (
|
||||
<Task aria-hidden />
|
||||
),
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
const pattern = /^image-([a-f\d]+)-(\d+x\d+)-(\w+)$/;
|
||||
|
||||
const decodeAssetId = (id) => {
|
||||
const [, assetId, dimensions, format] = pattern.exec(id);
|
||||
const [width, height] = dimensions.split("x").map((v) => parseInt(v, 10));
|
||||
|
||||
return {
|
||||
assetId,
|
||||
dimensions: { width, height },
|
||||
format,
|
||||
};
|
||||
};
|
||||
|
||||
export const SEOFields = {
|
||||
name: "seo",
|
||||
type: "object",
|
||||
title: "SEO",
|
||||
group: "seo",
|
||||
fields: [
|
||||
{
|
||||
name: "meta",
|
||||
type: "text",
|
||||
title: "Meta/:og description",
|
||||
description:
|
||||
"Anbefalt maks 150-160 bokstaver. Erstatter ingress som <meta /> description",
|
||||
rows: 3,
|
||||
},
|
||||
{
|
||||
title: "og:Image",
|
||||
name: "image",
|
||||
type: "image",
|
||||
description: "Anbefalt størrelse er 1200:630px",
|
||||
options: {
|
||||
accept: "image/*",
|
||||
},
|
||||
validation: (Rule) =>
|
||||
Rule.custom((image) => {
|
||||
if (!image) return true;
|
||||
const { dimensions } = decodeAssetId(image.asset._ref);
|
||||
const aspectR = dimensions.width / dimensions.height;
|
||||
if (aspectR < 1.5 || aspectR > 2.4) {
|
||||
return `Forventet aspect-ration rundt 1.91:1. Er nå: ${aspectR}:1.`;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,57 +0,0 @@
|
||||
{
|
||||
"name": "sanity",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"description": "Sanity setup (v2) for Aksel.nav.no",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "sanity start",
|
||||
"build": "sanity build",
|
||||
"deploy": "yarn typegen && sanity deploy",
|
||||
"backup": "node scripts/backup.js",
|
||||
"typegen": "sanity exec typegen.ts",
|
||||
"sanity:dev": "sanity start",
|
||||
"sanity:deploy": "yarn typegen && sanity deploy",
|
||||
"sanity:backup": "node scripts/backup.js"
|
||||
},
|
||||
"main": "package.json",
|
||||
"keywords": [
|
||||
"sanity"
|
||||
],
|
||||
"dependencies": {
|
||||
"@sanity/base": "^2.35.0",
|
||||
"@sanity/cli": "^2.35.0",
|
||||
"@sanity/code-input": "^2.35.0",
|
||||
"@sanity/components": "^2.14.0",
|
||||
"@sanity/core": "^2.35.0",
|
||||
"@sanity/dashboard": "^2.35.0",
|
||||
"@sanity/default-layout": "^2.35.0",
|
||||
"@sanity/default-login": "^2.35.0",
|
||||
"@sanity/desk-tool": "^2.35.0",
|
||||
"@sanity/export": "^2.30.3",
|
||||
"@sanity/production-preview": "^2.29.3",
|
||||
"@sanity/react-hooks": "^2.35.0",
|
||||
"@sanity/ui": "^0.37.22",
|
||||
"@sanity/vision": "^2.35.0",
|
||||
"moment": "2.29.4",
|
||||
"sanity-codegen": "0.9.8",
|
||||
"sanity-plugin-asset-source-unsplash": "^0.1.5",
|
||||
"sanity-plugin-dashboard-widget-document-list": "^0.0.13",
|
||||
"sanity-plugin-media": "^1.4.4",
|
||||
"sanity-super-pane": "^1.0.0-alpha.11",
|
||||
"styled-components": "^5.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/preset-typescript": "^7.0.0",
|
||||
"@sanity-codegen/schema-codegen": "1.0.0-alpha.13",
|
||||
"babel-plugin-mock-imports": "1.2.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/navikt/aksel-website.git"
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
User-specific packages can be placed here
|
||||
@@ -1,137 +0,0 @@
|
||||
/* https://github.com/sanity-io/dashboard-widget-document-list/blob/master/src/DocumentList.js */
|
||||
|
||||
import client from "@sanity/client";
|
||||
import { Button, Flex } from "@sanity/ui";
|
||||
import { DashboardWidget } from "@sanity/dashboard";
|
||||
|
||||
import React, { useEffect, useState, useRef, useCallback } from "react";
|
||||
import config from "../../config";
|
||||
import SanityConfig from "../../sanity.json";
|
||||
import moment from "moment";
|
||||
import styles from "./widget.css";
|
||||
import { Item, List } from "part:@sanity/components/lists/default";
|
||||
import { IntentLink } from "part:@sanity/base/router";
|
||||
import { getPublishedId } from "part:@sanity/base/util/draft-utils";
|
||||
import { Tag } from "@navikt/ds-react";
|
||||
|
||||
const sanityClient = client({
|
||||
projectId: SanityConfig.api.projectId,
|
||||
dataset: SanityConfig.api.dataset,
|
||||
apiVersion: "2020-06-19",
|
||||
useCdn: false,
|
||||
});
|
||||
|
||||
const OutDatedComponents = ({ type }) => {
|
||||
const query = `*[_type in [${config.allDocumentTypes.map((x) => `"${x}"`)}]]`;
|
||||
const [docs, setDocs] = useState([]);
|
||||
const [loading, setloading] = useState(true);
|
||||
const [timer, setTimer] = useState(new Date());
|
||||
const [fromTime, setFromTime] = useState(moment(new Date()).fromNow());
|
||||
|
||||
const success = (v) => {
|
||||
setDocs(
|
||||
v
|
||||
.filter((x) => {
|
||||
if (!x?._updatedAt) return false;
|
||||
const lastUpdate = moment(x._updatedAt);
|
||||
const daysSince = moment().diff(lastUpdate, "days");
|
||||
return type === "error"
|
||||
? daysSince > 180
|
||||
: daysSince >= 90 && daysSince < 180;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const lastUpdateA = moment(a._updatedAt);
|
||||
const lastUpdateB = moment(b._updatedAt);
|
||||
return lastUpdateA.diff(lastUpdateB, "days");
|
||||
})
|
||||
);
|
||||
setloading(false);
|
||||
setTimer(new Date());
|
||||
};
|
||||
|
||||
const load = useCallback(() => {
|
||||
setloading(true);
|
||||
sanityClient.fetch(query).then(success, (e) => console.error(e));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
load();
|
||||
}, []);
|
||||
|
||||
/* Refreshes every 5 minutes */
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
load();
|
||||
}, 300000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setFromTime(moment(timer).fromNow());
|
||||
}, 10000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const refresh = () => {
|
||||
load();
|
||||
};
|
||||
|
||||
const footer = (
|
||||
<Flex direction="column" align="stretch">
|
||||
<Button
|
||||
fontSize={[2]}
|
||||
tone="primary"
|
||||
paddingX={2}
|
||||
paddingY={4}
|
||||
text={`Updated ${fromTime}`}
|
||||
onClick={() => refresh()}
|
||||
mode="bleed"
|
||||
loading={loading}
|
||||
disabled={loading}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
return (
|
||||
<DashboardWidget
|
||||
header={type === "error" ? "Utdaterte sider" : "Stagnerte sider"}
|
||||
footer={footer}
|
||||
>
|
||||
<List>
|
||||
{docs &&
|
||||
docs.map((doc) => {
|
||||
const lastUpdate = moment(doc._updatedAt);
|
||||
const daysSince = moment().diff(lastUpdate, "days");
|
||||
|
||||
return (
|
||||
<Item key={doc._id}>
|
||||
<IntentLink
|
||||
intent="edit"
|
||||
params={{
|
||||
type: doc._type,
|
||||
id: getPublishedId(doc._id),
|
||||
}}
|
||||
className={styles.link}
|
||||
>
|
||||
<span className={styles.spacing}>
|
||||
<Tag size="small" variant={type}>
|
||||
{daysSince}d
|
||||
</Tag>
|
||||
{doc?.heading}
|
||||
</span>
|
||||
</IntentLink>
|
||||
</Item>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</DashboardWidget>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "outdated-documents-widget",
|
||||
component: OutDatedComponents,
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"parts": [
|
||||
{
|
||||
"name": "part:@sanity/dashboard/widget/outdated-documents-widget",
|
||||
"implements": "part:@sanity/dashboard/widget",
|
||||
"path": "index.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
@import "part:@sanity/base/theme/variables-style";
|
||||
|
||||
.container {
|
||||
composes: container from "part:@sanity/dashboard/widget-styles";
|
||||
}
|
||||
|
||||
.header {
|
||||
composes: header from "part:@sanity/dashboard/widget-styles";
|
||||
}
|
||||
|
||||
.title {
|
||||
composes: title from "part:@sanity/dashboard/widget-styles";
|
||||
}
|
||||
|
||||
.content {
|
||||
composes: content from "part:@sanity/dashboard/widget-styles";
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
padding: var(--small-padding) 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.link {
|
||||
composes: item from "part:@sanity/base/theme/layout/selectable-style";
|
||||
display: block;
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
outline: none;
|
||||
padding: var(--small-padding) var(--medium-padding);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.footer {
|
||||
composes: footer from "part:@sanity/dashboard/widget-styles";
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
.img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.spacing {
|
||||
display: inline-flex;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"project": {
|
||||
"name": "Aksel"
|
||||
},
|
||||
"api": {
|
||||
"projectId": "hnbe3yhs",
|
||||
"dataset": "production"
|
||||
},
|
||||
"env": {
|
||||
"development": {
|
||||
"api": {
|
||||
"dataset": "production"
|
||||
},
|
||||
"plugins": ["@sanity/vision"]
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
"@sanity/base",
|
||||
"@sanity/components",
|
||||
"@sanity/default-layout",
|
||||
"@sanity/default-login",
|
||||
"@sanity/desk-tool",
|
||||
"@sanity/code-input",
|
||||
"@sanity/dashboard",
|
||||
"dashboard-widget-document-list",
|
||||
"outdated-documents-widget",
|
||||
"media",
|
||||
"asset-source-unsplash"
|
||||
],
|
||||
"parts": [
|
||||
{
|
||||
"name": "part:@sanity/base/schema",
|
||||
"path": "./schemas/schema"
|
||||
},
|
||||
{
|
||||
"name": "part:@sanity/desk-tool/structure",
|
||||
"path": "./client/desk-structure/deskStructure.tsx"
|
||||
},
|
||||
{
|
||||
"implements": "part:@sanity/dashboard/config",
|
||||
"path": "./client/dashboardConfig.tsx"
|
||||
},
|
||||
{
|
||||
"name": "part:@sanity/base/initial-value-templates",
|
||||
"path": "./client/initialValueTemplates.tsx"
|
||||
},
|
||||
{
|
||||
"name": "part:@sanity/base/new-document-structure",
|
||||
"path": "./client/newDocumentStructure.tsx"
|
||||
},
|
||||
{
|
||||
"implements": "part:@sanity/base/absolutes",
|
||||
"path": "./client/bundleCheck.tsx"
|
||||
},
|
||||
{
|
||||
"implements": "part:@sanity/form-builder/input/image/asset-sources",
|
||||
"path": "./client/assetSources.ts"
|
||||
},
|
||||
{
|
||||
"implements": "part:@sanity/form-builder/input/file/asset-sources",
|
||||
"path": "./client/assetSources.ts"
|
||||
},
|
||||
{
|
||||
"implements": "part:@sanity/base/document-actions/resolver",
|
||||
"path": "./client/resolveDocumentActions.tsx"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export default null;
|
||||
@@ -1,57 +0,0 @@
|
||||
import {
|
||||
defaultDocPreview,
|
||||
editorField,
|
||||
groups,
|
||||
ingressField,
|
||||
innholdFieldNew,
|
||||
publishedAtField,
|
||||
relevanteArtiklerField,
|
||||
sanitySlug,
|
||||
SEOFields,
|
||||
titleField,
|
||||
} from "@/lib";
|
||||
|
||||
const prefix = "god-praksis/artikler/";
|
||||
|
||||
export default {
|
||||
title: "Aksel Artikkel",
|
||||
name: "aksel_artikkel",
|
||||
type: "document",
|
||||
groups,
|
||||
...defaultDocPreview,
|
||||
fields: [
|
||||
publishedAtField,
|
||||
{
|
||||
title: "Sist godkjent",
|
||||
name: "updateInfo",
|
||||
type: "object",
|
||||
hidden: true,
|
||||
fields: [
|
||||
{
|
||||
type: "date",
|
||||
name: "lastVerified",
|
||||
title: "Sist oppdatert",
|
||||
description: "Kun synlig for utviklere",
|
||||
readOnly: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
editorField,
|
||||
titleField,
|
||||
sanitySlug(prefix, 3),
|
||||
{
|
||||
title: "Tema",
|
||||
description: "Legg til de viktigeste temaene",
|
||||
name: "tema",
|
||||
type: "array",
|
||||
of: [{ type: "reference", to: [{ type: "aksel_tema" }] }],
|
||||
group: "innhold",
|
||||
},
|
||||
|
||||
ingressField,
|
||||
innholdFieldNew,
|
||||
relevanteArtiklerField,
|
||||
|
||||
SEOFields,
|
||||
],
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
import {
|
||||
defaultDocPreview,
|
||||
editorField,
|
||||
groups,
|
||||
ingressField,
|
||||
innholdFieldNew,
|
||||
publishedAtField,
|
||||
sanitySlug,
|
||||
SEOFields,
|
||||
titleField,
|
||||
} from "@/lib";
|
||||
|
||||
const prefix = "produktbloggen/";
|
||||
|
||||
export default {
|
||||
title: "Blogg",
|
||||
name: "aksel_blogg",
|
||||
type: "document",
|
||||
groups,
|
||||
...defaultDocPreview,
|
||||
fields: [
|
||||
publishedAtField,
|
||||
editorField,
|
||||
titleField,
|
||||
sanitySlug(prefix, 2),
|
||||
ingressField,
|
||||
innholdFieldNew,
|
||||
|
||||
SEOFields,
|
||||
],
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
import KomponentArtikkel from "./komponent";
|
||||
|
||||
export default {
|
||||
...KomponentArtikkel,
|
||||
title: "Komponentartikkel-template",
|
||||
name: "ds_component_template",
|
||||
};
|
||||
@@ -1,65 +0,0 @@
|
||||
import {
|
||||
defaultDocPreview,
|
||||
editorField,
|
||||
groups,
|
||||
innholdFieldNew,
|
||||
kategoriSlug,
|
||||
publishedAtField,
|
||||
titleField,
|
||||
} from "@/lib";
|
||||
|
||||
const prefix = "grunnleggende/";
|
||||
|
||||
export default {
|
||||
title: "Artikkel",
|
||||
name: "ds_artikkel",
|
||||
type: "document",
|
||||
groups,
|
||||
...defaultDocPreview,
|
||||
fields: [
|
||||
{
|
||||
title: "Sist godkjent",
|
||||
name: "updateInfo",
|
||||
type: "object",
|
||||
hidden: true,
|
||||
fields: [
|
||||
{
|
||||
type: "date",
|
||||
name: "lastVerified",
|
||||
title: "Sist oppdatert",
|
||||
description: "Kun synlig for utviklere",
|
||||
readOnly: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
publishedAtField,
|
||||
editorField,
|
||||
titleField,
|
||||
kategoriSlug(prefix),
|
||||
{ title: "url", name: "slug", type: "slug", hidden: true },
|
||||
{
|
||||
title: "Kategori",
|
||||
name: "kategori",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required(),
|
||||
options: {
|
||||
list: [
|
||||
{ title: "Styling", value: "styling" },
|
||||
{ title: "Tokens", value: "tokens" },
|
||||
{ title: "Stæsj", value: "staesj" },
|
||||
{ title: "Guider", value: "guider" },
|
||||
].map((x) => ({
|
||||
title: x.title,
|
||||
value: x.value,
|
||||
})),
|
||||
layout: "radio",
|
||||
},
|
||||
hidden: ({ currentUser }) =>
|
||||
!currentUser.roles.find((x) => x.name === "developer"),
|
||||
},
|
||||
{
|
||||
...innholdFieldNew,
|
||||
type: "riktekst_ds_artikkel",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,77 +0,0 @@
|
||||
export default {
|
||||
title: "Forside",
|
||||
name: "ds_frontpage",
|
||||
type: "document",
|
||||
fields: [
|
||||
{
|
||||
name: "body",
|
||||
type: "riktekst_enkel",
|
||||
title: "Innhold",
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
{
|
||||
name: "cards",
|
||||
type: "array",
|
||||
title: "Cards",
|
||||
of: [
|
||||
{
|
||||
title: "Card",
|
||||
name: "card",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Lenke",
|
||||
name: "link_ref",
|
||||
type: "reference",
|
||||
to: [{ type: "komponent_artikkel" }, { type: "ds_artikkel" }],
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
{
|
||||
title: "Tittel",
|
||||
name: "title",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
title: "Innhold",
|
||||
name: "content",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
title: "Pictogram",
|
||||
name: "picture",
|
||||
type: "image",
|
||||
options: {
|
||||
hotspot: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "title",
|
||||
title: "Alt-tekst",
|
||||
type: "string",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Bilde må ha en alt-tekst"),
|
||||
description: "Beskriv bildet for skjermlesere",
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Må legge til et pictogram"),
|
||||
},
|
||||
],
|
||||
options: {
|
||||
modal: {
|
||||
type: "dialog",
|
||||
width: "medium", // 'small' | 'medium' | 'large' | 'full'
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
prepare: () => ({ title: "Forside designsystemet" }),
|
||||
},
|
||||
};
|
||||
@@ -1,218 +0,0 @@
|
||||
// MIGRERT
|
||||
|
||||
import { People } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
import profilePage from "../../components/profile/profile-page";
|
||||
import { isEditorUnique } from "@/lib";
|
||||
import userStore from "part:@sanity/base/user";
|
||||
import sanityClient from "part:@sanity/base/client";
|
||||
|
||||
const navn = [
|
||||
"Alpesteinbukk",
|
||||
"Amurtiger",
|
||||
"Kamel",
|
||||
"Blissbukk",
|
||||
"Borneoorangutang",
|
||||
"Damfrosk",
|
||||
"Dvergsilkeape",
|
||||
"Dåhjort",
|
||||
"Edderkoppape",
|
||||
"Elandantilope",
|
||||
"Elg",
|
||||
"Esel",
|
||||
"Oter",
|
||||
"Fjellrev",
|
||||
"Flodsvin",
|
||||
"Fugler",
|
||||
"Gaupe",
|
||||
"Gepard",
|
||||
"Gulkinngibbon",
|
||||
"Javalangur",
|
||||
"Jerv",
|
||||
"Krokodille",
|
||||
"Labrador",
|
||||
"Puddel",
|
||||
"Skogskatt",
|
||||
"Maine Coon",
|
||||
"Lavlandstapir",
|
||||
"Beagle",
|
||||
"Hysky",
|
||||
"Løve",
|
||||
"Løvetamarin",
|
||||
"Nubisk geit",
|
||||
"Papegøye",
|
||||
"Ringhalelemur",
|
||||
"Rødpanda",
|
||||
"Sau",
|
||||
"Sjimpanse",
|
||||
"Sjiraff",
|
||||
"Stråleskilpadde",
|
||||
"Slanger",
|
||||
"Steppesebra",
|
||||
"Flamingo",
|
||||
"Struts",
|
||||
"Shetlandsponni",
|
||||
"Surikat",
|
||||
"Tiger",
|
||||
"Ulv",
|
||||
"Fjordfe",
|
||||
"Ekorn",
|
||||
"Bever",
|
||||
"Lemen",
|
||||
"Klatremus",
|
||||
"Fjellmarkmus",
|
||||
"Dvergmus",
|
||||
"Småskogmus",
|
||||
"Steinkobbe",
|
||||
"Røyskatt",
|
||||
"Moskusfe",
|
||||
];
|
||||
|
||||
const adjektiv = [
|
||||
"aktuell",
|
||||
"alvorlig",
|
||||
"ansvarlig",
|
||||
"berømt",
|
||||
"bevisst",
|
||||
"klein",
|
||||
"eksisterende",
|
||||
"fjern",
|
||||
"forsiktig",
|
||||
"heldig",
|
||||
"hjelpsom",
|
||||
"hyppig",
|
||||
"imponerende",
|
||||
"kul",
|
||||
"sjarmerende",
|
||||
"lykkelig",
|
||||
"lys",
|
||||
"merkelig",
|
||||
"mistenkelig",
|
||||
"modig",
|
||||
"morsom",
|
||||
"nysgjerrig",
|
||||
"rå",
|
||||
"rask",
|
||||
"blå",
|
||||
"fersk",
|
||||
"grønn",
|
||||
"rettferdig",
|
||||
"rimelig",
|
||||
"ryddig",
|
||||
"selvsikker",
|
||||
"skarp",
|
||||
"skikkelig",
|
||||
"skyldig",
|
||||
"smal",
|
||||
"sprudlende",
|
||||
"søt",
|
||||
"stolt",
|
||||
"streng",
|
||||
"sulten",
|
||||
"tilgjengelig",
|
||||
"vennlig",
|
||||
"voksen",
|
||||
"ærlig",
|
||||
"flittig",
|
||||
];
|
||||
|
||||
const client = sanityClient.withConfig({ apiVersion: "2020-06-19" });
|
||||
|
||||
const generateName = async () => {
|
||||
const names = await client.fetch(`*[_type == "editor"].anon_navn.current`);
|
||||
|
||||
let c = 0;
|
||||
let res = "";
|
||||
while ((res === "" || names.includes(res)) && c < 1000) {
|
||||
const adj = adjektiv[Math.floor(Math.random() * adjektiv.length)];
|
||||
const animal = navn[Math.floor(Math.random() * navn.length)];
|
||||
res = `${adj.charAt(0).toUpperCase() + adj.slice(1)} ${animal}`;
|
||||
c += 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
const generateInitialName = async () => ({
|
||||
current: await generateName(),
|
||||
});
|
||||
|
||||
export default {
|
||||
title: "Redaktører",
|
||||
name: "editor",
|
||||
type: "document",
|
||||
fields: [
|
||||
{
|
||||
title: "Navn",
|
||||
name: "title",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required().error("Må legge til navn"),
|
||||
},
|
||||
{
|
||||
title: "Sanity bruker-id",
|
||||
name: "user_id",
|
||||
type: "slug",
|
||||
validation: (Rule) => Rule.required().error("Må ha Id"),
|
||||
options: {
|
||||
isUnique: isEditorUnique,
|
||||
source: async () => {
|
||||
const { id } = await userStore.getUser("me");
|
||||
return id;
|
||||
},
|
||||
slugify: (input) => input,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Gjør meg anonym",
|
||||
description:
|
||||
"På artikler bytter vi ut navnet ditt med et tullenavn. Eks. Sprudlende Tiger",
|
||||
name: "anonym",
|
||||
type: "boolean",
|
||||
initialValue: true,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
hidden: true,
|
||||
title: "Anonymt navn",
|
||||
name: "anon_navn",
|
||||
type: "slug",
|
||||
initialValue: () => generateInitialName(),
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
title: "Roller",
|
||||
description: "eks: Utvikler, Webanalytiker, uu-spesialist",
|
||||
name: "roller",
|
||||
type: "array",
|
||||
of: [{ type: "string" }],
|
||||
options: {
|
||||
layout: "tags",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "profile_page",
|
||||
type: "string",
|
||||
title: "Profil",
|
||||
inputComponent: profilePage,
|
||||
hidden: ({ currentUser, parent }) => {
|
||||
const { id, roles } = currentUser;
|
||||
return (
|
||||
!roles.find(({ name }) => name === "administrator") &&
|
||||
parent?.user_id?.current !== id
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
},
|
||||
prepare(selection) {
|
||||
const { title } = selection;
|
||||
return {
|
||||
title,
|
||||
media: () => <People />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
import { groups, SEOFields } from "@/lib";
|
||||
|
||||
export default {
|
||||
title: "Forside",
|
||||
name: "vk_frontpage",
|
||||
type: "document",
|
||||
groups,
|
||||
fields: [
|
||||
{
|
||||
title: "Tittel",
|
||||
name: "title",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
{
|
||||
title: "Beskrivelse",
|
||||
name: "beskrivelse",
|
||||
type: "riktekst_enkel",
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
{
|
||||
title: "Brukeropplevelse",
|
||||
name: "prinsipp_1",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Vis på forside",
|
||||
name: "vis",
|
||||
type: "boolean",
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
{
|
||||
title: "Beskrivelse",
|
||||
name: "beskrivelse",
|
||||
type: "riktekst_enkel",
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
{
|
||||
title: "Hovedside",
|
||||
name: "hovedside",
|
||||
type: "reference",
|
||||
weak: true,
|
||||
to: [{ type: "aksel_prinsipp" }],
|
||||
},
|
||||
{
|
||||
title: "Undersider",
|
||||
description: "Rekkefølge bestemmer rekkefølgen på forsiden!",
|
||||
name: "undersider",
|
||||
type: "array",
|
||||
of: [
|
||||
{ type: "reference", weak: true, to: [{ type: "aksel_prinsipp" }] },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
SEOFields,
|
||||
],
|
||||
};
|
||||
@@ -1,57 +0,0 @@
|
||||
/* import { ExampleKeys } from "website/component-examples"; */
|
||||
|
||||
export default {
|
||||
title: "Dir/filnavn for kode eksempler",
|
||||
name: "kode_eksempler_fil",
|
||||
type: "document",
|
||||
fields: [
|
||||
{
|
||||
title: "Tittel",
|
||||
name: "title",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required(),
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
title: "Toggle om eksemplet er et dir eller filnavn",
|
||||
name: "dir",
|
||||
type: "boolean",
|
||||
validation: (Rule) => Rule.required(),
|
||||
initialValue: false,
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
title: "Filer",
|
||||
name: "filer",
|
||||
type: "array",
|
||||
readOnly: true,
|
||||
of: [
|
||||
{
|
||||
title: "Data i filer",
|
||||
name: "fil",
|
||||
type: "object",
|
||||
fields: [
|
||||
{ title: "Filnavn", name: "navn", type: "string" },
|
||||
{ title: "Innhold", name: "innhold", type: "string" },
|
||||
{ title: "Beskrivelse", name: "description", type: "text" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
dir: "dir",
|
||||
},
|
||||
prepare(selection) {
|
||||
const { title, dir } = selection;
|
||||
return {
|
||||
title: title,
|
||||
subtitle: dir ? "Alle kode-eksempler" : "Spesifikt kode-eksempel",
|
||||
media: () => "</>",
|
||||
};
|
||||
},
|
||||
},
|
||||
__experimental_omnisearch_visibility: false,
|
||||
};
|
||||
@@ -1,126 +0,0 @@
|
||||
import {
|
||||
defaultDocPreview,
|
||||
editorField,
|
||||
groups,
|
||||
innholdFieldNew,
|
||||
kategoriSlug,
|
||||
publishedAtField,
|
||||
titleField,
|
||||
} from "@/lib";
|
||||
|
||||
const prefix = "komponenter/";
|
||||
|
||||
export default {
|
||||
title: "Komponentartikkel",
|
||||
name: "komponent_artikkel",
|
||||
type: "document",
|
||||
groups,
|
||||
...defaultDocPreview,
|
||||
fields: [
|
||||
publishedAtField,
|
||||
editorField,
|
||||
titleField,
|
||||
kategoriSlug(prefix),
|
||||
{ title: "url", name: "slug", type: "slug", hidden: true },
|
||||
{
|
||||
title: "Sist godkjent",
|
||||
name: "updateInfo",
|
||||
type: "object",
|
||||
hidden: true,
|
||||
fields: [
|
||||
{
|
||||
type: "date",
|
||||
name: "lastVerified",
|
||||
title: "Sist oppdatert",
|
||||
description: "Kun synlig for utviklere",
|
||||
readOnly: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Kategori",
|
||||
name: "kategori",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required(),
|
||||
options: {
|
||||
list: [
|
||||
{ title: "Core", value: "core" },
|
||||
{ title: "Internal", value: "internal" },
|
||||
].map((x) => ({
|
||||
title: x.title,
|
||||
value: x.value,
|
||||
})),
|
||||
layout: "radio",
|
||||
},
|
||||
hidden: ({ currentUser }) =>
|
||||
!currentUser.roles.find((x) => x.name === "developer"),
|
||||
},
|
||||
{
|
||||
title: "Metadata",
|
||||
name: "status",
|
||||
group: "innhold",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Status",
|
||||
name: "tag",
|
||||
type: "string",
|
||||
initialValue: "new",
|
||||
options: {
|
||||
list: [
|
||||
{ title: "Beta", value: "beta" },
|
||||
{ title: "New", value: "new" },
|
||||
{ title: "Ready", value: "ready" },
|
||||
{ title: "Deprecated", value: "deprecated" },
|
||||
],
|
||||
layout: "radio",
|
||||
},
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
{
|
||||
name: "bilde",
|
||||
title: "Thumbnail",
|
||||
type: "image",
|
||||
},
|
||||
],
|
||||
options: {
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "intro",
|
||||
type: "intro_komponent",
|
||||
group: "innhold",
|
||||
},
|
||||
{
|
||||
...innholdFieldNew,
|
||||
type: "riktekst_komponent",
|
||||
name: "content",
|
||||
title: "Innhold",
|
||||
},
|
||||
{
|
||||
title: "Kodepakker",
|
||||
name: "kodepakker",
|
||||
type: "array",
|
||||
of: [{ type: "string" }],
|
||||
options: {
|
||||
list: [
|
||||
{ title: "ds-react", value: "ds-react" },
|
||||
{ title: "ds-css", value: "ds-css" },
|
||||
{ title: "ds-react-internal", value: "ds-react-internal" },
|
||||
{ title: "ds-css-internal", value: "ds-css-internal" },
|
||||
{ title: "ds-icons", value: "ds-icons" },
|
||||
{ title: "ds-tokens", value: "ds-tokens" },
|
||||
{ title: "ds-tailwind", value: "ds-tailwind" },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Figma lenke (optional)",
|
||||
name: "figma_link",
|
||||
type: "url",
|
||||
group: "lenker",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,129 +0,0 @@
|
||||
export default {
|
||||
name: "ds_navigation",
|
||||
title: "Navigation",
|
||||
type: "document",
|
||||
fields: [
|
||||
{
|
||||
title: "Designsystem navigajsons-struktur",
|
||||
name: "title",
|
||||
type: "string",
|
||||
readOnly: true,
|
||||
hidden: true,
|
||||
initialValue: "Designsystem navigajsons-struktur",
|
||||
},
|
||||
{
|
||||
name: "headings",
|
||||
title: "Header linker",
|
||||
type: "array",
|
||||
of: [
|
||||
{
|
||||
type: "ds_navigation_heading",
|
||||
name: "heading",
|
||||
title: "Header link",
|
||||
},
|
||||
],
|
||||
validation: (Rule) =>
|
||||
Rule.required()
|
||||
.min(1)
|
||||
.error("Headingmenyen må ha minst en koblet lenke i sidemenyen"),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const ds_header_heading = {
|
||||
name: "ds_navigation_heading",
|
||||
title: "Header link",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
name: "title",
|
||||
title: "Heading tittel",
|
||||
type: "string",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Header lenken må ha en tittel"),
|
||||
},
|
||||
{
|
||||
title: "Side selve headingen linker til",
|
||||
description:
|
||||
"Husk å legge denne til i menyen også, hvis ikke blir den bare tilgjengelig via headern",
|
||||
name: "link_ref",
|
||||
type: "reference",
|
||||
to: [{ type: "komponent_artikkel" }, { type: "ds_artikkel" }],
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Header lenken må linke til en startside"),
|
||||
},
|
||||
{
|
||||
title: "Meny for denne headingen",
|
||||
name: "menu",
|
||||
type: "array",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Sidemeny må ha misnt en lenke"),
|
||||
of: [
|
||||
{
|
||||
title: "Menypunkt",
|
||||
name: "item",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Menypunkt tittel",
|
||||
name: "title",
|
||||
type: "string",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Sidemeny-lenken må ha en tittel"),
|
||||
},
|
||||
{
|
||||
title: "Link til side",
|
||||
name: "link",
|
||||
type: "reference",
|
||||
to: [{ type: "komponent_artikkel" }, { type: "ds_artikkel" }],
|
||||
options: {
|
||||
modal: {
|
||||
type: "dialog",
|
||||
width: "medium", // 'small' | 'medium' | 'large' | 'full'
|
||||
},
|
||||
},
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Sidemeny-lenken må lenke til en side"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Subheading",
|
||||
name: "subheading",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Subheading",
|
||||
name: "title",
|
||||
type: "string",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Subheading må være fylt ut"),
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
},
|
||||
prepare(selection) {
|
||||
const { title } = selection;
|
||||
return {
|
||||
title: title,
|
||||
subtitle: "Subheading",
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
},
|
||||
prepare({ title }) {
|
||||
return {
|
||||
title: `${title}`,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,141 +0,0 @@
|
||||
import {
|
||||
defaultDocPreview,
|
||||
editorField,
|
||||
groups,
|
||||
ingressField,
|
||||
innholdFieldPrinsipp,
|
||||
isSlugUnique,
|
||||
prinsipper,
|
||||
publishedAtField,
|
||||
SEOFields,
|
||||
titleField,
|
||||
} from "@/lib";
|
||||
import sanityClient from "part:@sanity/base/client";
|
||||
|
||||
const client = sanityClient.withConfig({ apiVersion: "2020-06-19" });
|
||||
|
||||
const prefix = "prinsipper/";
|
||||
|
||||
export default {
|
||||
title: "Aksel Prinsipp",
|
||||
name: "aksel_prinsipp",
|
||||
type: "document",
|
||||
groups,
|
||||
...defaultDocPreview,
|
||||
fields: [
|
||||
publishedAtField,
|
||||
editorField,
|
||||
titleField,
|
||||
{
|
||||
title: "url",
|
||||
name: "slug",
|
||||
type: "slug",
|
||||
validation: (Rule) =>
|
||||
Rule.required().custom((slug, { document }) => {
|
||||
if (!slug || !slug.current)
|
||||
return `Må ha noe innhold. Har du husket å velget et prinsipp først?`;
|
||||
const maxLength = document?.prinsipp?.hovedside ? 2 : 3;
|
||||
const newPrefix = `${prefix}${document?.prinsipp?.prinsippvalg}`;
|
||||
|
||||
if (!document?.prinsipp?.prinsippvalg)
|
||||
return `Siden må ha valgt prinsipp for å sette opp url`;
|
||||
if (document?.prinsipp?.hovedside && slug.current !== newPrefix) {
|
||||
return `Siden er en hovedside for prinsippet og må derfor være på url ${newPrefix}`;
|
||||
}
|
||||
if (
|
||||
!document?.prinsipp?.hovedside &&
|
||||
!slug.current.startsWith(newPrefix)
|
||||
) {
|
||||
return `Slug må starte med: ${newPrefix}`;
|
||||
}
|
||||
|
||||
if (
|
||||
(slug.current.split("/") || []).filter((x) => !!x).length !==
|
||||
maxLength
|
||||
) {
|
||||
return `Siden må være på ${maxLength} nivå`;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
group: "settings",
|
||||
options: {
|
||||
isUnique: isSlugUnique,
|
||||
source: ({ prinsipp = null, heading = null }) => ({
|
||||
prinsipp,
|
||||
heading,
|
||||
}),
|
||||
slugify: ({ prinsipp, heading }) => {
|
||||
if (!prinsipp || !heading) return "";
|
||||
const rest = prinsipp.hovedside ? "" : `/${heading}`;
|
||||
return `${prefix}${prinsipp.prinsippvalg}${rest}`
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.slice(0, 80)
|
||||
.trim()
|
||||
.replace(/\s+/g, "-")
|
||||
.replace("æ", "a")
|
||||
.replace("ø", "o")
|
||||
.replace("å", "a");
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Prinsipp",
|
||||
description: "Velg prinsippet siden omhandler",
|
||||
name: "prinsipp",
|
||||
group: "innhold",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Velg prinsipp",
|
||||
name: "prinsippvalg",
|
||||
type: "string",
|
||||
options: {
|
||||
list: prinsipper,
|
||||
layout: "radio",
|
||||
},
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Prinsippsider må ha valgt et prinsipp"),
|
||||
},
|
||||
{
|
||||
title: "Er denne siden hovedsiden til Prinsippet?",
|
||||
name: "hovedside",
|
||||
type: "boolean",
|
||||
initialValue: false,
|
||||
validation: (Rule) =>
|
||||
Rule.required().custom(async (_, { document, parent }) => {
|
||||
const id = document._id.replace(/^drafts\./, "");
|
||||
const params = {
|
||||
draft: `drafts.${id}`,
|
||||
published: id,
|
||||
hoved: parent?.hovedside,
|
||||
prinsipp: parent?.prinsippvalg,
|
||||
};
|
||||
|
||||
const query = `*[!(_id in [$draft, $published]) && _type == "aksel_prinsipp" && prinsipp.prinsippvalg == $prinsipp && prinsipp.hovedside == true][0]{heading,_id}`;
|
||||
const res = await client.fetch(query, params);
|
||||
|
||||
if (parent?.hovedside && !!res?._id) {
|
||||
return `Kan bare ha en hovedside for hvert prinsipp. Hovedsiden er nå: ${
|
||||
res?.heading ?? "Siden har ikke en heading"
|
||||
}`;
|
||||
} else if (!parent?.hovedside && !res?._id) {
|
||||
return `Hvert prinsipp må ha minst en hovedside. Velg en hovedside før du fortsetter`;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Hero bilde",
|
||||
name: "hero_bilde",
|
||||
type: "herobilde",
|
||||
group: "innhold",
|
||||
hidden: ({ parent }) => !parent.prinsipp.hovedside,
|
||||
},
|
||||
ingressField,
|
||||
innholdFieldPrinsipp,
|
||||
SEOFields,
|
||||
],
|
||||
};
|
||||
@@ -1,88 +0,0 @@
|
||||
/* import { ExampleKeys } from "website/component-examples"; */
|
||||
|
||||
export default {
|
||||
title: "Autogenerert Propdata",
|
||||
name: "ds_props",
|
||||
type: "document",
|
||||
fields: [
|
||||
{
|
||||
title: "Tittel",
|
||||
name: "title",
|
||||
type: "string",
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
title: "Displayname",
|
||||
name: "displayname",
|
||||
type: "string",
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
title: "Filepath",
|
||||
name: "filepath",
|
||||
type: "string",
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
title: "props",
|
||||
name: "proplist",
|
||||
type: "array",
|
||||
readOnly: true,
|
||||
of: [
|
||||
{
|
||||
title: "Prop",
|
||||
name: "prop",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Name",
|
||||
name: "name",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
title: "DefaultValue",
|
||||
name: "defaultValue",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
title: "Description",
|
||||
name: "description",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
title: "Required",
|
||||
name: "required",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
title: "Type",
|
||||
name: "type",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
title: "isRef",
|
||||
name: "ref",
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
filepath: "filepath",
|
||||
id: "_id",
|
||||
},
|
||||
prepare(selection) {
|
||||
const { title, filepath, id } = selection;
|
||||
const str = id.includes("core") ? "ds-react" : "ds-internal";
|
||||
return {
|
||||
title,
|
||||
subtitle: `${str}: ${filepath}`,
|
||||
};
|
||||
},
|
||||
},
|
||||
__experimental_omnisearch_visibility: false,
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
const limits = [
|
||||
"/blogg/",
|
||||
"/artikkel/",
|
||||
"/prinsipper/",
|
||||
"/designsystem/side/",
|
||||
"/designsystem/komponenter/",
|
||||
];
|
||||
|
||||
export default {
|
||||
name: "redirect",
|
||||
title: "Redirect",
|
||||
type: "document",
|
||||
fields: [
|
||||
{
|
||||
name: "source",
|
||||
title: "Fra",
|
||||
type: "string",
|
||||
validation: (Rule) =>
|
||||
Rule.required().custom((_, { parent }) => {
|
||||
if (!parent?.source?.startsWith?.("/")) {
|
||||
return "Kan bare redirecte fra relativ-url, eks /min/gamle/sideurl";
|
||||
}
|
||||
const valid = limits.find(
|
||||
(x) => parent?.source?.startsWith?.(x) && parent.source > x
|
||||
);
|
||||
|
||||
if (!valid) {
|
||||
return `Kan bare redirecte fra sider som starter med en av disse url-ene ${limits.join(
|
||||
", "
|
||||
)}`;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "destination",
|
||||
title: "Til",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
{
|
||||
name: "permanent",
|
||||
title: "Permanent",
|
||||
type: "boolean",
|
||||
initialValue: () => true,
|
||||
},
|
||||
],
|
||||
__experimental_omnisearch_visibility: false,
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
import {
|
||||
defaultDocPreview,
|
||||
groups,
|
||||
innholdFieldNew,
|
||||
publishedAtField,
|
||||
sanitySlug,
|
||||
titleField,
|
||||
} from "@/lib";
|
||||
|
||||
const prefix = "side/";
|
||||
|
||||
export default {
|
||||
title: "Standalone-sider",
|
||||
name: "aksel_standalone",
|
||||
type: "document",
|
||||
groups,
|
||||
...defaultDocPreview,
|
||||
fields: [
|
||||
publishedAtField,
|
||||
titleField,
|
||||
sanitySlug(prefix, 2),
|
||||
innholdFieldNew,
|
||||
],
|
||||
};
|
||||
@@ -1,148 +0,0 @@
|
||||
import { groups } from "@/lib";
|
||||
|
||||
export default {
|
||||
title: "Aksel Tema",
|
||||
name: "aksel_tema",
|
||||
type: "document",
|
||||
groups,
|
||||
fields: [
|
||||
{
|
||||
title: "Navn",
|
||||
name: "title",
|
||||
type: "string",
|
||||
group: "innhold",
|
||||
validation: (Rule) =>
|
||||
Rule.required()
|
||||
.warning("Denne endringe påvirker URL")
|
||||
.error("Temaet må ha et navn"),
|
||||
},
|
||||
{
|
||||
title: "Kort Intro/Oppsummering",
|
||||
description: "Brukes i kort og innganger",
|
||||
name: "oppsummering",
|
||||
type: "string",
|
||||
group: "innhold",
|
||||
validation: (Rule) =>
|
||||
Rule.required()
|
||||
.max(65)
|
||||
.error("Temaet burde ha en kort oppsummering/intro på max 65tegn"),
|
||||
},
|
||||
{
|
||||
title: "Beskrivelse",
|
||||
name: "beskrivelse",
|
||||
type: "riktekst_enkel",
|
||||
group: "innhold",
|
||||
},
|
||||
{
|
||||
title: "Hidden",
|
||||
name: "bruk_seksjoner",
|
||||
type: "boolean",
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
title: "Shortname",
|
||||
description: "En mer sanitert visning av tema-navnet i url ene",
|
||||
name: "slug",
|
||||
type: "slug",
|
||||
group: "innhold",
|
||||
validation: (Rule) => Rule.required().error("Tema må ha en URL"),
|
||||
options: {
|
||||
source: "title",
|
||||
slugify: (s: string) =>
|
||||
s
|
||||
? s
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.replace(/\s+/g, "-")
|
||||
.replace(/-+/gm, "-")
|
||||
.replace(/æ/g, "a")
|
||||
.replace(/å/g, "a")
|
||||
.replace(/ø/g, "o")
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
.replace(/[&\\#!,+()$~%.'"¨:*?<>{}]/g, "")
|
||||
: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Ansvarlig for tema",
|
||||
description: "Legg til redaktør som har forvaltningsansvaret for temaet",
|
||||
name: "ansvarlig",
|
||||
type: "reference",
|
||||
to: [{ type: "editor" }],
|
||||
validation: (Rule) => Rule.required(),
|
||||
group: "innhold",
|
||||
},
|
||||
{
|
||||
title: "Seksjonering",
|
||||
description:
|
||||
"Del inn artiklene i flere seksjoner (vises ikke i preview før publisering desverre)",
|
||||
name: "seksjoner",
|
||||
type: "array",
|
||||
group: "innhold",
|
||||
of: [
|
||||
{
|
||||
type: "object",
|
||||
title: "Seksjon",
|
||||
name: "seksjon",
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
name: "title",
|
||||
title: "Tittel",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Seksjonen må ha et navn"),
|
||||
},
|
||||
{
|
||||
title: "Beskrivelse",
|
||||
name: "beskrivelse",
|
||||
type: "riktekst_enkel",
|
||||
},
|
||||
{
|
||||
name: "sider",
|
||||
type: "array",
|
||||
title: "Sider",
|
||||
of: [
|
||||
{
|
||||
type: "reference",
|
||||
name: "ref",
|
||||
title: "Side",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Seksjonen må ha minst en referanse"),
|
||||
to: [{ type: "aksel_artikkel" }],
|
||||
options: {
|
||||
filter: ({ document, parent }) => {
|
||||
const selected = parent
|
||||
.filter((x) => !!x._ref)
|
||||
.map((x) => x._ref);
|
||||
return {
|
||||
filter: "references($refId) && !(_id in $docIds)",
|
||||
params: {
|
||||
refId: document._id.replace("drafts.", ""),
|
||||
docIds: selected,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Pictogram",
|
||||
name: "pictogram",
|
||||
type: "image",
|
||||
fields: [
|
||||
{
|
||||
name: "alt",
|
||||
type: "string",
|
||||
title: "Attribution",
|
||||
hidden: true,
|
||||
},
|
||||
],
|
||||
validation: (Rule) => Rule.required().error("Tema må ha pictogram"),
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
export default {
|
||||
title: "Tokens",
|
||||
name: "token_kategori",
|
||||
type: "document",
|
||||
fields: [
|
||||
{
|
||||
title: "Navn",
|
||||
name: "title",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required(),
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
title: "Kategori",
|
||||
name: "kategori",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required(),
|
||||
readOnly: true,
|
||||
},
|
||||
],
|
||||
__experimental_omnisearch_visibility: false,
|
||||
};
|
||||
@@ -1,75 +0,0 @@
|
||||
import { Expand } from "@navikt/ds-icons";
|
||||
import { innholdFieldNewNested } from "@/lib";
|
||||
import React from "react";
|
||||
import { BodyLong, Label } from "@navikt/ds-react";
|
||||
|
||||
export default {
|
||||
name: "accordion",
|
||||
title: "Accordion",
|
||||
type: "object",
|
||||
fields: [
|
||||
{ title: "Tittel (optional)", type: "string", name: "title" },
|
||||
{
|
||||
title: "Liste",
|
||||
description: "Legg til en eller flere elementer",
|
||||
name: "list",
|
||||
type: "array",
|
||||
of: [
|
||||
{
|
||||
title: "Accordion",
|
||||
name: "element",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Tittel ",
|
||||
name: "title",
|
||||
type: "string",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Accordion må ha en tittel"),
|
||||
},
|
||||
innholdFieldNewNested("content", "riktekst_aksel"),
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
},
|
||||
prepare(selection) {
|
||||
return {
|
||||
title: selection.title ?? "",
|
||||
media: () => <Expand />,
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
validation: (Rule) =>
|
||||
Rule.required().min(1).error("Accordion modul må ha minst 1 element"),
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
list: "list",
|
||||
},
|
||||
prepare(s) {
|
||||
return {
|
||||
title: s?.title ? s.title : "Accordion",
|
||||
list: s?.list,
|
||||
};
|
||||
},
|
||||
component: ({ value }) => {
|
||||
return value?.list ? (
|
||||
<BodyLong as="div">
|
||||
<Label as="p">{`Accordion (${value.list.length})`}</Label>
|
||||
<ul>
|
||||
{value.list.map((x, y) => (
|
||||
<li key={x._key}>{x.title}</li>
|
||||
))}
|
||||
</ul>
|
||||
</BodyLong>
|
||||
) : (
|
||||
<Label as="p">Accordion</Label>
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,68 +0,0 @@
|
||||
import { toPlainText } from "@/lib";
|
||||
import { Warning } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
name: "alert",
|
||||
title: "Alert",
|
||||
type: "object",
|
||||
icon: Warning,
|
||||
fields: [
|
||||
{
|
||||
title: "Variant",
|
||||
name: "variant",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required().error("Alert må ha en variant"),
|
||||
options: {
|
||||
list: [
|
||||
{ value: "success", title: "Suksess" },
|
||||
{ value: "info", title: "Info" },
|
||||
{ value: "warning", title: "Fare" },
|
||||
{ value: "error", title: "Error" },
|
||||
],
|
||||
layout: "radio",
|
||||
},
|
||||
initialValue: "info",
|
||||
},
|
||||
{
|
||||
title: "Heading (optional)",
|
||||
name: "heading",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
title: "Heading nivå",
|
||||
name: "heading_level",
|
||||
type: "string",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Alert må ha et heading-nivå"),
|
||||
options: {
|
||||
list: [
|
||||
{ value: "h3", title: "H3" },
|
||||
{ value: "h4", title: "H4" },
|
||||
],
|
||||
layout: "radio",
|
||||
},
|
||||
hidden: ({ parent }) => !parent.heading,
|
||||
initialValue: "h3",
|
||||
},
|
||||
{
|
||||
title: "Innhold",
|
||||
name: "body",
|
||||
type: "riktekst_enkel",
|
||||
validation: (Rule) => Rule.required().error("Alert må ha noe innhold"),
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
variant: "variant",
|
||||
body: "body",
|
||||
},
|
||||
prepare(selection) {
|
||||
return {
|
||||
title: toPlainText(selection?.body),
|
||||
subtitle: `Alert - ${selection.variant}`,
|
||||
media: () => <Warning />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,105 +0,0 @@
|
||||
import { Picture } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Bilde",
|
||||
name: "bilde",
|
||||
type: "image",
|
||||
icon: Picture,
|
||||
options: {
|
||||
hotspot: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "alt",
|
||||
title: "Alt-tekst",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required().error("Bilde må ha en alt-tekst"),
|
||||
description: "Beskriv bildet for skjermlesere",
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "caption",
|
||||
title: "Bilde-tekst (optional)",
|
||||
description: "Dette vil stå under bildet",
|
||||
type: "string",
|
||||
hidden: ({ parent }) => parent?.floating,
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "small",
|
||||
title: "Bildet tar bare ~halve bredden",
|
||||
type: "boolean",
|
||||
initialValue: false,
|
||||
hidden: ({ parent }) => parent?.floating || parent?.hide_floating,
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Kilde",
|
||||
type: "object",
|
||||
name: "kilde",
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
collapsible: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
title: "Legg til kilde",
|
||||
name: "har_kilde",
|
||||
type: "boolean",
|
||||
initialValue: false,
|
||||
},
|
||||
{
|
||||
title: "Kilde-prefix",
|
||||
name: "prefix",
|
||||
type: "string",
|
||||
options: {
|
||||
list: [
|
||||
{ title: "FOTO:", value: "FOTO" },
|
||||
{ title: "Kilde:", value: "Kilde" },
|
||||
],
|
||||
layout: "radio",
|
||||
direction: "horizontal",
|
||||
},
|
||||
hidden: ({ parent }) => !parent?.har_kilde,
|
||||
},
|
||||
{
|
||||
title: "Tekst",
|
||||
name: "tekst",
|
||||
type: "string",
|
||||
hidden: ({ parent }) => !parent?.har_kilde,
|
||||
},
|
||||
{
|
||||
title: "Lenke-kilde",
|
||||
description: "Kilde-teksten blir satt som lenke",
|
||||
name: "link",
|
||||
type: "url",
|
||||
hidden: ({ parent }) => !parent?.har_kilde,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
validation: (Rule) =>
|
||||
Rule.custom((v) => {
|
||||
return v?.asset ? true : "Må legge til et bilde";
|
||||
}).error(),
|
||||
preview: {
|
||||
select: {
|
||||
alt: "alt",
|
||||
floating: "floating",
|
||||
},
|
||||
prepare(selection) {
|
||||
return {
|
||||
title: selection?.alt,
|
||||
subtitle: `Bilde`,
|
||||
media: () => <Picture />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
import { Success } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Do / Dont",
|
||||
name: "do_dont",
|
||||
type: "object",
|
||||
icon: Success,
|
||||
fields: [
|
||||
{
|
||||
type: "array",
|
||||
name: "blokker",
|
||||
title: "Do / donts",
|
||||
of: [{ type: "do_dont_block" }],
|
||||
validation: (Rule) => Rule.required().max(4),
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
prepare() {
|
||||
return {
|
||||
title: "Do / Dont",
|
||||
media: () => <Success />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const doDontBlock = {
|
||||
title: "DoDont",
|
||||
name: "do_dont_block",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Fullwidth",
|
||||
description: "Tar opp ~ 40% eller 100% av tilgjengelig bredde",
|
||||
name: "fullwidth",
|
||||
type: "boolean",
|
||||
validation: (Rule) => Rule.required(),
|
||||
initialValue: false,
|
||||
},
|
||||
{
|
||||
title: "Bilde",
|
||||
name: "picture",
|
||||
type: "image",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Do/dont må ha et bilde lagt til"),
|
||||
options: {
|
||||
hotspot: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "alt tekst for bilde",
|
||||
name: "alt",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required().error("Do/dont må ha en alt-tekst"),
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
title: "Fritekst",
|
||||
description:
|
||||
"Korte konsise beskrivelser. Bruk fullbredde bilde i dodont med egen tekst for lengre forklaringer",
|
||||
type: "text",
|
||||
},
|
||||
{
|
||||
name: "variant",
|
||||
title: "Variant",
|
||||
type: "string",
|
||||
options: {
|
||||
list: [
|
||||
{ title: "Do", value: "do" },
|
||||
{ title: "Dont", value: "dont" },
|
||||
{ title: "Warning", value: "warning" },
|
||||
],
|
||||
layout: "radio",
|
||||
},
|
||||
initialValue: "do",
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
*/
|
||||
@@ -1,36 +0,0 @@
|
||||
import { Picture } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Hero bilde",
|
||||
name: "herobilde",
|
||||
type: "image",
|
||||
icon: Picture,
|
||||
options: {
|
||||
hotspot: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "alt",
|
||||
title: "Alt-tekst",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required().error("Bilde må ha en alt-tekst"),
|
||||
description: "Beskriv bildet for skjermlesere",
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
alt: "alt",
|
||||
},
|
||||
prepare(selection) {
|
||||
return {
|
||||
title: selection?.alt,
|
||||
subtitle: `Bilde`,
|
||||
media: () => <Picture />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,59 +0,0 @@
|
||||
import Accordion from "./accordion";
|
||||
import Alert from "./alert";
|
||||
import Innholdskort from "./innholdskort";
|
||||
import Bilde from "./bilde";
|
||||
import DoDont, { doDontBlock } from "./do-dont";
|
||||
import HeroBilde from "./hero-bilde";
|
||||
import introKomponent from "./intro-komponent";
|
||||
import Kode from "./kode";
|
||||
import KodeEksempler from "./kode-eksempler";
|
||||
import Props from "./props";
|
||||
import RelatertInnhold from "./relatert-innhold";
|
||||
import { tmpTabell, tmpTabellRow } from "./tabellv2";
|
||||
import {
|
||||
RiktekstAksel,
|
||||
RiktekstDsArtikkel,
|
||||
RiktekstEnkel,
|
||||
RiktekstKomponent,
|
||||
RiktekstPrinsipp,
|
||||
RiktekstTabell,
|
||||
} from "./riktekst";
|
||||
import SpesialSeksjon from "./spesial-seksjon";
|
||||
import Tastatur from "./tastatur";
|
||||
import Tips from "./tips";
|
||||
import TokenRef from "./token-tabell";
|
||||
import Video from "./video";
|
||||
|
||||
const v2Blocks = [
|
||||
tmpTabell,
|
||||
tmpTabellRow,
|
||||
/* Blocks */
|
||||
RiktekstEnkel,
|
||||
RiktekstAksel,
|
||||
RiktekstDsArtikkel,
|
||||
RiktekstKomponent,
|
||||
RiktekstTabell,
|
||||
RiktekstPrinsipp,
|
||||
|
||||
/* Moduler */
|
||||
/* Tabellv2, */
|
||||
DoDont,
|
||||
doDontBlock,
|
||||
Bilde,
|
||||
HeroBilde,
|
||||
Alert,
|
||||
Kode,
|
||||
RelatertInnhold,
|
||||
Innholdskort,
|
||||
introKomponent,
|
||||
Props,
|
||||
Accordion,
|
||||
SpesialSeksjon,
|
||||
Video,
|
||||
Tips,
|
||||
Tastatur,
|
||||
KodeEksempler,
|
||||
TokenRef,
|
||||
];
|
||||
|
||||
export default v2Blocks;
|
||||
@@ -1,55 +0,0 @@
|
||||
// Usikker på om skal være med videre
|
||||
|
||||
import { FileContent } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Innholdskort",
|
||||
name: "innholdskort",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Tittel",
|
||||
name: "title",
|
||||
type: "string",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Innholdskort må ha en beskrivende tittel"),
|
||||
},
|
||||
{
|
||||
title: "Lenke til prinsipp",
|
||||
name: "lenke",
|
||||
type: "reference",
|
||||
to: [{ type: "aksel_prinsipp" }],
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Innholdskort må ha en lenke"),
|
||||
},
|
||||
{
|
||||
title: "Innhold",
|
||||
description: "Ikke bruk lenker inne i selve kortet",
|
||||
name: "body",
|
||||
type: "riktekst_enkel",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Innholdskort må ha noe beskrivende innhold"),
|
||||
},
|
||||
],
|
||||
validation: (Rule) =>
|
||||
Rule.custom((_, { document }) => {
|
||||
if (!document?.prinsipp?.hovedside) {
|
||||
return "Innholdskort kan bare brukes på 'hovedsiden' til prinsippet";
|
||||
}
|
||||
|
||||
return true;
|
||||
}),
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
},
|
||||
prepare(selection) {
|
||||
return {
|
||||
title: selection?.title,
|
||||
subtitle: `Innholdskort`,
|
||||
media: () => <FileContent />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,45 +0,0 @@
|
||||
import { Home } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Intro",
|
||||
name: "intro_komponent",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Intro-tekst",
|
||||
name: "body",
|
||||
type: "riktekst_enkel",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Komponentintro må ha en intro"),
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
name: "brukes_til",
|
||||
title: "Egnet til å:",
|
||||
of: [{ type: "string" }],
|
||||
validation: (Rule) => Rule.required().min(1),
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
name: "brukes_ikke_til",
|
||||
title: "Vurder noe annet: (optional)",
|
||||
of: [{ type: "string" }],
|
||||
},
|
||||
],
|
||||
options: {
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
},
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
},
|
||||
prepare() {
|
||||
return {
|
||||
title: "Komponent-intro",
|
||||
media: () => <Home />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
import { Ruler } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Kode-eksempler",
|
||||
name: "kode_eksempler",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "tittel",
|
||||
name: "title",
|
||||
type: "string",
|
||||
initialValue: "Kode-eksempler",
|
||||
readOnly: true,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
title: "Standalone-eksempel",
|
||||
description: "Vis bare et spesfikt eksempel",
|
||||
name: "standalone",
|
||||
type: "boolean",
|
||||
initialValue: false,
|
||||
},
|
||||
{
|
||||
title: "Eksempel-navn",
|
||||
name: "dir",
|
||||
type: "reference",
|
||||
to: [{ type: "kode_eksempler_fil" }],
|
||||
options: {
|
||||
filter: "dir == true",
|
||||
},
|
||||
hidden: ({ parent }) => parent.standalone,
|
||||
},
|
||||
{
|
||||
title: "Installasjon-snippet",
|
||||
name: "filnavn",
|
||||
type: "reference",
|
||||
to: [{ type: "kode_eksempler_fil" }],
|
||||
options: {
|
||||
filter: "dir != true",
|
||||
},
|
||||
hidden: ({ parent }) => !parent.standalone,
|
||||
},
|
||||
],
|
||||
icon: () => <Ruler />,
|
||||
preview: {
|
||||
select: {
|
||||
standalone: "standalone",
|
||||
filnavn: "filnavn.title",
|
||||
dir: "dir.title",
|
||||
},
|
||||
prepare({ standalone, filnavn, dir }) {
|
||||
return {
|
||||
title: "Komponent-demo",
|
||||
subtitle: standalone ? filnavn?.replace(".tsx", "") ?? "" : dir ?? "",
|
||||
media: () => <Ruler />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
// MIGRERT
|
||||
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Kode",
|
||||
name: "kode",
|
||||
type: "object",
|
||||
icon: () => <div>{`<>`}</div>,
|
||||
fields: [
|
||||
{
|
||||
name: "code",
|
||||
title: "Kode",
|
||||
type: "code",
|
||||
hidden: ({ parent }) => parent?.variant,
|
||||
validation: (Rule) => Rule.required(),
|
||||
options: {
|
||||
languageAlternatives: [
|
||||
{ value: "js", title: "Javascript" },
|
||||
{ value: "jsx", title: "JSX" },
|
||||
{ value: "html", title: "HTML" },
|
||||
{ value: "css", title: "CSS" },
|
||||
{ value: "less", title: "Less" },
|
||||
{ value: "terminal", title: "Terminal/Bash" },
|
||||
{ value: "terminal", title: "Standard" },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
code: "code",
|
||||
ref: "ref.title",
|
||||
},
|
||||
prepare: ({ code, ref }) => ({
|
||||
title: code ? `${code?.code?.slice(0, 50)}...` : ref ? ref : "Kode",
|
||||
subtitle: "kode",
|
||||
media: () => <div>{`</>`}</div>,
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
// MIGRERT
|
||||
|
||||
import { List } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Props",
|
||||
name: "props_seksjon",
|
||||
type: "object",
|
||||
icon: List,
|
||||
fields: [
|
||||
{
|
||||
title: "Tittel (h2)",
|
||||
name: "title",
|
||||
type: "string",
|
||||
initialValue: "Props",
|
||||
readOnly: true,
|
||||
},
|
||||
{
|
||||
title: "Props",
|
||||
type: "array",
|
||||
name: "komponenter",
|
||||
of: [
|
||||
{
|
||||
title: "Komponent",
|
||||
type: "object",
|
||||
name: "komponent",
|
||||
fields: [
|
||||
{
|
||||
title: "Komponent navn",
|
||||
description: "Slik man ville brukt den, eks Accordion.Item",
|
||||
type: "string",
|
||||
name: "title",
|
||||
},
|
||||
{
|
||||
title: "Bruker komponenten OverridableComponent API-et",
|
||||
type: "boolean",
|
||||
name: "overridable",
|
||||
initialValue: false,
|
||||
},
|
||||
{
|
||||
name: "propref",
|
||||
title: "Komponent referanse",
|
||||
type: "reference",
|
||||
to: [{ type: "ds_props" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
prepare() {
|
||||
return {
|
||||
title: "Props",
|
||||
media: () => <List />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,79 +0,0 @@
|
||||
// MIGRERT
|
||||
|
||||
import { allDocumentTypes } from "../../config";
|
||||
import { Link } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
name: "relatert_innhold",
|
||||
title: "Relatert Innhold",
|
||||
type: "object",
|
||||
icon: Link,
|
||||
fields: [
|
||||
{
|
||||
title: "Lenker til innhold",
|
||||
name: "lenker",
|
||||
type: "array",
|
||||
validation: (Rule) =>
|
||||
Rule.required().max(4).error("Kan ha maks 4 relaterte lenker"),
|
||||
of: [
|
||||
{
|
||||
title: "Lenke",
|
||||
name: "lenke",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Tittel",
|
||||
name: "title",
|
||||
type: "string",
|
||||
validation: (Rule) =>
|
||||
Rule.required()
|
||||
.max(40)
|
||||
.error("Tittelen kan være på maks 35 tegn"),
|
||||
},
|
||||
{
|
||||
title: "Intern side i Sanity",
|
||||
name: "intern",
|
||||
type: "boolean",
|
||||
option: {
|
||||
layout: "checkbox",
|
||||
},
|
||||
validation: (Rule) => Rule.required(),
|
||||
initialValue: false,
|
||||
},
|
||||
{
|
||||
title: "Lenke til Intern sanity-side",
|
||||
name: "intern_lenke",
|
||||
type: "reference",
|
||||
to: [...allDocumentTypes.map((x) => ({ type: x }))],
|
||||
hidden: ({ parent }) => !parent?.intern,
|
||||
},
|
||||
{
|
||||
title: "Lenke til ekstern side",
|
||||
name: "ekstern_link",
|
||||
type: "url",
|
||||
hidden: ({ parent }) => parent?.intern,
|
||||
},
|
||||
{
|
||||
title: "Linker til et eksternt domene",
|
||||
description:
|
||||
"Sett denne hvis lenken går til en side utenfor aksel.nav.no",
|
||||
name: "ekstern_domene",
|
||||
type: "boolean",
|
||||
initialValue: false,
|
||||
hidden: ({ parent }) => parent?.intern,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
links: "links",
|
||||
},
|
||||
prepare(s) {
|
||||
return { title: "Relatert innhold kort", media: () => <Link /> };
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,269 +0,0 @@
|
||||
import "@navikt/ds-css?raw";
|
||||
import "@navikt/ds-css-internal?raw";
|
||||
import { ExternalLink, FileContent, Link } from "@navikt/ds-icons";
|
||||
import { BodyLong, Heading } from "@navikt/ds-react/cjs";
|
||||
import { KBD } from "@sanity/ui";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { allDocumentTypes } from "../../config";
|
||||
|
||||
export const TitleRenderer = (props, size, level) => (
|
||||
<Heading size={size} level={level}>
|
||||
{props.children}
|
||||
</Heading>
|
||||
);
|
||||
|
||||
export const ScCode = styled.code`
|
||||
color: var(--a-deepblue-500);
|
||||
background-color: var(--a-deepblue-50);
|
||||
border-radius: 6px;
|
||||
font-size: 1rem;
|
||||
padding: 2px 0.5rem;
|
||||
`;
|
||||
|
||||
export const styles = [
|
||||
{
|
||||
title: "Avsnitt",
|
||||
value: "normal",
|
||||
blockEditor: {
|
||||
render: (props) => <BodyLong>{props.children}</BodyLong>,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const block = {
|
||||
title: "Block",
|
||||
type: "block",
|
||||
styles: [...styles],
|
||||
lists: [
|
||||
{ title: "Bullet", value: "bullet" },
|
||||
{ title: "Numbered", value: "number" },
|
||||
],
|
||||
// Marks let you mark up inline text in the block editor.
|
||||
marks: {
|
||||
// Decorators usually describe a single property – e.g. a typographic
|
||||
// preference or highlighting by editors.
|
||||
decorators: [
|
||||
{ title: "Strong", value: "strong" },
|
||||
{ title: "Emphasis", value: "em" },
|
||||
{
|
||||
title: "Code",
|
||||
value: "code",
|
||||
blockEditor: {
|
||||
render: (props) => <ScCode>{props.children}</ScCode>,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "KBD",
|
||||
value: "kbd",
|
||||
blockEditor: {
|
||||
icon: () => <div>KBD</div>,
|
||||
render: (props) => (
|
||||
<KBD padding={[1, 1, 2]} style={{ verticalAlign: "super" }}>
|
||||
{props.children}
|
||||
</KBD>
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
// Annotations can be any object structure – e.g. a link or a footnote.
|
||||
annotations: [
|
||||
{
|
||||
title: "Link til side i sanity",
|
||||
name: "internalLink",
|
||||
type: "object",
|
||||
blockEditor: {
|
||||
icon: () => <Link />,
|
||||
},
|
||||
options: {
|
||||
modal: {
|
||||
type: "dialog",
|
||||
width: "medium", // 'small' | 'medium' | 'large' | 'full'
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
title: "Reference",
|
||||
name: "reference",
|
||||
type: "reference",
|
||||
to: [
|
||||
...allDocumentTypes.map((doc) => ({
|
||||
type: doc,
|
||||
})),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Lenke",
|
||||
name: "link",
|
||||
type: "object",
|
||||
blockEditor: {
|
||||
icon: () => <ExternalLink />,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
title: "URL",
|
||||
name: "href",
|
||||
type: "url",
|
||||
validation: (Rule) =>
|
||||
Rule.uri({
|
||||
scheme: ["https", "mailto", "tel"],
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "Åpne siden i ny tab",
|
||||
description:
|
||||
"Vi anbefaler å ikke åpne lenker i ny fane slik at brukeren selv kan styre det om ønsket.",
|
||||
name: "blank",
|
||||
type: "boolean",
|
||||
initialValue: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const headingStyles = [
|
||||
...block.styles,
|
||||
{
|
||||
title: "H2",
|
||||
value: "h2",
|
||||
blockEditor: {
|
||||
render: (props) => (
|
||||
<Heading as="span" size="medium">
|
||||
{props.children}
|
||||
</Heading>
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "H3",
|
||||
value: "h3",
|
||||
blockEditor: {
|
||||
render: (props) => (
|
||||
<Heading as="span" size="small">
|
||||
{props.children}
|
||||
</Heading>
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "H4",
|
||||
value: "h4",
|
||||
blockEditor: {
|
||||
render: (props) => (
|
||||
<Heading as="span" size="xsmall">
|
||||
{props.children}
|
||||
</Heading>
|
||||
),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const Riktekst = (type: "aksel" | "ds" | "komponent" | "prinsipp") => {
|
||||
const fields: string[] = [];
|
||||
const standard = [
|
||||
"relatert_innhold",
|
||||
"bilde",
|
||||
"kode",
|
||||
"tips",
|
||||
"do_dont",
|
||||
"accordion",
|
||||
"alert",
|
||||
"tabell_v2",
|
||||
"video",
|
||||
];
|
||||
|
||||
const comp = [
|
||||
"props_seksjon",
|
||||
"tastatur_modul",
|
||||
"kode_eksempler",
|
||||
"token_ref",
|
||||
];
|
||||
|
||||
const ds_artikkel = ["spesial_seksjon"];
|
||||
|
||||
fields.push(...standard);
|
||||
|
||||
switch (type) {
|
||||
case "komponent":
|
||||
fields.push(...comp);
|
||||
break;
|
||||
case "ds":
|
||||
fields.push(...ds_artikkel);
|
||||
break;
|
||||
case "prinsipp":
|
||||
fields.push("innholdskort");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const uniq = fields.filter((item, pos, self) => self.indexOf(item) === pos);
|
||||
|
||||
return [
|
||||
{
|
||||
...block,
|
||||
styles: [...headingStyles],
|
||||
},
|
||||
...uniq.map((x) => ({ type: x })),
|
||||
];
|
||||
};
|
||||
|
||||
export const RiktekstAksel = {
|
||||
title: "Riktekst Aksel",
|
||||
name: "riktekst_aksel",
|
||||
type: "array",
|
||||
of: Riktekst("aksel"),
|
||||
icon: () => <FileContent />,
|
||||
};
|
||||
|
||||
export const RiktekstPrinsipp = {
|
||||
title: "Riktekst Aksel",
|
||||
name: "riktekst_prinsipp",
|
||||
type: "array",
|
||||
of: Riktekst("prinsipp"),
|
||||
icon: () => <FileContent />,
|
||||
};
|
||||
|
||||
export const RiktekstDsArtikkel = {
|
||||
title: "Riktekst Aksel",
|
||||
name: "riktekst_ds_artikkel",
|
||||
type: "array",
|
||||
of: Riktekst("ds"),
|
||||
icon: () => <FileContent />,
|
||||
};
|
||||
|
||||
export const RiktekstKomponent = {
|
||||
title: "Riktekst Aksel",
|
||||
name: "riktekst_komponent",
|
||||
type: "array",
|
||||
of: Riktekst("komponent"),
|
||||
icon: () => <FileContent />,
|
||||
};
|
||||
|
||||
export const RiktekstTabell = {
|
||||
title: "Riktekst",
|
||||
name: "riktekst_tabell",
|
||||
type: "array",
|
||||
of: [
|
||||
{
|
||||
...block,
|
||||
marks: {
|
||||
...block.marks,
|
||||
annotations: block.marks.annotations.filter(
|
||||
(x) => x.name !== "internalLink"
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const RiktekstEnkel = {
|
||||
title: "Riktekst",
|
||||
name: "riktekst_enkel",
|
||||
type: "array",
|
||||
of: [block],
|
||||
};
|
||||
@@ -1,44 +0,0 @@
|
||||
import { Star } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Unik Sidemodul",
|
||||
type: "object",
|
||||
name: "spesial_seksjon",
|
||||
icon: Star,
|
||||
validation: (Rule) => Rule.required(),
|
||||
fields: [
|
||||
{
|
||||
title: "Modul",
|
||||
name: "modul",
|
||||
type: "string",
|
||||
options: {
|
||||
list: [
|
||||
{ title: "Token kategori", value: "token_kategori" },
|
||||
{ title: "Ikonsøk", value: "ikonsok" },
|
||||
{ title: "Komponentoversikt", value: "komponentoversikt" },
|
||||
],
|
||||
layout: "radio",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Token kategori",
|
||||
type: "reference",
|
||||
name: "token_ref",
|
||||
hidden: ({ parent }) => parent.modul !== "token_kategori",
|
||||
to: [{ type: "token_kategori" }],
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
modul: "modul",
|
||||
},
|
||||
prepare(s) {
|
||||
return {
|
||||
title: s.modul,
|
||||
subtitle: "Unik Sidemodul",
|
||||
media: () => <Star />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
import { Data } from "@navikt/ds-icons";
|
||||
|
||||
export const tmpTabell = {
|
||||
type: "object",
|
||||
name: "tabell_v2",
|
||||
title: "Tabell",
|
||||
icon: Data,
|
||||
fields: [{ type: "array", name: "rows", of: [{ type: "tableRow" }] }],
|
||||
preview: {
|
||||
select: {
|
||||
rows: "rows",
|
||||
},
|
||||
prepare(selection) {
|
||||
const { rows } = selection;
|
||||
return {
|
||||
title: "Tabell",
|
||||
subtitle: rows && `Rader: ${rows.length}`,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const tmpTabellRow = {
|
||||
type: "object",
|
||||
name: "tableRow",
|
||||
title: "Rad",
|
||||
fields: [{ type: "array", name: "cells", of: [{ type: "string" }] }],
|
||||
preview: {
|
||||
select: {
|
||||
cells: "cells",
|
||||
},
|
||||
prepare(selection) {
|
||||
const { cells } = selection;
|
||||
return {
|
||||
title: cells ? cells.join(" | ") : "cell",
|
||||
media: Data,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
title: "Tastatur",
|
||||
name: "tastatur_modul",
|
||||
type: "object",
|
||||
icon: () => <div>KBD</div>,
|
||||
fields: [
|
||||
{
|
||||
type: "array",
|
||||
name: "tastatur",
|
||||
title: "Tastatur key + action",
|
||||
of: [
|
||||
{
|
||||
type: "object",
|
||||
name: "keys",
|
||||
fields: [
|
||||
{ type: "string", name: "key" },
|
||||
{ type: "string", name: "action" },
|
||||
],
|
||||
validation: (Rule) => Rule.required(),
|
||||
options: {
|
||||
columns: "2",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
import { toPlainText } from "@/lib";
|
||||
import { LightBulb } from "@navikt/ds-icons";
|
||||
import React from "react";
|
||||
|
||||
export default {
|
||||
name: "tips",
|
||||
title: "Tips/Feedback",
|
||||
type: "object",
|
||||
icon: LightBulb,
|
||||
fields: [
|
||||
{
|
||||
title: "Feedback",
|
||||
description: "Endrer modul-variant",
|
||||
name: "eksperiment",
|
||||
type: "boolean",
|
||||
initialValue: false,
|
||||
},
|
||||
{
|
||||
title: "Innhold",
|
||||
name: "body",
|
||||
type: "riktekst_enkel",
|
||||
validation: (Rule) =>
|
||||
Rule.required().error("Tips-modul må ha noe innhold"),
|
||||
},
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
body: "body",
|
||||
eksperiment: "eksperiment",
|
||||
},
|
||||
prepare(selection) {
|
||||
return {
|
||||
title: toPlainText(selection?.body ?? []) ?? "",
|
||||
subtitle: selection.eksperiment ? "Feedback (tips)" : "Tips",
|
||||
media: () => <LightBulb />,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Table } from "@navikt/ds-icons";
|
||||
|
||||
export default {
|
||||
name: "token_ref",
|
||||
title: "Tokens referanse",
|
||||
type: "reference",
|
||||
to: [{ type: "token_kategori" }],
|
||||
validation: (Rule) => Rule.required(),
|
||||
icon: Table,
|
||||
};
|
||||
@@ -1,71 +0,0 @@
|
||||
import { VideoRoom } from "@navikt/ds-icons";
|
||||
|
||||
export default {
|
||||
name: "video",
|
||||
title: "Video",
|
||||
type: "object",
|
||||
icon: VideoRoom,
|
||||
fields: [
|
||||
{
|
||||
name: "bruk_embed",
|
||||
title: "Bruk Microsoft-streams embed",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
name: "embed",
|
||||
title: "Iframe",
|
||||
description:
|
||||
"Trykk share og legg inn iframe her fra Microsoft-streams. Husk å velge størrelse og slå av autplay og show info!",
|
||||
type: "text",
|
||||
rows: 3,
|
||||
hidden: ({ parent }) => !parent?.bruk_embed,
|
||||
},
|
||||
{
|
||||
name: "webm",
|
||||
title: "Video i WebM format",
|
||||
description: "Vi anbefaler å bruke Webm formatet om mulig!",
|
||||
type: "file",
|
||||
options: {
|
||||
accept: "video/webm",
|
||||
},
|
||||
hidden: ({ parent }) => parent?.bruk_embed,
|
||||
},
|
||||
{
|
||||
name: "fallback",
|
||||
title: "Video i Mp4 format (fallback)",
|
||||
type: "file",
|
||||
options: {
|
||||
accept: "video/mp4",
|
||||
},
|
||||
hidden: ({ parent }) => parent?.bruk_embed,
|
||||
},
|
||||
{
|
||||
name: "alt",
|
||||
title: "Alt tekst for skjermlesere",
|
||||
type: "string",
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
},
|
||||
validation: (Rule) => Rule.required(),
|
||||
},
|
||||
{
|
||||
name: "caption",
|
||||
title: "Videotekst",
|
||||
description: "Kort beskrivelse som vises rett under videon",
|
||||
type: "string",
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "transkripsjon",
|
||||
title: "Transkripsjon",
|
||||
description:
|
||||
"Hvis videoen inneholder lyd, anbelfaler vi å skrive en transkripsjon som kan leses under videoen.",
|
||||
type: "text",
|
||||
options: {
|
||||
isHighlighted: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,47 +0,0 @@
|
||||
import createSchema from "part:@sanity/base/schema-creator";
|
||||
import schemaTypes from "all:part:@sanity/base/schema-type";
|
||||
|
||||
/* Schemas */
|
||||
/* Documents */
|
||||
import editors from "./documents/editors";
|
||||
import redirect from "./documents/redirects";
|
||||
import KodeEksempler from "./documents/kode-eksempler";
|
||||
import Tokens from "./documents/tokens";
|
||||
import Props from "./documents/props";
|
||||
import DsFrontpage from "./documents/ds-frontpage";
|
||||
import DsCompTemplate from "./documents/component-template";
|
||||
import KompArtikkel from "./documents/komponent";
|
||||
import AkselTema from "./documents/tema";
|
||||
import AkselArtikkel from "./documents/aksel-artikkel";
|
||||
import DsArtikkel from "./documents/ds-artikkel";
|
||||
import Blogg from "./documents/blogg";
|
||||
import Prinsipp from "./documents/prinsipp";
|
||||
import Standalone from "./documents/standalone";
|
||||
import Navigation, { ds_header_heading } from "./documents/navigation";
|
||||
|
||||
import v2Blocks from "./modules";
|
||||
|
||||
export default createSchema({
|
||||
name: "default",
|
||||
types: schemaTypes.concat([
|
||||
...v2Blocks,
|
||||
editors,
|
||||
redirect,
|
||||
Navigation,
|
||||
ds_header_heading,
|
||||
KompArtikkel,
|
||||
|
||||
KodeEksempler,
|
||||
Tokens,
|
||||
Props,
|
||||
DsFrontpage,
|
||||
DsCompTemplate,
|
||||
DsArtikkel,
|
||||
|
||||
AkselArtikkel,
|
||||
Blogg,
|
||||
AkselTema,
|
||||
Prinsipp,
|
||||
Standalone,
|
||||
]),
|
||||
});
|
||||
@@ -1,48 +0,0 @@
|
||||
const exportDataset = require("@sanity/export");
|
||||
const sanityClient = require("@sanity/client");
|
||||
const sanityToken = process.env.SANITY_PREVIEW_TOKEN;
|
||||
const SanityConfig = require("../sanity.json");
|
||||
|
||||
if (!sanityToken) {
|
||||
throw new Error("Could not find token from SANITY_PREVIEW_TOKEN");
|
||||
}
|
||||
|
||||
const client = sanityClient({
|
||||
projectId: SanityConfig.api.projectId,
|
||||
dataset: SanityConfig.api.dataset,
|
||||
apiVersion: "2020-06-19",
|
||||
token: sanityToken,
|
||||
useCdn: false,
|
||||
});
|
||||
|
||||
const main = async () => {
|
||||
const time = Date.now();
|
||||
await exportDataset({
|
||||
// Instance of @sanity/client configured to correct project ID and dataset
|
||||
client: client,
|
||||
|
||||
// Name of dataset to export
|
||||
dataset: "production",
|
||||
|
||||
// Path to write tar.gz-archive file to, or `-` for stdout
|
||||
outputPath: `backup-${time}.tar.gz`,
|
||||
|
||||
// Whether or not to export assets. Note that this operation is currently slightly lossy;
|
||||
// metadata stored on the asset document itself (original filename, for instance) might be lost
|
||||
// Default: `true`
|
||||
assets: true,
|
||||
|
||||
// Exports documents only, without downloading or rewriting asset references
|
||||
// Default: `false`
|
||||
raw: false,
|
||||
|
||||
// Whether or not to export drafts
|
||||
// Default: `true`
|
||||
drafts: true,
|
||||
|
||||
// Run 12 concurrent asset downloads
|
||||
assetConcurrency: 12,
|
||||
});
|
||||
};
|
||||
|
||||
main();
|
||||
@@ -1,27 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const SanityConfig = require("../sanity.json");
|
||||
const sanityClient = require("@sanity/client");
|
||||
|
||||
const client = sanityClient({
|
||||
projectId: SanityConfig.api.projectId,
|
||||
dataset: SanityConfig.api.dataset,
|
||||
apiVersion: "2021-03-25",
|
||||
});
|
||||
|
||||
/* const fetchDocuments = () => client.fetch(`*[_id in path('_.groups.*')]`); */
|
||||
/* .then((res) => userStore.getUsers(res))
|
||||
.then((users) => users.filter((user) => user.isCurrentUser)); */
|
||||
|
||||
/* const fetchDocument = async () =>
|
||||
client.fetch(`*[_id == "drafts.bc1fd317-02bd-4c5b-bf93-703816aeb0c7"]`); */
|
||||
|
||||
const runDemo = async () => {
|
||||
const res = await client.fetch(`*[_type == "aksel_artikkel"]`);
|
||||
console.log(res.length);
|
||||
/* await client.create({}).then(() => console.log("ok")); */
|
||||
};
|
||||
|
||||
runDemo().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,57 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
import sanityClient from "part:@sanity/base/client";
|
||||
|
||||
const client = sanityClient.withConfig({
|
||||
apiVersion: "2021-08-21",
|
||||
dataset: "production",
|
||||
});
|
||||
|
||||
/** Script for å gjøre diverse oppgaver på dataset. Endre linje 15 og 20 med ønsket config
|
||||
* https://www.sanity.io/schemas/rename-a-field-across-documents-5cd6f5f0
|
||||
* Husk å kjøre backup med sanity dataset export først!
|
||||
* run: sanity exec scripts/renameField.js --with-user-token
|
||||
*/
|
||||
|
||||
const fetchDocuments = () => client.fetch(`*[under_arbeid != null]`);
|
||||
|
||||
const buildPatches = (docs) =>
|
||||
docs.map((doc) => ({
|
||||
id: doc._id,
|
||||
patch: {
|
||||
unset: ["under_arbeid"],
|
||||
ifRevisionID: doc._rev,
|
||||
},
|
||||
}));
|
||||
|
||||
const createTransaction = (patches) =>
|
||||
patches.reduce(
|
||||
(tx, patch) => tx.patch(patch.id, patch.patch),
|
||||
client.transaction()
|
||||
);
|
||||
|
||||
const commitTransaction = (tx) => tx.commit();
|
||||
|
||||
const migrateNextBatch = async () => {
|
||||
const documents = await fetchDocuments();
|
||||
console.log(documents.length);
|
||||
return;
|
||||
const patches = buildPatches(documents);
|
||||
if (patches.length === 0) {
|
||||
console.log("No more documents to migrate!");
|
||||
return null;
|
||||
}
|
||||
console.log(
|
||||
`Migrating batch:\n %s`,
|
||||
patches
|
||||
.map((patch) => `${patch.id} => ${JSON.stringify(patch.patch)}`)
|
||||
.join("\n")
|
||||
);
|
||||
const transaction = createTransaction(patches);
|
||||
await commitTransaction(transaction);
|
||||
return migrateNextBatch();
|
||||
};
|
||||
|
||||
migrateNextBatch().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
Files placed here will be served by the Sanity server under the `/static`-prefix
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg
|
||||
width="269px"
|
||||
height="169px"
|
||||
viewBox="0 0 269 169"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
<title>NAV logo / rød</title>
|
||||
<defs>
|
||||
<polygon
|
||||
id="path-1"
|
||||
points="22.407 43.4168 22.407 0.6878 0.5635 0.6878 0.5635 43.4168 22.407 43.4168"
|
||||
></polygon>
|
||||
</defs>
|
||||
<g
|
||||
id="Modul-forslag"
|
||||
stroke="none"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
>
|
||||
<g id="NAV-logo-/-rød">
|
||||
<g id="Page-1-Copy">
|
||||
<path
|
||||
d="M125.3091,168.942 C78.6681,168.942 40.8491,131.125 40.8491,84.477 C40.8491,37.824 78.6681,0 125.3091,0 C171.9671,0 209.7901,37.824 209.7901,84.477 C209.7901,131.125 171.9671,168.942 125.3091,168.942 Z"
|
||||
id="Fill-1"
|
||||
fill="#C30000"
|
||||
></path>
|
||||
<polygon
|
||||
id="Fill-3"
|
||||
fill="#C30000"
|
||||
points="0 121.3588 17.265 78.6298 33.854 78.6298 16.611 121.3588"
|
||||
></polygon>
|
||||
<polygon
|
||||
id="Fill-5"
|
||||
fill="#C30000"
|
||||
points="213.044 121.3588 230.088 78.6298 239.132 78.6298 222.089 121.3588"
|
||||
></polygon>
|
||||
<g id="Group-9" transform="translate(246.000000, 77.942000)">
|
||||
<mask id="mask-2" fill="white">
|
||||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<g id="Clip-8"></g>
|
||||
<polygon
|
||||
id="Fill-7"
|
||||
fill="#C30000"
|
||||
mask="url(#mask-2)"
|
||||
points="0.5635 43.4168 17.6045 0.6878 22.4075 0.6878 5.3645 43.4168"
|
||||
></polygon>
|
||||
</g>
|
||||
<path
|
||||
d="M197.3604,78.6298 L182.3444,78.6298 C182.3444,78.6298 181.3094,78.6298 180.9434,79.5438 L172.6334,104.9828 L164.3304,79.5438 C163.9644,78.6298 162.9234,78.6298 162.9234,78.6298 L134.0514,78.6298 C133.4264,78.6298 132.9024,79.1518 132.9024,79.7728 L132.9024,88.4118 C132.9024,81.5588 125.6104,78.6298 121.3404,78.6298 C111.7784,78.6298 105.3774,84.9278 103.3844,94.5028 C103.2764,88.1508 102.7484,85.8748 101.0374,83.5438 C100.2514,82.4018 99.1154,81.4418 97.8784,80.6478 C95.3314,79.1558 93.0444,78.6298 88.1294,78.6298 L82.3584,78.6298 C82.3584,78.6298 81.3154,78.6298 80.9474,79.5438 L75.6964,92.5568 L75.6964,79.7728 C75.6964,79.1518 75.1764,78.6298 74.5524,78.6298 L61.1984,78.6298 C61.1984,78.6298 60.1674,78.6298 59.7924,79.5438 L54.3334,93.0748 C54.3334,93.0748 53.7884,94.4278 55.0344,94.4278 L60.1674,94.4278 L60.1674,120.2118 C60.1674,120.8518 60.6714,121.3588 61.3144,121.3588 L74.5524,121.3588 C75.1764,121.3588 75.6964,120.8518 75.6964,120.2118 L75.6964,94.4278 L80.8564,94.4278 C83.8174,94.4278 84.4444,94.5088 85.5964,95.0458 C86.2904,95.3078 86.9154,95.8378 87.2564,96.4488 C87.9544,97.7628 88.1294,99.3408 88.1294,103.9938 L88.1294,120.2118 C88.1294,120.8518 88.6434,121.3588 89.2784,121.3588 L101.9664,121.3588 C101.9664,121.3588 103.4004,121.3588 103.9674,119.9428 L106.7794,112.9928 C110.5184,118.2298 116.6724,121.3588 124.3204,121.3588 L125.9914,121.3588 C125.9914,121.3588 127.4344,121.3588 128.0054,119.9428 L132.9024,107.8148 L132.9024,120.2118 C132.9024,120.8518 133.4264,121.3588 134.0514,121.3588 L147.0034,121.3588 C147.0034,121.3588 148.4324,121.3588 149.0064,119.9428 C149.0064,119.9428 154.1864,107.0818 154.2064,106.9848 L154.2144,106.9848 C154.4134,105.9148 153.0614,105.9148 153.0614,105.9148 L148.4384,105.9148 L148.4384,83.8468 L162.9834,119.9428 C163.5514,121.3588 164.9834,121.3588 164.9834,121.3588 L180.2844,121.3588 C180.2844,121.3588 181.7244,121.3588 182.2924,119.9428 L198.4174,80.0138 C198.9754,78.6298 197.3604,78.6298 197.3604,78.6298 L197.3604,78.6298 Z M132.9024,105.9148 L124.2024,105.9148 C120.7394,105.9148 117.9224,103.1108 117.9224,99.6438 C117.9224,96.1828 120.7394,93.3608 124.2024,93.3608 L126.6354,93.3608 C130.0894,93.3608 132.9024,96.1828 132.9024,99.6438 L132.9024,105.9148 Z"
|
||||
id="Fill-10"
|
||||
fill="#FEFEFE"
|
||||
></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"include": [
|
||||
"./node_modules/@sanity/base/types/**/*.ts",
|
||||
"../node_modules/@sanity/base/types/**/*.ts",
|
||||
"./**/*.ts",
|
||||
"./**/*.tsx",
|
||||
"./**/*.js",
|
||||
"./**/*.jsx"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"jsx": "react",
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"baseUrl": ".",
|
||||
"resolveJsonModule": true,
|
||||
"paths": {
|
||||
"@/lib": ["lib/index.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
const {
|
||||
schemaExtractor,
|
||||
generateSchemaTypes,
|
||||
} = require("@sanity-codegen/schema-codegen");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
async function main() {
|
||||
const normalizedSchema = await schemaExtractor({
|
||||
schemaPath: "./schemas/schema.ts",
|
||||
babelOptions: {
|
||||
plugins: [
|
||||
[
|
||||
"mock-imports",
|
||||
{
|
||||
redirects: [
|
||||
{
|
||||
pattern: "@/lib",
|
||||
location: path.resolve(__dirname, "./lib/index.ts"),
|
||||
},
|
||||
{
|
||||
pattern: "@navikt/ds-css",
|
||||
location: path.resolve(__dirname, "./schema-mock.tsx"),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const typescriptSource = await generateSchemaTypes({
|
||||
normalizedSchema,
|
||||
generateTypeName: (x) => {
|
||||
return x === "code" || x === "powerTable" ? "any" : x;
|
||||
},
|
||||
});
|
||||
|
||||
await fs.promises.writeFile(
|
||||
"../website/lib/types/schema.d.ts",
|
||||
`${typescriptSource}\nexport default SanityT;\n`.replace(
|
||||
"declare namespace Sanity",
|
||||
"declare namespace SanityT"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -1,19 +0,0 @@
|
||||
import React from "react";
|
||||
import { WebPreviewWrapper } from "./WebPreviewWrapper";
|
||||
|
||||
export const ComponentPageWebPreview = (ctx: any) => {
|
||||
const slug = ctx.document.displayed?.slug?.current;
|
||||
|
||||
if (!slug) {
|
||||
return <div>Side må ha en url/slug før den kan forhåndsvises...</div>;
|
||||
}
|
||||
|
||||
const webUrl = "https://aksel.nav.no";
|
||||
const previewUrl = `/preview/${slug}`;
|
||||
const url =
|
||||
process.env.NODE_ENV === "production"
|
||||
? webUrl + previewUrl
|
||||
: `http://localhost:3000${previewUrl}`;
|
||||
|
||||
return <WebPreviewWrapper url={url} />;
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
import React from "react";
|
||||
import { WebPreviewWrapper } from "./WebPreviewWrapper";
|
||||
|
||||
export const KomponentPreview = (ctx: any) => {
|
||||
const slug = ctx.document.displayed?.slug?.current;
|
||||
|
||||
if (!slug) {
|
||||
return <div>Side må ha en url/slug før den kan forhåndsvises...</div>;
|
||||
}
|
||||
|
||||
const webUrl = "https://aksel.dev.nav.no";
|
||||
const previewUrl = `/preview/${slug}`;
|
||||
const url =
|
||||
process.env.NODE_ENV === "production"
|
||||
? webUrl + previewUrl
|
||||
: `http://localhost:3000${previewUrl}`;
|
||||
|
||||
return <WebPreviewWrapper url={url} dev />;
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
import React from "react";
|
||||
import { WebPreviewWrapper } from "./WebPreviewWrapper";
|
||||
|
||||
export const PageWebPreview = (ctx: any) => {
|
||||
const slug = ctx.document.displayed?.slug?.current;
|
||||
|
||||
if (!slug) {
|
||||
return <div>Side må ha en url/slug før den kan forhåndsvises...</div>;
|
||||
}
|
||||
|
||||
let previewUrl = `/preview/${slug}`;
|
||||
|
||||
const webUrl = "https://aksel.nav.no";
|
||||
const url =
|
||||
process.env.NODE_ENV === "production"
|
||||
? webUrl + previewUrl
|
||||
: `http://localhost:3000${previewUrl}`;
|
||||
|
||||
return <WebPreviewWrapper url={url} />;
|
||||
};
|
||||
@@ -1,80 +0,0 @@
|
||||
import { ExternalLink, Refresh } from "@navikt/ds-icons";
|
||||
import { Button, Detail, HelpText, Link } from "@navikt/ds-react";
|
||||
import { CopyToClipboard } from "@navikt/ds-react-internal";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
const StyledDiv = styled.div`
|
||||
iframe {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: left;
|
||||
`;
|
||||
|
||||
const ScTop = styled.div`
|
||||
padding: 0.25rem 0.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-bottom: 1px solid var(--card-shadow-outline-color);
|
||||
`;
|
||||
|
||||
export const WebPreviewWrapper = (props: { url: string; dev?: boolean }) => {
|
||||
const reloadIframe = () => {
|
||||
const el: HTMLIFrameElement | null =
|
||||
document &&
|
||||
(document.getElementById("preview-iframe") as HTMLIFrameElement);
|
||||
if (el) {
|
||||
el.src = el.src;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<ScTop>
|
||||
<Detail size="small" style={{ overflowX: "auto" }}>
|
||||
{props.url}
|
||||
</Detail>
|
||||
<div style={{ display: "flex", gap: "0.5rem", alignItems: "center" }}>
|
||||
{props.dev && (
|
||||
<Link href="https://doc.nais.io/device/">Krever NAISDevice</Link>
|
||||
)}
|
||||
<CopyToClipboard
|
||||
size="small"
|
||||
popoverText={"Kopierte lenke"}
|
||||
copyText={props.url}
|
||||
>
|
||||
Kopier
|
||||
</CopyToClipboard>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => reloadIframe()}
|
||||
icon={<Refresh title="refresh preview" />}
|
||||
/>
|
||||
<Button
|
||||
as="a"
|
||||
target="_blank"
|
||||
href={props.url}
|
||||
size="small"
|
||||
icon={<ExternalLink title="Åpne preview i nytt vindu" />}
|
||||
/>
|
||||
</div>
|
||||
</ScTop>
|
||||
<StyledDiv>
|
||||
<iframe id="preview-iframe" src={props.url} frameBorder={0} />
|
||||
</StyledDiv>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = function (config, options) {
|
||||
config.module.rules[0].exclude = {
|
||||
test: /(node_modules|bower_components)/,
|
||||
not: [/@radix-ui/, /@floating-ui/],
|
||||
};
|
||||
config.resolve.alias = {
|
||||
"@/lib": path.resolve(__dirname, "lib/index.ts"),
|
||||
};
|
||||
|
||||
return config;
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -21,6 +21,7 @@ import {
|
||||
TastaturModul,
|
||||
Tips,
|
||||
TokenTable,
|
||||
UuFeedback,
|
||||
Video,
|
||||
} from ".";
|
||||
|
||||
@@ -51,6 +52,7 @@ const serializers = {
|
||||
video: ({ node }) => <Video node={node} />,
|
||||
tips: ({ node }) => <Tips node={node} />,
|
||||
kode_eksempler: ({ node }) => <CodeExamples node={node} />,
|
||||
uufeedback: ({ node }) => <UuFeedback node={node} />,
|
||||
|
||||
block: ({ node, children }) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
@@ -188,18 +190,19 @@ const serializers = {
|
||||
}
|
||||
if (href && href.startsWith("mailto:")) {
|
||||
return (
|
||||
<NextLink
|
||||
href={href}
|
||||
passHref
|
||||
onClick={(e) =>
|
||||
logNav(
|
||||
"link",
|
||||
window.location.pathname,
|
||||
e.currentTarget.getAttribute("href")
|
||||
)
|
||||
}
|
||||
>
|
||||
<Link className="inline">{children}</Link>
|
||||
<NextLink href={href} passHref>
|
||||
<Link
|
||||
onClick={(e) =>
|
||||
logNav(
|
||||
"link",
|
||||
window.location.pathname,
|
||||
e.currentTarget.getAttribute("href")
|
||||
)
|
||||
}
|
||||
className="inline"
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
</NextLink>
|
||||
);
|
||||
}
|
||||
@@ -219,18 +222,19 @@ const serializers = {
|
||||
{children} <ExternalLink title="åpner lenken i ny fane" />
|
||||
</Link>
|
||||
) : (
|
||||
<NextLink
|
||||
href={href}
|
||||
passHref
|
||||
onClick={(e) =>
|
||||
logNav(
|
||||
"link",
|
||||
window.location.pathname,
|
||||
e.currentTarget.getAttribute("href")
|
||||
)
|
||||
}
|
||||
>
|
||||
<Link className="inline">{children}</Link>
|
||||
<NextLink href={href} passHref>
|
||||
<Link
|
||||
onClick={(e) =>
|
||||
logNav(
|
||||
"link",
|
||||
window.location.pathname,
|
||||
e.currentTarget.getAttribute("href")
|
||||
)
|
||||
}
|
||||
className="inline"
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
</NextLink>
|
||||
);
|
||||
},
|
||||
|
||||
Loaded 100 of 164 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user