add: Layout, working permissions for papers

This commit is contained in:
Dominik Natter
2025-03-26 20:56:56 +01:00
parent c5c9cc37af
commit 6951e662c9
12 changed files with 308 additions and 146 deletions

View File

@@ -23,15 +23,7 @@ export const Media: CollectionConfig = {
type: 'text',
//required: true,
},
{
name: 'caption',
type: 'richText',
editor: lexicalEditor({
features: ({ rootFeatures }) => {
return [...rootFeatures, FixedToolbarFeature(), InlineToolbarFeature()]
},
}),
},
],
upload: {
// Upload to the public/media directory in Next.js making them publicly accessible even outside of Payload

View File

@@ -1,133 +1,154 @@
import type { CollectionConfig } from 'payload'
import type { CollectionConfig } from "payload";
export const Papers: CollectionConfig = {
slug: 'papers',
slug: "papers",
labels: {
singular: 'Diplomarbeit',
plural: 'Diplomarbeiten',
singular: "Diplomarbeit",
plural: "Diplomarbeiten",
},
access: {
create: ({ req: { user } }) => {
return Boolean(user?.type == "admin") // <-- Check if the user is authenticated
},
delete: ({ req: { user } }) => {
return Boolean(user?.type == "admin") // <-- Check if the user is authenticated
},
update: async ({ req: { user }, id, findByID }) => {
if (user?.type == "admin") return true; // Admins can update any paper
create: ({ req: { user } }) => Boolean(user?.type === "admin"),
delete: ({ req: { user } }) => Boolean(user?.type === "admin"),
update: async ({ req: { user, payload }, id }) => {
if (user?.type === "admin") return true;
const paper = await findByID({ collection: 'papers', id });
return paper.authors.some(author => author.user === user.id); // Check if the user is an author
if (!user || !id) return false; // Explicitly handle missing ID
const paper = await payload.findByID({
collection: 'papers',
id,
depth: 1,
});
if (!paper) return false;
return paper.authors.some((author: any) => author.user.id === user.id);
},
},
admin: {
useAsTitle: 'title',
useAsTitle: "title",
},
fields: [
{
name: 'title',
type: 'text',
name: "title",
type: "text",
required: true,
},
{
name: 'issue',
label: 'Problemstellung',
type: 'textarea',
name: "year",
type: "text",
required: true,
},
{
name: 'goal',
label: 'Zielsetzung',
type: 'textarea',
name: "issue",
label: "Problemstellung",
type: "textarea",
required: true,
},
{
name: 'technologies',
type: 'array',
name: "goal",
label: "Zielsetzung",
type: "textarea",
required: true,
},
{
name: "result",
label: "Ergebnis",
type: "textarea",
required: true,
},
{
name: "technologies",
type: "array",
fields: [
{
name: 'technology',
type: 'relationship',
relationTo: 'technologies',
name: "technology",
type: "relationship",
relationTo: "technologies",
required: true,
},
{
name: 'description',
type: 'text',
name: "description",
type: "text",
required: true,
admin: {
placeholder: '... wurde für das Frontend verwendet',
}
placeholder: "... wurde für das Frontend verwendet",
},
},
],
},
{
name: 'prototype',
type: 'group',
name: "prototype",
type: "group",
fields: [
{
name: 'image',
type: 'upload',
relationTo: 'media',
name: "image",
type: "upload",
relationTo: "media",
required: true,
},
{
name: 'description',
type: 'text',
name: "description",
type: "text",
required: true,
},
],
},
{
name: 'authors',
type: 'array',
label: 'Projektmitglieder',
name: "authors",
type: "array",
label: "Projektmitglieder",
required: true,
fields: [
{
name: 'profilePicture',
type: 'upload',
relationTo: 'media',
name: "profilePicture",
type: "upload",
relationTo: "media",
required: true,
},
{
name: 'user',
type: 'relationship',
relationTo: 'users',
name: "user",
type: "relationship",
relationTo: "users",
required: true,
},
{
name: 'position',
type: 'select',
name: "position",
type: "select",
required: true,
options: [
{
label: 'Projektleiter (PL)',
value: 'leader',
label: "Projektleiter (PL)",
value: "leader",
},
{
label: 'Projektmitarbeiter (PM)',
value: 'member',
label: "Projektmitarbeiter (PM)",
value: "member",
},
],
},
{
name: 'description',
type: 'text',
name: "description",
type: "text",
required: true,
},
],
validate: (authors) => {
// @ts-ignore
const leaders = authors.filter(author => author.position === 'leader')
const leaders = authors.filter(
(author) => author.position === "leader",
);
if (leaders.length > 1) {
return 'Only one author can be the project leader.'
return "Only one author can be the project leader.";
}
return true
return true;
},
},
],
}
};

View File

@@ -1,6 +1,11 @@
import type { CollectionConfig } from 'payload'
import path from 'path'
import { fileURLToPath } from 'url'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
export const Technologies: CollectionConfig = {
slug: 'technologies',
labels: {
@@ -11,7 +16,10 @@ export const Technologies: CollectionConfig = {
useAsTitle: 'name',
},
access: {
read: () => true,
create: ({ req: { user } }) => Boolean(user),
update: ({ req: { user } }) => Boolean(user?.type === "admin"),
delete: ({ req: { user } }) => Boolean(user?.type === "admin"),
},
fields: [
{
@@ -24,11 +32,22 @@ export const Technologies: CollectionConfig = {
type: 'textarea',
required: true,
},
{
name: 'icon',
type: 'upload',
relationTo: 'media',
required: true,
},
],
upload: {
// Upload to the public/media directory in Next.js making them publicly accessible even outside of Payload
staticDir: path.resolve(dirname, '../../public/technology-icons'),
adminThumbnail: 'thumbnail',
focalPoint: true,
imageSizes: [
{
name: 'thumbnail',
width: 300,
},
{
name: 'square',
width: 500,
height: 500,
},
],
},
}