334 lines
10 KiB
JavaScript
334 lines
10 KiB
JavaScript
import mongoose from 'mongoose';
|
|
import Series from '../server/models/series.js';
|
|
import Event from '../server/models/event.js';
|
|
import dotenv from 'dotenv';
|
|
|
|
// Load environment variables
|
|
dotenv.config();
|
|
|
|
const MONGODB_URI = process.env.NUXT_MONGODB_URI || process.env.MONGODB_URI;
|
|
|
|
async function addToRemoteDB() {
|
|
try {
|
|
console.log('Connecting to remote MongoDB...');
|
|
await mongoose.connect(MONGODB_URI);
|
|
console.log('✓ Connected');
|
|
|
|
// Check existing series
|
|
const existingSeries = await Series.findOne({ id: 'cooperative-values-into-practice' });
|
|
|
|
if (existingSeries) {
|
|
console.log(`\n✓ Found existing series: ${existingSeries.title}`);
|
|
console.log(` Series _id: ${existingSeries._id}`);
|
|
} else {
|
|
console.log('\nSeries not found, creating new one...');
|
|
const newSeries = new Series({
|
|
id: 'cooperative-values-into-practice',
|
|
title: 'Cooperative Values into Practice',
|
|
description: 'A practical, region-agnostic foundation in cooperative values and governance for game studio founders interested in worker-centric, anti-capitalist models. Structured as a peer-driven workshop emphasizing reciprocal learning and sharing.',
|
|
type: 'workshop_series',
|
|
isVisible: true,
|
|
isActive: true,
|
|
targetCircles: ['founder', 'practitioner'],
|
|
totalEvents: 6,
|
|
createdBy: 'admin@ghostguild.org',
|
|
tickets: {
|
|
enabled: true,
|
|
requiresSeriesTicket: false,
|
|
allowIndividualEventTickets: true,
|
|
currency: 'CAD',
|
|
member: {
|
|
available: true,
|
|
isFree: true,
|
|
price: 0,
|
|
name: 'Member Series Pass',
|
|
description: 'Free access to all sessions for Ghost Guild members.'
|
|
},
|
|
public: {
|
|
available: true,
|
|
name: 'Series Pass',
|
|
description: 'Access to all 6 sessions',
|
|
price: 150,
|
|
quantity: 20,
|
|
sold: 0,
|
|
reserved: 0
|
|
},
|
|
capacity: {
|
|
total: 30,
|
|
reserved: 0
|
|
},
|
|
waitlist: {
|
|
enabled: true,
|
|
maxSize: 15,
|
|
entries: []
|
|
}
|
|
}
|
|
});
|
|
await newSeries.save();
|
|
console.log('✓ Series created');
|
|
}
|
|
|
|
const series = await Series.findOne({ id: 'cooperative-values-into-practice' });
|
|
|
|
// Check existing events
|
|
const existingEvents = await Event.find({
|
|
'series.id': 'cooperative-values-into-practice',
|
|
'series.isSeriesEvent': true
|
|
}).select('title').lean();
|
|
|
|
console.log(`\nCurrent events in series: ${existingEvents.length}`);
|
|
existingEvents.forEach(e => console.log(` - ${e.title}`));
|
|
|
|
// Define the 6 modules
|
|
const baseDate = new Date('2025-11-01T18:00:00.000Z');
|
|
const modulesData = [
|
|
{
|
|
title: 'Module 0: Orientation',
|
|
tagline: 'Welcome to Cooperative Values into Practice',
|
|
description: 'Introduce the goals and format of the program, quick power & identity reflections, Baby Ghosts values, and create group agreements.',
|
|
content: `## Welcome!
|
|
|
|
This orientation session kicks off our 6-month journey exploring cooperative values and governance for game studios.
|
|
|
|
## What We'll Cover
|
|
|
|
- Program goals and format
|
|
- Power & identity reflections
|
|
- Baby Ghosts values introduction
|
|
- Creating our group agreements together
|
|
|
|
## Homework
|
|
|
|
Power Flower exercise to complete before Module 1`,
|
|
position: 1,
|
|
weeksFromPrevious: 0
|
|
},
|
|
{
|
|
title: 'Module 1: Principles',
|
|
tagline: 'Understanding cooperative foundations',
|
|
description: 'Explore the difference between coops and traditional studios, foundational cooperative principles, historical and cultural context, and how they challenge industry norms.',
|
|
content: `## Cooperative Principles
|
|
|
|
Understanding what makes cooperatives different from traditional game studios.
|
|
|
|
## Topics
|
|
|
|
- Coops vs. traditional studios
|
|
- Foundational cooperative principles
|
|
- How cooperative values challenge industry norms
|
|
- Historical and cultural context
|
|
- Coops for Creatives
|
|
|
|
## Activities
|
|
|
|
- Values Reflection exercise
|
|
- Value Mapping workshop`,
|
|
position: 2,
|
|
weeksFromPrevious: 3
|
|
},
|
|
{
|
|
title: 'Module 2: Purpose',
|
|
tagline: 'Alignment, agreement, and shared vision',
|
|
description: 'Learn the difference between alignment, agreement, and false consensus. Reflect on cooperative origin stories, discuss financial needs and capacity, and map collective visions.',
|
|
content: `## Finding Your Cooperative Purpose
|
|
|
|
Moving beyond false consensus to genuine alignment.
|
|
|
|
## Topics
|
|
|
|
- Alignment vs. agreement vs. false consensus
|
|
- Reflecting on cooperative origin stories
|
|
- Discussing financial needs and capacity
|
|
- Mapping collective visions for scale and pace
|
|
- Clarifying roles and expectations
|
|
|
|
## Activities
|
|
|
|
- Origin Stories sharing
|
|
- Solidarity Press exercise
|
|
- "The Talk" - discussing money
|
|
- Scale & Pace Alignment worksheets`,
|
|
position: 3,
|
|
weeksFromPrevious: 4
|
|
},
|
|
{
|
|
title: 'Module 3: Practices Part 1 - Meetings & Decision-Making',
|
|
tagline: 'Democratic processes in action',
|
|
description: 'Move from boss-decides or majority-rules to cooperative approaches. Learn to redesign hierarchical meetings and facilitate inclusive, productive discussions.',
|
|
content: `## Democratic Practices: Meetings
|
|
|
|
Redesigning how we make decisions together.
|
|
|
|
## Topics
|
|
|
|
- Moving from boss-decides to cooperative approaches
|
|
- Redesigning hierarchical meetings
|
|
- Facilitating inclusive, productive meetings
|
|
- Consensus-building techniques
|
|
- Managing power dynamics
|
|
|
|
## Activities
|
|
|
|
- Meeting redesign workshop
|
|
- Facilitation practice
|
|
- Decision-making simulations`,
|
|
position: 4,
|
|
weeksFromPrevious: 4
|
|
},
|
|
{
|
|
title: 'Module 4: Practices Part 2 - Finances & Governance',
|
|
tagline: 'Transparent systems for cooperative work',
|
|
description: 'Design transparent financial practices and systems, reframe disagreement as valuable information, and establish clear governance structures.',
|
|
content: `## Democratic Practices: Money & Structure
|
|
|
|
Building transparent financial and governance systems.
|
|
|
|
## Topics
|
|
|
|
- Designing transparent financial practices
|
|
- Open book management
|
|
- Reframing disagreement as valuable information
|
|
- Establishing clear governance systems
|
|
- Creating accountability without hierarchy
|
|
|
|
## Activities
|
|
|
|
- Financial transparency workshop
|
|
- Governance structure design
|
|
- Conflict as data reframing`,
|
|
position: 5,
|
|
weeksFromPrevious: 4
|
|
},
|
|
{
|
|
title: 'Module 5: Pathways Forward',
|
|
tagline: 'Your cooperative journey continues',
|
|
description: 'Integrate learnings, share next steps, create accountability partnerships, and celebrate the work done together.',
|
|
content: `## Moving Forward Together
|
|
|
|
Bringing it all together and planning your next steps.
|
|
|
|
## Topics
|
|
|
|
- Integrating everything we've learned
|
|
- Individual and collective action plans
|
|
- Creating accountability partnerships
|
|
- Resources for ongoing learning
|
|
- Building a community of practice
|
|
|
|
## Activities
|
|
|
|
- Action planning workshop
|
|
- Accountability partner matching
|
|
- Celebration and reflection`,
|
|
position: 6,
|
|
weeksFromPrevious: 4
|
|
}
|
|
];
|
|
|
|
let currentDate = new Date(baseDate);
|
|
let created = 0;
|
|
let updated = 0;
|
|
|
|
for (const moduleData of modulesData) {
|
|
const startDate = new Date(currentDate);
|
|
const endDate = new Date(startDate);
|
|
endDate.setHours(endDate.getHours() + 2);
|
|
|
|
const eventPayload = {
|
|
title: moduleData.title,
|
|
tagline: moduleData.tagline,
|
|
description: moduleData.description,
|
|
content: moduleData.content,
|
|
startDate,
|
|
endDate,
|
|
eventType: 'workshop',
|
|
location: '#ghost-guild-workshops',
|
|
isOnline: true,
|
|
isVisible: true,
|
|
membersOnly: false,
|
|
series: {
|
|
id: series.id,
|
|
title: series.title,
|
|
description: series.description,
|
|
type: series.type,
|
|
position: moduleData.position,
|
|
totalEvents: 6,
|
|
isSeriesEvent: true
|
|
},
|
|
tickets: {
|
|
enabled: true,
|
|
requiresSeriesTicket: false,
|
|
seriesTicketReference: series._id,
|
|
currency: 'CAD',
|
|
member: {
|
|
available: true,
|
|
isFree: true,
|
|
price: 0,
|
|
name: 'Member Ticket',
|
|
description: 'Free for Ghost Guild members'
|
|
},
|
|
public: {
|
|
available: true,
|
|
name: 'Single Session Ticket',
|
|
description: 'Attend this individual session',
|
|
price: 30,
|
|
quantity: 10
|
|
},
|
|
capacity: {
|
|
total: 30
|
|
},
|
|
waitlist: {
|
|
enabled: true,
|
|
maxSize: 10
|
|
}
|
|
},
|
|
targetCircles: ['founder', 'practitioner'],
|
|
registrationRequired: true,
|
|
createdBy: 'admin@ghostguild.org'
|
|
};
|
|
|
|
const existing = await Event.findOne({
|
|
title: moduleData.title,
|
|
'series.id': 'cooperative-values-into-practice'
|
|
});
|
|
|
|
if (existing) {
|
|
await Event.findByIdAndUpdate(existing._id, eventPayload);
|
|
updated++;
|
|
console.log(` ✓ Updated: ${moduleData.title}`);
|
|
} else {
|
|
const newEvent = new Event(eventPayload);
|
|
await newEvent.save();
|
|
created++;
|
|
console.log(` ✓ Created: ${moduleData.title}`);
|
|
}
|
|
|
|
// Move to next date
|
|
if (moduleData.weeksFromPrevious > 0) {
|
|
currentDate.setDate(currentDate.getDate() + (moduleData.weeksFromPrevious * 7));
|
|
}
|
|
}
|
|
|
|
console.log(`\n✅ Success!`);
|
|
console.log(` Created: ${created} events`);
|
|
console.log(` Updated: ${updated} events`);
|
|
|
|
// Verify final count
|
|
const finalEvents = await Event.find({
|
|
'series.id': 'cooperative-values-into-practice',
|
|
'series.isSeriesEvent': true
|
|
}).select('title series.position').sort({ 'series.position': 1 }).lean();
|
|
|
|
console.log(`\n📋 Total events in series: ${finalEvents.length}`);
|
|
finalEvents.forEach(e => {
|
|
console.log(` ${e.series.position}. ${e.title}`);
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
} finally {
|
|
await mongoose.connection.close();
|
|
}
|
|
}
|
|
|
|
addToRemoteDB();
|