mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-18 02:44:12 +00:00
- Add 5 new collections: SocialPlatforms, SocialAccounts, CommunityInteractions, CommunityTemplates, CommunityRules - Add communityRole field to Users collection - Add YouTube API client for comment sync - Add Claude AI service for sentiment analysis - Add API endpoints: /api/community/sync-comments, /api/community/reply - Add communityAccess.ts for role-based access control - Add migrations for all new tables and community_role enum fix Fix: Make audit hooks non-blocking to prevent user save timeout Dependencies: @anthropic-ai/sdk, googleapis Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
262 lines
7 KiB
TypeScript
262 lines
7 KiB
TypeScript
// src/collections/CommunityRules.ts
|
|
|
|
import type { CollectionConfig } from 'payload'
|
|
import { isCommunityManager, hasCommunityAccess } from '../lib/communityAccess'
|
|
|
|
/**
|
|
* CommunityRules Collection
|
|
*
|
|
* Auto-Regeln für Community-Interaktionen basierend auf Keywords, Sentiment etc.
|
|
* Teil des Community Management Systems.
|
|
*/
|
|
export const CommunityRules: CollectionConfig = {
|
|
slug: 'community-rules',
|
|
labels: {
|
|
singular: 'Community Rule',
|
|
plural: 'Community Rules',
|
|
},
|
|
admin: {
|
|
group: 'Community',
|
|
useAsTitle: 'name',
|
|
defaultColumns: ['name', 'trigger.type', 'isActive', 'priority'],
|
|
},
|
|
access: {
|
|
read: hasCommunityAccess,
|
|
create: isCommunityManager,
|
|
update: isCommunityManager,
|
|
delete: isCommunityManager,
|
|
},
|
|
fields: [
|
|
{
|
|
type: 'row',
|
|
fields: [
|
|
{
|
|
name: 'name',
|
|
type: 'text',
|
|
required: true,
|
|
label: 'Name',
|
|
admin: { width: '50%' },
|
|
},
|
|
{
|
|
name: 'priority',
|
|
type: 'number',
|
|
required: true,
|
|
defaultValue: 100,
|
|
label: 'Priorität',
|
|
admin: {
|
|
width: '25%',
|
|
description: 'Niedrigere Zahl = höhere Priorität',
|
|
},
|
|
},
|
|
{
|
|
name: 'isActive',
|
|
type: 'checkbox',
|
|
label: 'Aktiv',
|
|
defaultValue: true,
|
|
admin: { width: '25%' },
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'description',
|
|
type: 'textarea',
|
|
label: 'Beschreibung',
|
|
admin: { rows: 2 },
|
|
},
|
|
|
|
// Scope
|
|
{
|
|
type: 'row',
|
|
fields: [
|
|
{
|
|
name: 'channel',
|
|
type: 'relationship',
|
|
relationTo: 'youtube-channels',
|
|
label: 'Kanal (optional)',
|
|
admin: {
|
|
width: '50%',
|
|
description: 'Leer = alle Kanäle',
|
|
},
|
|
},
|
|
{
|
|
name: 'platforms',
|
|
type: 'relationship',
|
|
relationTo: 'social-platforms',
|
|
hasMany: true,
|
|
label: 'Plattformen',
|
|
admin: {
|
|
width: '50%',
|
|
description: 'Leer = alle Plattformen',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
|
|
// Trigger
|
|
{
|
|
name: 'trigger',
|
|
type: 'group',
|
|
label: 'Trigger',
|
|
fields: [
|
|
{
|
|
name: 'type',
|
|
type: 'select',
|
|
required: true,
|
|
label: 'Trigger-Typ',
|
|
options: [
|
|
{ label: 'Keyword Match', value: 'keyword' },
|
|
{ label: 'Sentiment', value: 'sentiment' },
|
|
{ label: 'Frage erkannt', value: 'question_detected' },
|
|
{ label: 'Medizinisch erkannt', value: 'medical_detected' },
|
|
{ label: 'Influencer', value: 'influencer' },
|
|
{ label: 'Alle neuen', value: 'all_new' },
|
|
{ label: 'Enthält Link', value: 'contains_link' },
|
|
{ label: 'Enthält Email', value: 'contains_email' },
|
|
],
|
|
},
|
|
{
|
|
name: 'keywords',
|
|
type: 'array',
|
|
label: 'Keywords',
|
|
admin: {
|
|
condition: (data, siblingData) => siblingData?.type === 'keyword',
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'keyword',
|
|
type: 'text',
|
|
required: true,
|
|
label: 'Keyword',
|
|
},
|
|
{
|
|
name: 'matchType',
|
|
type: 'select',
|
|
label: 'Match-Typ',
|
|
options: [
|
|
{ label: 'Enthält', value: 'contains' },
|
|
{ label: 'Exakt', value: 'exact' },
|
|
{ label: 'Regex', value: 'regex' },
|
|
],
|
|
defaultValue: 'contains',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'sentimentValues',
|
|
type: 'select',
|
|
hasMany: true,
|
|
label: 'Sentiment-Werte',
|
|
options: [
|
|
{ label: 'Positiv', value: 'positive' },
|
|
{ label: 'Negativ', value: 'negative' },
|
|
{ label: 'Neutral', value: 'neutral' },
|
|
{ label: 'Frage', value: 'question' },
|
|
],
|
|
admin: {
|
|
condition: (data, siblingData) => siblingData?.type === 'sentiment',
|
|
},
|
|
},
|
|
{
|
|
name: 'influencerMinFollowers',
|
|
type: 'number',
|
|
label: 'Min. Follower',
|
|
defaultValue: 10000,
|
|
admin: {
|
|
condition: (data, siblingData) => siblingData?.type === 'influencer',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
|
|
// Actions
|
|
{
|
|
name: 'actions',
|
|
type: 'array',
|
|
label: 'Aktionen',
|
|
required: true,
|
|
minRows: 1,
|
|
fields: [
|
|
{
|
|
type: 'row',
|
|
fields: [
|
|
{
|
|
name: 'action',
|
|
type: 'select',
|
|
required: true,
|
|
label: 'Aktion',
|
|
options: [
|
|
{ label: 'Priorität setzen', value: 'set_priority' },
|
|
{ label: 'Zuweisen', value: 'assign_to' },
|
|
{ label: 'Flag setzen', value: 'set_flag' },
|
|
{ label: 'Template vorschlagen', value: 'suggest_template' },
|
|
{ label: 'Notification senden', value: 'send_notification' },
|
|
{ label: 'Medical Flag', value: 'flag_medical' },
|
|
{ label: 'Eskalieren', value: 'escalate' },
|
|
{ label: 'Als Spam markieren', value: 'mark_spam' },
|
|
{ label: 'Deadline setzen', value: 'set_deadline' },
|
|
],
|
|
admin: { width: '40%' },
|
|
},
|
|
{
|
|
name: 'value',
|
|
type: 'text',
|
|
label: 'Wert',
|
|
admin: {
|
|
width: '40%',
|
|
description: 'Priority: urgent/high/normal/low, Deadline: Stunden',
|
|
},
|
|
},
|
|
{
|
|
name: 'targetUser',
|
|
type: 'relationship',
|
|
relationTo: 'users',
|
|
label: 'User',
|
|
admin: {
|
|
width: '20%',
|
|
condition: (data, siblingData) =>
|
|
['assign_to', 'send_notification'].includes(siblingData?.action || ''),
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'targetTemplate',
|
|
type: 'relationship',
|
|
relationTo: 'community-templates',
|
|
label: 'Template',
|
|
admin: {
|
|
condition: (data, siblingData) => siblingData?.action === 'suggest_template',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
|
|
// Stats
|
|
{
|
|
name: 'stats',
|
|
type: 'group',
|
|
label: 'Statistiken',
|
|
fields: [
|
|
{
|
|
type: 'row',
|
|
fields: [
|
|
{
|
|
name: 'timesTriggered',
|
|
type: 'number',
|
|
label: 'Ausgelöst',
|
|
defaultValue: 0,
|
|
admin: { width: '50%', readOnly: true },
|
|
},
|
|
{
|
|
name: 'lastTriggeredAt',
|
|
type: 'date',
|
|
label: 'Zuletzt ausgelöst',
|
|
admin: { width: '50%', readOnly: true },
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
timestamps: true,
|
|
}
|