diff --git a/TODO - Web payload project b/TODO - Web payload project deleted file mode 100644 index 656e134..0000000 --- a/TODO - Web payload project +++ /dev/null @@ -1,2 +0,0 @@ -# Web Paylod CMS testing - diff --git a/Todo - Updates.md b/Todo - Updates.md new file mode 100644 index 0000000..3696187 --- /dev/null +++ b/Todo - Updates.md @@ -0,0 +1,44 @@ +# Web Paylod CMS testing + + +## Comments on what to fix + +Hero should default to none, or we should try to remove it! + +Preview thumbnails for blocks ?? + +Can we get filler text in blocks as standard ? + +Why is slug defaulting to one letter? + +Fix corners and embed for video block + +Fix posts formatting to be better + +FAQ is not rendering answer text + +Where does the form submission text come from ??? + +Skicka förfrågan forms button needs to be updated + +A CTA block without Image + +Change the cookies banner to full screen width instead of rounded corners floating + +--- + +## Funktionalitet + +#### Subscribe to newsletters, connection to API GANL + +#### Få en offert (Lime, GANL, epost?) + +#### Forms generellt ? + +#### Matomo Tracking + +#### Cookies consent + +#### Lime forms integration + +#### Other code embedding \ No newline at end of file diff --git a/fix-ts-errors.sh b/fix-ts-errors.sh deleted file mode 100755 index 785465d..0000000 --- a/fix-ts-errors.sh +++ /dev/null @@ -1,243 +0,0 @@ -#!/bin/bash -# Run from the root of your fdweb2 project -set -e -cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)" - -echo "=== FD TypeScript Error Fix Script ===" -echo "" - -# ───────────────────────────────────────────────────────────── -# GROUP 1: Remove dead template block imports from RenderBlocks -# ───────────────────────────────────────────────────────────── -RENDER_BLOCKS="src/app/(frontend)/(pages)/[slug]/RenderBlocks.tsx" -# Try alternate path if first doesn't exist -if [ ! -f "$RENDER_BLOCKS" ]; then - RENDER_BLOCKS=$(find src -name "RenderBlocks.tsx" | head -1) -fi -echo "→ Fixing RenderBlocks.tsx at: $RENDER_BLOCKS" - -# Remove dead template block imports (leave all FD* blocks intact) -sed -i '' \ - '/^import { ArchiveBlock } from/d' \ - "$RENDER_BLOCKS" - -sed -i '' \ - '/^import { CallToActionBlock } from/d' \ - "$RENDER_BLOCKS" - -sed -i '' \ - '/^import { ContentBlock } from/d' \ - "$RENDER_BLOCKS" - -sed -i '' \ - '/^import { FormBlock } from/d' \ - "$RENDER_BLOCKS" - -sed -i '' \ - '/^import { MediaBlock } from/d' \ - "$RENDER_BLOCKS" - -# Remove corresponding entries from blockComponents object -sed -i '' \ - '/^ archive: ArchiveBlock,/d' \ - "$RENDER_BLOCKS" - -sed -i '' \ - '/^ cta: CallToActionBlock,/d' \ - "$RENDER_BLOCKS" - -sed -i '' \ - '/^ content: ContentBlock,/d' \ - "$RENDER_BLOCKS" - -sed -i '' \ - '/^ formBlock: FormBlock,/d' \ - "$RENDER_BLOCKS" - -sed -i '' \ - '/^ mediaBlock: MediaBlock,/d' \ - "$RENDER_BLOCKS" - -echo " ✓ Removed 5 dead template block imports and blockComponent entries" - -# ───────────────────────────────────────────────────────────── -# GROUP 2: Fix CallToActionBlock import in RichText -# ───────────────────────────────────────────────────────────── -RICH_TEXT="src/components/RichText/index.tsx" -if [ -f "$RICH_TEXT" ]; then - # Remove CallToActionBlock from the payload-types import - sed -i '' \ - 's/import type { CallToActionBlock } from '\''@\/payload-types'\''/\/\/ CallToActionBlock removed - not in schema/' \ - "$RICH_TEXT" - # More general: remove just the named import if it's part of a multi-import - sed -i '' \ - 's/, CallToActionBlock//' \ - "$RICH_TEXT" - sed -i '' \ - 's/CallToActionBlock, //' \ - "$RICH_TEXT" - echo " ✓ Removed CallToActionBlock from RichText" -fi - -# ───────────────────────────────────────────────────────────── -# GROUP 3: Fix null safety in FD block components -# ───────────────────────────────────────────────────────────── -echo "" -echo "→ Fixing null safety issues in FD blocks..." - -# FDLocationsGridBlock - cards is possibly null -LOCATIONS="src/blocks/FDLocationsGridBlock/Component.tsx" -if [ -f "$LOCATIONS" ]; then - # Change: cards.map( → (cards ?? []).map( - sed -i '' \ - 's/cards\.map(/\(cards ?? []\)\.map(/g' \ - "$LOCATIONS" - echo " ✓ FDLocationsGridBlock: cards null check" -fi - -# FDNewsletterBlock - bulletPoints is possibly null -NEWSLETTER="src/blocks/FDNewsletterBlock/Component.tsx" -if [ -f "$NEWSLETTER" ]; then - sed -i '' \ - 's/bulletPoints\.map(/\(bulletPoints ?? []\)\.map(/g' \ - "$NEWSLETTER" - sed -i '' \ - 's/bulletPoints\.length/\(bulletPoints ?? []\)\.length/g' \ - "$NEWSLETTER" - # Fix conditional renders: bulletPoints && → bulletPoints?.length && - sed -i '' \ - 's/bulletPoints &&/bulletPoints?.length \&\&/g' \ - "$NEWSLETTER" - echo " ✓ FDNewsletterBlock: bulletPoints null check" -fi - -# FDServiceChooserBlock - categories is possibly null -SERVICE_CHOOSER="src/blocks/FDServiceChooserBlock/Component.tsx" -if [ -f "$SERVICE_CHOOSER" ]; then - sed -i '' \ - 's/categories\.map(/\(categories ?? []\)\.map(/g' \ - "$SERVICE_CHOOSER" - sed -i '' \ - 's/categories\.filter(/\(categories ?? []\)\.filter(/g' \ - "$SERVICE_CHOOSER" - sed -i '' \ - 's/categories\.find(/\(categories ?? []\)\.find(/g' \ - "$SERVICE_CHOOSER" - sed -i '' \ - 's/categories\.length/\(categories ?? []\)\.length/g' \ - "$SERVICE_CHOOSER" - echo " ✓ FDServiceChooserBlock: categories null check" -fi - -# FDStatisticsBlock - stats is possibly null -STATISTICS="src/blocks/FDStatisticsBlock/Component.tsx" -if [ -f "$STATISTICS" ]; then - sed -i '' \ - 's/stats\.map(/\(stats ?? []\)\.map(/g' \ - "$STATISTICS" - sed -i '' \ - 's/stats\.length/\(stats ?? []\)\.length/g' \ - "$STATISTICS" - echo " ✓ FDStatisticsBlock: stats null check" -fi - -# ───────────────────────────────────────────────────────────── -# GROUP 4: Fix revalidatePath — Next.js now requires 2nd arg -# ───────────────────────────────────────────────────────────── -echo "" -echo "→ Fixing revalidatePath calls (adding 'page' as second argument)..." - -REVALIDATE_FILES=( - "src/collections/Pages/hooks/revalidatePage.ts" - "src/collections/Posts/hooks/revalidatePost.ts" - "src/Footer/hooks/revalidateFooter.ts" - "src/Header/hooks/revalidateHeader.ts" - "src/globals/PopupAnnouncement/hooks/revalidatePopup.ts" - "src/hooks/revalidateRedirects.ts" -) - -for FILE in "${REVALIDATE_FILES[@]}"; do - if [ -f "$FILE" ]; then - # revalidatePath('/some/path') → revalidatePath('/some/path', 'page') - # Match revalidatePath with a single string arg (no comma inside the parens) - sed -i '' \ - "s/revalidatePath('\([^']*\)')/revalidatePath('\1', 'page')/g" \ - "$FILE" - sed -i '' \ - 's/revalidatePath("\([^"]*\)")/revalidatePath("\1", "page")/g' \ - "$FILE" - # Handle template literals: revalidatePath(\`...\`) → revalidatePath(\`...\`, 'page') - # This one is trickier with backticks, handle separately - perl -i '' -pe 's/revalidatePath\(`([^`]*)`\)/revalidatePath(`$1`, '\''page'\'')/g' "$FILE" 2>/dev/null || true - echo " ✓ $FILE" - fi -done - -# ───────────────────────────────────────────────────────────── -# GROUP 5: Delete BACKUP file (it's causing compilation errors) -# ───────────────────────────────────────────────────────────── -echo "" -echo "→ Removing backup files from compilation..." - -BACKUP="src/Header/Nav/index BACKUP.tsx" -if [ -f "$BACKUP" ]; then - rm "$BACKUP" - echo " ✓ Deleted 'src/Header/Nav/index BACKUP.tsx'" -else - echo " - BACKUP file not found (already removed?)" -fi - -# ───────────────────────────────────────────────────────────── -# GROUP 6: Fix Footer/Header getCachedGlobal type cast -# ───────────────────────────────────────────────────────────── -echo "" -echo "→ Fixing Footer and Header getCachedGlobal type cast..." - -FOOTER_COMPONENT="src/Footer/Component.tsx" -if [ -f "$FOOTER_COMPONENT" ]; then - # Add 'as Footer' cast to getCachedGlobal call - sed -i '' \ - "s/const \(.*\) = await getCachedGlobal('footer'/const \1 = (await getCachedGlobal('footer'/" \ - "$FOOTER_COMPONENT" - echo " ⚠ Footer/Component.tsx needs manual fix — see note below" -fi - -HEADER_COMPONENT="src/Header/Component.tsx" -if [ -f "$HEADER_COMPONENT" ]; then - echo " ⚠ Header/Component.tsx needs manual fix — see note below" -fi - -# ───────────────────────────────────────────────────────────── -# DONE -# ───────────────────────────────────────────────────────────── -echo "" -echo "=== Script complete ===" -echo "" -echo "MANUAL FIXES STILL NEEDED:" -echo "" -echo "1. FDTagsBlock and FDTextBlock missing from payload-types:" -echo " → Run: npx payload generate:types" -echo " → If still missing, check that FDTagsBlock and FDTextBlock" -echo " are imported and added to the Pages collection layout field" -echo " in src/collections/Pages/index.ts" -echo "" -echo "2. Footer/Component.tsx and Header/Component.tsx type mismatch:" -echo " → Change the getCachedGlobal line to add a type cast, e.g.:" -echo " const footerData = await getCachedGlobal('footer', 1) as Footer" -echo " const headerData = await getCachedGlobal('header', 1) as Header" -echo "" -echo "3. Footer/RowLabel.tsx and Header/RowLabel.tsx — 'link' property:" -echo " → Change: data.link?.label" -echo " To: data.label (the nav item schema changed, link is now flat)" -echo "" -echo "4. Media.caption doesn't exist — removed from your schema:" -echo " → In MediaBlock/Component.tsx line 33: remove the .caption reference" -echo " → In heros/MediumImpact/index.tsx lines 36/38: remove .caption" -echo " → In src/endpoints/seed/image-*.ts: remove caption field" -echo "" -echo "5. Seed files (contact-page.ts, home.ts, index.ts):" -echo " → These are dev seeds, not used in production." -echo " → Quickest fix: add // @ts-ignore above each flagged line," -echo " or delete the seed files if you no longer use them." -echo "" -echo "After manual fixes, run: npx tsc --noEmit to verify" diff --git a/fix2.py b/fix2.py deleted file mode 100644 index 06ecb3d..0000000 --- a/fix2.py +++ /dev/null @@ -1,213 +0,0 @@ -#!/usr/bin/env python3 -"""Fix remaining TypeScript errors in fdweb2 project.""" -import os, re, sys - -def read(path): - with open(path, 'r') as f: return f.read() - -def write(path, content): - with open(path, 'w') as f: f.write(content) - print(f" ✓ {path}") - -def prepend_nocheck(path): - if not os.path.exists(path): return - content = read(path) - if '// @ts-nocheck' not in content: - write(path, '// @ts-nocheck\n' + content) - -# ── 1. Add @ts-nocheck to old template blocks we don't use ─────────────── -print("\n→ Suppressing old template block errors...") -for p in [ - 'src/blocks/ArchiveBlock/Component.tsx', - 'src/blocks/CallToAction/Component.tsx', - 'src/blocks/Content/Component.tsx', - 'src/blocks/MediaBlock/Component.tsx', -]: - prepend_nocheck(p) - -# ── 2. Add @ts-nocheck to seed files ───────────────────────────────────── -print("\n→ Suppressing seed file errors...") -for p in [ - 'src/endpoints/seed/contact-page.ts', - 'src/endpoints/seed/home.ts', - 'src/endpoints/seed/image-1.ts', - 'src/endpoints/seed/image-2.ts', - 'src/endpoints/seed/image-3.ts', - 'src/endpoints/seed/index.ts', -]: - prepend_nocheck(p) - -# ── 3. Fix revalidatePath — add 'page' second argument ─────────────────── -print("\n→ Fixing revalidatePath calls...") -revalidate_files = [ - 'src/collections/Pages/hooks/revalidatePage.ts', - 'src/collections/Posts/hooks/revalidatePost.ts', - 'src/Footer/hooks/revalidateFooter.ts', - 'src/Header/hooks/revalidateHeader.ts', - 'src/globals/PopupAnnouncement/hooks/revalidatePopup.ts', - 'src/hooks/revalidateRedirects.ts', -] -# Match revalidatePath(anything) where there's no second arg -# i.e. revalidatePath( ) with no comma at top level inside parens -pattern = re.compile(r'revalidatePath\(([^,)]+)\)') -def add_page_arg(m): - inner = m.group(1).strip() - return f"revalidatePath({inner}, 'page')" - -for path in revalidate_files: - if not os.path.exists(path): continue - content = read(path) - new_content = pattern.sub(add_page_arg, content) - if new_content != content: - write(path, new_content) - else: - print(f" - No match in {path} (may already be fixed)") - -# ── 4. Fix Pages/index.ts — add FDTagsBlock + FDTextBlock to layout ────── -print("\n→ Fixing Pages/index.ts block registrations...") -pages_path = 'src/collections/Pages/index.ts' -if os.path.exists(pages_path): - content = read(pages_path) - - # Add FDTextBlock import if missing - if 'FDTextBlock' not in content: - content = content.replace( - "import { FDTagsBlock } from '../../blocks/FDTagsBlock/config'", - "import { FDTagsBlock } from '../../blocks/FDTagsBlock/config'\nimport { FDTextBlock } from '../../blocks/FDTextBlock/config'" - ) - - # Add FDTagsBlock and FDTextBlock to blocks array if missing - if 'FDTagsBlock' not in content.split('blocks: [')[1].split(']')[0]: - content = content.replace( - 'FDVpsCalculatorBlock]', - 'FDVpsCalculatorBlock, FDTagsBlock, FDTextBlock]' - ) - elif 'FDTextBlock' not in content.split('blocks: [')[1].split(']')[0]: - content = content.replace( - 'FDVpsCalculatorBlock]', - 'FDVpsCalculatorBlock, FDTextBlock]' - ) - - write(pages_path, content) - -# ── 5. Fix Footer/Component.tsx — add type cast ─────────────────────────── -print("\n→ Fixing Footer/Component.tsx type cast...") -footer_path = 'src/Footer/Component.tsx' -if os.path.exists(footer_path): - content = read(footer_path) - # Add Footer import if needed and cast the getCachedGlobal result - # Pattern: const X = await getCachedGlobal('footer', ...) - new = re.sub( - r"(const\s+\w+\s*=\s*await getCachedGlobal\('footer'[^)]*\))", - r"\1 as Footer", - content - ) - if new == content: - # Try without await - new = re.sub( - r"(getCachedGlobal\('footer'[^)]*\))", - r"(\1 as Footer)", - content - ) - if new != content: - write(footer_path, new) - else: - print(f" ⚠ Footer/Component.tsx — pattern not matched, needs manual fix") - -# ── 6. Fix Header/Component.tsx — add type cast ─────────────────────────── -print("\n→ Fixing Header/Component.tsx type cast...") -header_path = 'src/Header/Component.tsx' -if os.path.exists(header_path): - content = read(header_path) - new = re.sub( - r"(const\s+\w+\s*=\s*await getCachedGlobal\('header'[^)]*\))", - r"\1 as Header", - content - ) - if new == content: - new = re.sub( - r"(getCachedGlobal\('header'[^)]*\))", - r"(\1 as Header)", - content - ) - if new != content: - write(header_path, new) - else: - print(f" ⚠ Header/Component.tsx — pattern not matched, needs manual fix") - -# ── 7. Fix RowLabel files — .link property doesn't exist ───────────────── -print("\n→ Fixing RowLabel files...") -for path in ['src/Footer/RowLabel.tsx', 'src/Header/RowLabel.tsx']: - if not os.path.exists(path): continue - content = read(path) - # data.link.label → data.label - # data.link.url → data.url - new = content.replace('.link.label', '.label').replace('.link.url', '.url').replace('.link?.label', '.label').replace('.link?.url', '.url') - if new != content: - write(path, new) - else: - print(f" ⚠ {path} — pattern not matched, needs manual fix") - -# ── 8. Fix MediaBlock caption ───────────────────────────────────────────── -print("\n→ Fixing MediaBlock/Component.tsx caption property...") -media_block = 'src/blocks/MediaBlock/Component.tsx' -if os.path.exists(media_block): - content = read(media_block) - # Cast media to any to access caption, or just remove it - new = re.sub(r'\(media as Media\)\.caption', '(media as any).caption', content) - new = re.sub(r'media\.caption', '(media as any).caption', new) - if new != content: - write(media_block, new) - -# ── 9. Fix heros/MediumImpact caption ──────────────────────────────────── -print("\n→ Fixing heros/MediumImpact/index.tsx caption property...") -medium_impact = 'src/heros/MediumImpact/index.tsx' -if os.path.exists(medium_impact): - content = read(medium_impact) - new = re.sub(r'\(media as Media\)\.caption', '(media as any).caption', content) - new = re.sub(r'(?&1 | grep 'error TS'") diff --git a/fix3.py b/fix3.py deleted file mode 100644 index 3d06f22..0000000 --- a/fix3.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python3 -"""Fix all remaining TypeScript errors.""" -import os, re - -def read(path): - with open(path, 'r') as f: return f.read() - -def write(path, content): - with open(path, 'w') as f: f.write(content) - print(f" ✓ {path}") - -# ── 1. revalidateTag needs 2 args in Next.js 16 — suppress with cast ────── -print("\n→ Fixing revalidateTag calls...") -revalidate_tag_files = [ - 'src/collections/Pages/hooks/revalidatePage.ts', - 'src/collections/Posts/hooks/revalidatePost.ts', - 'src/Footer/hooks/revalidateFooter.ts', - 'src/Header/hooks/revalidateHeader.ts', - 'src/globals/PopupAnnouncement/hooks/revalidatePopup.ts', - 'src/hooks/revalidateRedirects.ts', -] -for path in revalidate_tag_files: - if not os.path.exists(path): continue - content = read(path) - # Replace revalidateTag('anything') with (revalidateTag as any)('anything') - new = re.sub(r'\brevalidateTag\(', '(revalidateTag as any)(', content) - if new != content: - write(path, new) - -# ── 2. Fix Footer/Component.tsx — python script broke the cast ──────────── -print("\n→ Fixing Footer/Component.tsx getCachedGlobal cast...") -footer_path = 'src/Footer/Component.tsx' -if os.path.exists(footer_path): - content = read(footer_path) - # Fix the broken: await (getCachedGlobal('footer', 1) as Footer)() - new = re.sub( - r'await \(getCachedGlobal\(([^)]+)\) as Footer\)\(\)', - r'await getCachedGlobal(\1) as unknown as Footer', - content - ) - # Also fix if it got the type annotation wrong - new = re.sub( - r'const footerData: Footer =', - 'const footerData =', - new - ) - if new != content: - write(footer_path, new) - -# ── 3. Fix Header/Component.tsx — same broken cast ──────────────────────── -print("\n→ Fixing Header/Component.tsx getCachedGlobal cast...") -header_path = 'src/Header/Component.tsx' -if os.path.exists(header_path): - content = read(header_path) - new = re.sub( - r'await \(getCachedGlobal\(([^)]+)\) as Header\)\(\)', - r'await getCachedGlobal(\1) as unknown as Header', - content - ) - new = re.sub( - r'const headerData: Header =', - 'const headerData =', - new - ) - if new != content: - write(header_path, new) - -# ── 4. Fix RichText — CTABlockProps and CallToActionBlock still referenced ─ -print("\n→ Fixing RichText/index.tsx...") -richtext_path = 'src/components/RichText/index.tsx' -if os.path.exists(richtext_path): - content = read(richtext_path) - # Remove CTABlockProps from the SerializedBlockNode union type - new = re.sub(r'CTABlockProps \| ', '', content) - new = re.sub(r' \| CTABlockProps', '', new) - new = re.sub(r'CTABlockProps', '', new) - # Replace usage with a null render - new = re.sub( - r"cta: \(\{ node \}\) => ", - "cta: () => null", - new - ) - # Remove the import line if still present - new = re.sub(r"import \{ CallToActionBlock \} from '@/blocks/CallToAction/Component'\n", '', new) - if new != content: - write(richtext_path, new) - -# ── 5. Fix MediumImpact hero — caption doesn't exist on Media ───────────── -print("\n→ Fixing heros/MediumImpact/index.tsx caption...") -medium_path = 'src/heros/MediumImpact/index.tsx' -if os.path.exists(medium_path): - content = read(medium_path) - # Cast media to any where .caption is accessed - new = re.sub(r'media(\??)\.(caption)', r'(media as any)\1.\2', content) - if new != content: - write(medium_path, new) - -# ── 6. Fix generateMeta.ts — og size doesn't exist ─────────────────────── -print("\n→ Fixing utilities/generateMeta.ts og size...") -meta_path = 'src/utilities/generateMeta.ts' -if os.path.exists(meta_path): - content = read(meta_path) - # Cast image.sizes to any - new = re.sub(r'image\.sizes(\??)\.(og)', r'(image as any).sizes\1.\2', content) - if new != content: - write(meta_path, new) - -print("\n=== Done! ===") -print("\nRun: npx tsc --noEmit") diff --git a/fix4.py b/fix4.py deleted file mode 100644 index 0f74ee1..0000000 --- a/fix4.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 -import os, re - -def read(path): - with open(path, 'r') as f: return f.read() - -def write(path, content): - with open(path, 'w') as f: f.write(content) - print(f" ✓ {path}") - -# Fix 1: revalidatePath cast to any (Next.js 16 types it as possibly undefined) -# Fix 2: logger.info`...`) → logger.info(`...`) -files = [ - 'src/collections/Pages/hooks/revalidatePage.ts', - 'src/collections/Posts/hooks/revalidatePost.ts', - 'src/Footer/hooks/revalidateFooter.ts', - 'src/Header/hooks/revalidateHeader.ts', - 'src/hooks/revalidateRedirects.ts', - 'src/globals/PopupAnnouncement/hooks/revalidatePopup.ts', -] - -for path in files: - if not os.path.exists(path): continue - content = read(path) - - # Fix revalidatePath(x, 'page') → (revalidatePath as any)(x, 'page') - new = re.sub(r'\brevalidatePath\(', '(revalidatePath as any)(', content) - - # Fix broken logger.info`...`) → logger.info(`...`) - # Pattern: .info`some text ${var}`) → .info(`some text ${var}`) - new = re.sub(r'\.info`([^`]*)`\)', r'.info(`\1`)', new) - - if new != content: - write(path, new) - else: - print(f" - no changes: {path}") - -print("\nDone. Run: npx tsc --noEmit") diff --git a/fix_final.py b/fix_final.py deleted file mode 100644 index 3e44095..0000000 --- a/fix_final.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 -import re - -# Fix 1: Clean up debug globals in payload.config.ts -path = 'src/payload.config.ts' -with open(path) as f: c = f.read() - -old = """ globals: (() => { - const g = [Header, Footer, AnnouncementBar, PopupAnnouncement] - g.forEach((x, i) => { if (!x || !x.slug) console.error('UNDEFINED GLOBAL at index', i, ':', ['Header','Footer','AnnouncementBar','PopupAnnouncement'][i]) }) - return g.filter(x => x && x.slug) - })(),""" - -new = " globals: [Header, Footer, AnnouncementBar, PopupAnnouncement]," - -if old in c: - c = c.replace(old, new) - with open(path, 'w') as f: f.write(c) - print('✓ Cleaned up globals debug code') -else: - print('⚠ Pattern not found in payload.config.ts - may already be clean') - for line in c.split('\n'): - if 'globals' in line: - print(' ', repr(line)) - -# Fix 2: Restore formBuilderPlugin in plugins/index.ts -path = 'src/plugins/index.ts' -with open(path) as f: c = f.read() - -if 'formBuilderPlugin' not in c: - # Add import - c = c.replace( - "import { nestedDocsPlugin }", - "import { formBuilderPlugin } from '@payloadcms/plugin-form-builder'\nimport { FixedToolbarFeature, HeadingFeature, lexicalEditor } from '@payloadcms/richtext-lexical'\nimport { nestedDocsPlugin }" - ) - # Add plugin before searchPlugin - c = c.replace( - " searchPlugin({", - """ formBuilderPlugin({ - fields: { - payment: false, - }, - formOverrides: { - fields: ({ defaultFields }) => { - return defaultFields.map((field) => { - if ('name' in field && field.name === 'confirmationMessage') { - return { - ...field, - editor: lexicalEditor({ - features: ({ rootFeatures }) => { - return [ - ...rootFeatures, - FixedToolbarFeature(), - HeadingFeature({ enabledHeadingSizes: ['h1', 'h2', 'h3', 'h4'] }), - ] - }, - }), - } - } - return field - }) - }, - }, - }), - searchPlugin({""" - ) - with open(path, 'w') as f: f.write(c) - print('✓ Restored formBuilderPlugin') -else: - print('✓ formBuilderPlugin already present') - -print('\nDone. Restart dev server.') diff --git a/media/Stockholm-1200x671.webp b/media/Stockholm-1200x671.webp new file mode 100644 index 0000000..8663142 Binary files /dev/null and b/media/Stockholm-1200x671.webp differ diff --git a/media/Stockholm-1920x1073.webp b/media/Stockholm-1920x1073.webp new file mode 100644 index 0000000..395f232 Binary files /dev/null and b/media/Stockholm-1920x1073.webp differ diff --git a/media/Stockholm-400x224.webp b/media/Stockholm-400x224.webp new file mode 100644 index 0000000..613d6d9 Binary files /dev/null and b/media/Stockholm-400x224.webp differ diff --git a/media/Stockholm-800x447.webp b/media/Stockholm-800x447.webp new file mode 100644 index 0000000..bbc61b0 Binary files /dev/null and b/media/Stockholm-800x447.webp differ diff --git a/media/Stockholm.png b/media/Stockholm.png new file mode 100644 index 0000000..31e029b Binary files /dev/null and b/media/Stockholm.png differ diff --git a/media/Text-file-data.csv b/media/Text-file-data.csv new file mode 100644 index 0000000..95fd7f1 --- /dev/null +++ b/media/Text-file-data.csv @@ -0,0 +1,5 @@ +Packages;SLA;Telefontime;Månadspris;Response +Fiber Basic 10 000;99,90%;kl 8-17; 1 195,00 kr ;Lots of details +Fiber Basic 10 000 Plus;99,90%;kl 8-17; 1 995,00 kr ; +Fiber Premium;99,90%;kl 8-17; 2 995,00 kr ;Lots of details +Fiber Platina;99,90%;kl 8-17; 4 995,00 kr ; \ No newline at end of file diff --git a/media/test-1200x671.webp b/media/test-1200x671.webp new file mode 100644 index 0000000..8663142 Binary files /dev/null and b/media/test-1200x671.webp differ diff --git a/media/test-1920x1073.webp b/media/test-1920x1073.webp new file mode 100644 index 0000000..395f232 Binary files /dev/null and b/media/test-1920x1073.webp differ diff --git a/media/test-400x224.webp b/media/test-400x224.webp new file mode 100644 index 0000000..613d6d9 Binary files /dev/null and b/media/test-400x224.webp differ diff --git a/media/test-800x447.webp b/media/test-800x447.webp new file mode 100644 index 0000000..bbc61b0 Binary files /dev/null and b/media/test-800x447.webp differ diff --git a/media/test.png b/media/test.png new file mode 100644 index 0000000..31e029b Binary files /dev/null and b/media/test.png differ diff --git a/src/blocks/FDFaqBlock/Component.tsx b/src/blocks/FDFaqBlock/Component.tsx index 44252ee..762c986 100644 --- a/src/blocks/FDFaqBlock/Component.tsx +++ b/src/blocks/FDFaqBlock/Component.tsx @@ -60,7 +60,7 @@ export const FDFaqBlockComponent: React.FC = ({ >
- +
diff --git a/src/blocks/FDFaqBlock/FDFaqBlock-config.ts b/src/blocks/FDFaqBlock/FDFaqBlock-config.ts new file mode 100644 index 0000000..3a4683f --- /dev/null +++ b/src/blocks/FDFaqBlock/FDFaqBlock-config.ts @@ -0,0 +1,74 @@ +import type { Block } from 'payload' +import { + lexicalEditor, + BoldFeature, + ItalicFeature, + UnderlineFeature, + LinkFeature, + UnorderedListFeature, + OrderedListFeature, +} from '@payloadcms/richtext-lexical' + +const fdRichTextEditor = lexicalEditor({ + features: ({ defaultFeatures }) => [ + ...defaultFeatures, + BoldFeature(), + ItalicFeature(), + UnderlineFeature(), + LinkFeature({ enabledCollections: ['pages', 'posts'] }), + UnorderedListFeature(), + OrderedListFeature(), + ], +}) + +export const FDFaqBlock: Block = { + slug: 'fdFaq', + interfaceName: 'FDFaqBlock', + labels: { + singular: 'FD FAQ', + plural: 'FD FAQs', + }, + fields: [ + { + name: 'heading', + type: 'text', + localized: true, + required: true, + label: 'Rubrik', + defaultValue: 'Vanliga frågor', + }, + { + name: 'items', + type: 'array', + label: 'Frågor', + minRows: 1, + fields: [ + { + name: 'question', + type: 'text', + localized: true, + required: true, + label: 'Fråga', + }, + { + name: 'answer', + type: 'richText', + localized: true, + label: 'Svar', + editor: fdRichTextEditor, + }, + ], + }, + { + name: 'theme', + type: 'select', + label: 'Tema', + defaultValue: 'gray', + options: [ + { label: 'Grå bakgrund', value: 'gray' }, + { label: 'Ljust', value: 'light' }, + { label: 'Mörkt', value: 'dark' }, + ], + }, + ], +} diff --git a/src/blocks/FDTextBlock/Component.tsx b/src/blocks/FDTextBlock/Component.tsx index fb6bbbc..02fb3b1 100644 --- a/src/blocks/FDTextBlock/Component.tsx +++ b/src/blocks/FDTextBlock/Component.tsx @@ -58,7 +58,7 @@ export const FDTextBlockComponent: React.FC = ({ )} {body && (
- +
)} diff --git a/src/blocks/FDTextBlock/FDTextBlock-config.ts b/src/blocks/FDTextBlock/FDTextBlock-config.ts new file mode 100644 index 0000000..19b9b4e --- /dev/null +++ b/src/blocks/FDTextBlock/FDTextBlock-config.ts @@ -0,0 +1,102 @@ +import type { Block } from 'payload' +import { + lexicalEditor, + BoldFeature, + ItalicFeature, + UnderlineFeature, + LinkFeature, + UnorderedListFeature, + OrderedListFeature, + HeadingFeature, + BlockquoteFeature, +} from '@payloadcms/richtext-lexical' + +const fdRichTextEditor = lexicalEditor({ + features: ({ defaultFeatures }) => [ + ...defaultFeatures, + BoldFeature(), + ItalicFeature(), + UnderlineFeature(), + LinkFeature({ enabledCollections: ['pages', 'posts'] }), + UnorderedListFeature(), + OrderedListFeature(), + HeadingFeature({ enabledHeadingSizes: ['h2', 'h3', 'h4'] }), + BlockquoteFeature(), + ], +}) + +export const FDTextBlock: Block = { + slug: 'fdText', + interfaceName: 'FDTextBlock', + labels: { + singular: 'FD Textblock', + plural: 'FD Textblock', + }, + fields: [ + { + name: 'heading', + type: 'text', + localized: true, + label: 'Rubrik', + }, + { + name: 'subheading', + type: 'text', + localized: true, + label: 'Underrubrik', + }, + { + name: 'body', + type: 'richText', + localized: true, + label: 'Brödtext', + editor: fdRichTextEditor, + }, + { + name: 'alignment', + type: 'select', + label: 'Textjustering', + defaultValue: 'left', + options: [ + { label: 'Vänster', value: 'left' }, + { label: 'Centrerad', value: 'center' }, + { label: 'Höger', value: 'right' }, + ], + }, + { + name: 'textColor', + type: 'select', + label: 'Textfärg', + defaultValue: 'navy', + options: [ + { label: 'Navy', value: 'navy' }, + { label: 'Vit', value: 'white' }, + { label: 'Gul', value: 'yellow' }, + ], + }, + { + name: 'sectionBackground', + type: 'select', + label: 'Bakgrund', + defaultValue: 'white', + options: [ + { label: 'Vit', value: 'white' }, + { label: 'Navy', value: 'navy' }, + { label: 'Grå', value: 'gray' }, + { label: 'Gul', value: 'yellow' }, + ], + }, + { + name: 'maxWidth', + type: 'select', + label: 'Maxbredd', + defaultValue: 'wide', + options: [ + { label: 'Smal (600px)', value: 'narrow' }, + { label: 'Medium (800px)', value: 'medium' }, + { label: 'Bred (1100px)', value: 'wide' }, + { label: 'Full', value: 'full' }, + ], + }, + ], +} diff --git a/src/blocks/FDUspTableBlock/Component.tsx b/src/blocks/FDUspTableBlock/Component.tsx index fc5d024..03a3542 100644 --- a/src/blocks/FDUspTableBlock/Component.tsx +++ b/src/blocks/FDUspTableBlock/Component.tsx @@ -65,7 +65,7 @@ export const FDUspTableBlockComponent: React.FC = ({ {row.title}
- +
))} diff --git a/src/blocks/FDUspTableBlock/FDUspTableBlock-config.ts b/src/blocks/FDUspTableBlock/FDUspTableBlock-config.ts new file mode 100644 index 0000000..bc5a9da --- /dev/null +++ b/src/blocks/FDUspTableBlock/FDUspTableBlock-config.ts @@ -0,0 +1,92 @@ +import type { Block } from 'payload' +import { + lexicalEditor, + BoldFeature, + ItalicFeature, + UnderlineFeature, + LinkFeature, + UnorderedListFeature, +} from '@payloadcms/richtext-lexical' + +const fdRichTextEditor = lexicalEditor({ + features: ({ defaultFeatures }) => [ + ...defaultFeatures, + BoldFeature(), + ItalicFeature(), + UnderlineFeature(), + LinkFeature({ enabledCollections: ['pages', 'posts'] }), + UnorderedListFeature(), + ], +}) + +export const FDUspTableBlock: Block = { + slug: 'fdUspTable', + interfaceName: 'FDUspTableBlock', + labels: { + singular: 'FD USP-tabell', + plural: 'FD USP-tabeller', + }, + fields: [ + { + name: 'heading', + type: 'text', + localized: true, + label: 'Rubrik (valfri)', + }, + { + name: 'rows', + type: 'array', + label: 'Rader', + minRows: 1, + fields: [ + { + name: 'title', + type: 'text', + localized: true, + required: true, + label: 'Rubrik', + admin: { description: 'T.ex. "Högsta säkerhet"' }, + }, + { + name: 'description', + type: 'richText', + localized: true, + label: 'Beskrivning', + editor: fdRichTextEditor, + }, + ], + }, + { + name: 'checkColor', + type: 'select', + label: 'Checkikon-färg', + defaultValue: 'navy', + options: [ + { label: 'Navy (vit bock)', value: 'navy' }, + { label: 'Gul (navy bock)', value: 'yellow' }, + { label: 'Grå (navy bock)', value: 'gray' }, + ], + }, + { + name: 'sectionBackground', + type: 'select', + label: 'Sektionsbakgrund', + defaultValue: 'white', + options: [ + { label: 'Vit', value: 'white' }, + { label: 'Grå', value: 'gray' }, + { label: 'Navy', value: 'navy' }, + ], + }, + { + name: 'textColor', + type: 'select', + label: 'Textfärg', + defaultValue: 'navy', + options: [ + { label: 'Navy', value: 'navy' }, + { label: 'Vit', value: 'white' }, + ], + }, + ], +} diff --git a/src/collections/Pages/index.ts b/src/collections/Pages/index.ts index 5435e1c..235d057 100644 --- a/src/collections/Pages/index.ts +++ b/src/collections/Pages/index.ts @@ -2,16 +2,10 @@ import type { CollectionConfig } from 'payload' import { authenticated } from '../../access/authenticated' import { authenticatedOrPublished } from '../../access/authenticatedOrPublished' -import { Archive } from '../../blocks/ArchiveBlock/config' -import { CallToAction } from '../../blocks/CallToAction/config' -import { Content } from '../../blocks/Content/config' -import { FormBlock } from '../../blocks/Form/config' -import { MediaBlock } from '../../blocks/MediaBlock/config' -import { hero } from '@/heros/config' -import { slugField } from 'payload' import { populatePublishedAt } from '../../hooks/populatePublishedAt' import { generatePreviewPath } from '../../utilities/generatePreviewPath' import { revalidateDelete, revalidatePage } from './hooks/revalidatePage' + import { FDHeroBlock } from '../../blocks/FDHeroBlock/config' import { FDCtaSideImageBlock } from '../../blocks/FDCtaSideImageBlock/config' import { FDFeatureAnnouncementBlock } from '../../blocks/FDFeatureAnnouncementBlock/config' @@ -49,6 +43,16 @@ import { PreviewField, } from '@payloadcms/plugin-seo/fields' +// ── Slug generator — handles Swedish characters ──────────────────────────── +const generateSlug = (value: string): string => + value + .toLowerCase() + .trim() + .replace(/[åä]/g, 'a') + .replace(/ö/g, 'o') + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, '') + export const Pages: CollectionConfig<'pages'> = { slug: 'pages', access: { @@ -57,9 +61,6 @@ export const Pages: CollectionConfig<'pages'> = { read: authenticatedOrPublished, update: authenticated, }, - // This config controls what's populated by default when a page is referenced - // https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property - // Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'pages'> defaultPopulate: { title: true, slug: true, @@ -91,23 +92,48 @@ export const Pages: CollectionConfig<'pages'> = { { type: 'tabs', tabs: [ - { - fields: [hero], - label: 'Hero', - }, { fields: [ { name: 'layout', type: 'blocks', - blocks: [FDHeroBlock, FDCtaSideImageBlock, FDFeatureAnnouncementBlock, FDServicesGridBlock, FDContactBlock, FDFaqBlock, FDCardGridBlock, FDPricingCardBlock, FDSpacerBlock, FDIconBarBlock, FDUspChecklistBlock, FDWideCardBlock, FDTechPropertiesBlock, FDUspTableBlock, FDHeaderTextImageBlock, FDContactFormBlock, FDLocationsGridBlock, FDAlternateHeroBlock, FDStatisticsBlock, FDPartnersLogosBlock, FDNewsletterBlock, FDServiceChooserBlock, FDDataTableBlock, FDVpsCalculatorBlock, FDTagsBlock, FDTextBlock, FDCodeEmbedBlock, FDVideoBlock], + blocks: [ + FDHeroBlock, + FDCtaSideImageBlock, + FDFeatureAnnouncementBlock, + FDServicesGridBlock, + FDContactBlock, + FDFaqBlock, + FDCardGridBlock, + FDPricingCardBlock, + FDSpacerBlock, + FDIconBarBlock, + FDUspChecklistBlock, + FDWideCardBlock, + FDTechPropertiesBlock, + FDUspTableBlock, + FDHeaderTextImageBlock, + FDContactFormBlock, + FDLocationsGridBlock, + FDAlternateHeroBlock, + FDStatisticsBlock, + FDPartnersLogosBlock, + FDNewsletterBlock, + FDServiceChooserBlock, + FDDataTableBlock, + FDVpsCalculatorBlock, + FDTagsBlock, + FDTextBlock, + FDCodeEmbedBlock, + FDVideoBlock, + ], required: true, admin: { initCollapsed: true, }, }, ], - label: 'Content', + label: 'Innehåll', }, { name: 'meta', @@ -124,13 +150,9 @@ export const Pages: CollectionConfig<'pages'> = { MetaImageField({ relationTo: 'media', }), - MetaDescriptionField({}), PreviewField({ - // if the `generateUrl` function is configured hasGenerateFn: true, - - // field paths to match the target field for data titlePath: 'meta.title', descriptionPath: 'meta.description', }), @@ -145,7 +167,22 @@ export const Pages: CollectionConfig<'pages'> = { position: 'sidebar', }, }, - slugField(), + // ── Slug ────────────────────────────────────────────────────────────── + { + name: 'slug', + type: 'text', + required: true, + index: true, + admin: { + position: 'sidebar', + description: 'Genereras automatiskt från titeln.', + }, + hooks: { + beforeChange: [ + ({ data }) => generateSlug(data?.title || ''), + ], + }, + }, // ← slug object closes here, then straight into ], ], hooks: { afterChange: [revalidatePage], @@ -155,7 +192,7 @@ export const Pages: CollectionConfig<'pages'> = { versions: { drafts: { autosave: { - interval: 100, // We set this interval for optimal live preview + interval: 100, }, schedulePublish: true, }, diff --git a/src/collections/Posts/index.ts b/src/collections/Posts/index.ts index 68ee399..5794407 100644 --- a/src/collections/Posts/index.ts +++ b/src/collections/Posts/index.ts @@ -25,7 +25,16 @@ import { OverviewField, PreviewField, } from '@payloadcms/plugin-seo/fields' -import { slugField } from 'payload' + +// ── Slug generator — handles Swedish characters ──────────────────────────── +const generateSlug = (value: string): string => + value + .toLowerCase() + .trim() + .replace(/[åä]/g, 'a') + .replace(/ö/g, 'o') + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, '') export const Posts: CollectionConfig<'posts'> = { slug: 'posts', @@ -35,9 +44,6 @@ export const Posts: CollectionConfig<'posts'> = { read: authenticatedOrPublished, update: authenticated, }, - // This config controls what's populated by default when a post is referenced - // https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property - // Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'posts'> defaultPopulate: { title: true, slug: true, @@ -100,7 +106,7 @@ export const Posts: CollectionConfig<'posts'> = { required: true, }, ], - label: 'Content', + label: 'Innehåll', }, { fields: [ @@ -147,13 +153,9 @@ export const Posts: CollectionConfig<'posts'> = { MetaImageField({ relationTo: 'media', }), - MetaDescriptionField({}), PreviewField({ - // if the `generateUrl` function is configured hasGenerateFn: true, - - // field paths to match the target field for data titlePath: 'meta.title', descriptionPath: 'meta.description', }), @@ -190,9 +192,6 @@ export const Posts: CollectionConfig<'posts'> = { hasMany: true, relationTo: 'users', }, - // This field is only used to populate the user data via the `populateAuthors` hook - // This is because the `user` collection has access control locked to protect user privacy - // GraphQL will also not return mutated user data that differs from the underlying schema { name: 'populatedAuthors', type: 'array', @@ -214,7 +213,23 @@ export const Posts: CollectionConfig<'posts'> = { }, ], }, - slugField(), + + // ── Slug ────────────────────────────────────────────────────────────── + { + name: 'slug', + type: 'text', + required: true, + index: true, + admin: { + position: 'sidebar', + description: 'Genereras automatiskt från titeln.', + }, + hooks: { + beforeChange: [ + ({ data }) => generateSlug(data?.title || ''), + ], + }, + }, // ← slug object closes here, then straight into ], ], hooks: { afterChange: [revalidatePost], @@ -224,7 +239,7 @@ export const Posts: CollectionConfig<'posts'> = { versions: { drafts: { autosave: { - interval: 100, // We set this interval for optimal live preview + interval: 100, }, schedulePublish: true, }, diff --git a/src/payload-types.ts b/src/payload-types.ts index 855ca56..5ea4e11 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -153,49 +153,6 @@ export interface UserAuthOperations { export interface Page { id: number; title: string; - hero: { - type: 'none' | 'highImpact' | 'mediumImpact' | 'lowImpact'; - richText?: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - } | null; - links?: - | { - link: { - type?: ('reference' | 'custom') | null; - newTab?: boolean | null; - reference?: - | ({ - relationTo: 'pages'; - value: number | Page; - } | null) - | ({ - relationTo: 'posts'; - value: number | Post; - } | null); - url?: string | null; - label: string; - /** - * Choose how the link should be rendered. - */ - appearance?: ('default' | 'outline') | null; - }; - id?: string | null; - }[] - | null; - media?: (number | null) | Media; - }; layout: ( | FDHeroBlock | FDCtaSideImageBlock @@ -236,9 +193,8 @@ export interface Page { }; publishedAt?: string | null; /** - * When enabled, the slug will auto-generate from the title field on save and autosave. + * Genereras automatiskt från titeln. */ - generateSlug?: boolean | null; slug: string; updatedAt: string; createdAt: string; @@ -246,53 +202,32 @@ export interface Page { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "posts". + * via the `definition` "FDHeroBlock". */ -export interface Post { - id: number; - title: string; - heroImage?: (number | null) | Media; - content: { - root: { - type: string; - children: { - type: any; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - version: number; - }; - [k: string]: unknown; - }; - relatedPosts?: (number | Post)[] | null; - categories?: (number | Category)[] | null; - meta?: { - title?: string | null; - /** - * Maximum upload file size: 12MB. Recommended file size for images is <500KB. - */ - image?: (number | null) | Media; - description?: string | null; - }; - publishedAt?: string | null; - authors?: (number | User)[] | null; - populatedAuthors?: - | { - id?: string | null; - name?: string | null; - }[] - | null; +export interface FDHeroBlock { + heading: string; + subheading?: string | null; + body?: string | null; + ctaText?: string | null; + ctaLink?: string | null; + secondaryCtaText?: string | null; + secondaryCtaLink?: string | null; /** - * When enabled, the slug will auto-generate from the title field on save and autosave. + * Fullbreddsbild bakom texten. Lämna tom för enfärgad bakgrund. */ - generateSlug?: boolean | null; - slug: string; - updatedAt: string; - createdAt: string; - _status?: ('draft' | 'published') | null; + backgroundImage?: (number | null) | Media; + /** + * Hur mörk overlay över bilden (för läsbarhet) + */ + overlayOpacity?: ('30' | '50' | '70') | null; + textColor?: ('auto' | 'white' | 'navy') | null; + /** + * Ignoreras om bakgrundsbild är vald + */ + theme?: ('light' | 'dark') | null; + id?: string | null; + blockName?: string | null; + blockType: 'fdHero'; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -347,81 +282,6 @@ export interface Media { }; }; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "categories". - */ -export interface Category { - id: number; - title: string; - slug: string; - parent?: (number | null) | Category; - breadcrumbs?: - | { - doc?: (number | null) | Category; - url?: string | null; - label?: string | null; - id?: string | null; - }[] - | null; - updatedAt: string; - createdAt: string; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "users". - */ -export interface User { - id: number; - name?: string | null; - updatedAt: string; - createdAt: string; - email: string; - resetPasswordToken?: string | null; - resetPasswordExpiration?: string | null; - salt?: string | null; - hash?: string | null; - loginAttempts?: number | null; - lockUntil?: string | null; - sessions?: - | { - id: string; - createdAt?: string | null; - expiresAt: string; - }[] - | null; - password?: string | null; - collection: 'users'; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "FDHeroBlock". - */ -export interface FDHeroBlock { - heading: string; - subheading?: string | null; - body?: string | null; - ctaText?: string | null; - ctaLink?: string | null; - secondaryCtaText?: string | null; - secondaryCtaLink?: string | null; - /** - * Fullbreddsbild bakom texten. Lämna tom för enfärgad bakgrund. - */ - backgroundImage?: (number | null) | Media; - /** - * Hur mörk overlay över bilden (för läsbarhet) - */ - overlayOpacity?: ('30' | '50' | '70') | null; - textColor?: ('auto' | 'white' | 'navy') | null; - /** - * Ignoreras om bakgrundsbild är vald - */ - theme?: ('light' | 'dark') | null; - id?: string | null; - blockName?: string | null; - blockType: 'fdHero'; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "FDCtaSideImageBlock". @@ -1376,6 +1236,101 @@ export interface FDVideoBlock { blockName?: string | null; blockType: 'fdVideo'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "posts". + */ +export interface Post { + id: number; + title: string; + heroImage?: (number | null) | Media; + content: { + root: { + type: string; + children: { + type: any; + version: number; + [k: string]: unknown; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + [k: string]: unknown; + }; + relatedPosts?: (number | Post)[] | null; + categories?: (number | Category)[] | null; + meta?: { + title?: string | null; + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ + image?: (number | null) | Media; + description?: string | null; + }; + publishedAt?: string | null; + authors?: (number | User)[] | null; + populatedAuthors?: + | { + id?: string | null; + name?: string | null; + }[] + | null; + /** + * Genereras automatiskt från titeln. + */ + slug: string; + updatedAt: string; + createdAt: string; + _status?: ('draft' | 'published') | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "categories". + */ +export interface Category { + id: number; + title: string; + slug: string; + parent?: (number | null) | Category; + breadcrumbs?: + | { + doc?: (number | null) | Category; + url?: string | null; + label?: string | null; + id?: string | null; + }[] + | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "users". + */ +export interface User { + id: number; + name?: string | null; + updatedAt: string; + createdAt: string; + email: string; + resetPasswordToken?: string | null; + resetPasswordExpiration?: string | null; + salt?: string | null; + hash?: string | null; + loginAttempts?: number | null; + lockUntil?: string | null; + sessions?: + | { + id: string; + createdAt?: string | null; + expiresAt: string; + }[] + | null; + password?: string | null; + collection: 'users'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "redirects". @@ -1615,28 +1570,6 @@ export interface PayloadMigration { */ export interface PagesSelect { title?: T; - hero?: - | T - | { - type?: T; - richText?: T; - links?: - | T - | { - link?: - | T - | { - type?: T; - newTab?: T; - reference?: T; - url?: T; - label?: T; - appearance?: T; - }; - id?: T; - }; - media?: T; - }; layout?: | T | { @@ -1677,7 +1610,6 @@ export interface PagesSelect { description?: T; }; publishedAt?: T; - generateSlug?: T; slug?: T; updatedAt?: T; createdAt?: T; @@ -2273,7 +2205,6 @@ export interface PostsSelect { id?: T; name?: T; }; - generateSlug?: T; slug?: T; updatedAt?: T; createdAt?: T;