EventBuzz_Backend/scripts/setup-goa-8-9-microsite.js

243 lines
8.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Load novel2026-goa-8-9-aug.csv into microsite + agenda for the 8–9 Aug Goa event.
*
* Usage:
* node scripts/setup-goa-8-9-microsite.js [--publish] [--csv=path]
*/
const path = require('path');
const fs = require('fs');
require('dotenv').config({ path: path.join(__dirname, '..', '.env') });
const mongoose = require('mongoose');
const { connectDB } = require('../src/config/database');
const Event = require('../src/models/Event');
const Form = require('../src/models/Form');
const EventStaticMicrosite = require('../src/models/EventStaticMicrosite');
const User = require('../src/models/User');
const { normalizeSubdomain, subdomainAvailability } = require('../src/utils/subdomainAvailability');
const { publishStaticMicrosite } = require('../src/utils/publishStaticMicrosite');
const { parseNovelScheduleCsv } = require('../src/utils/parseNovelScheduleCsv');
const { importNovelScheduleToAgenda } = require('../src/utils/importNovelScheduleAgenda');
const EVENT_ID = '6a4cb75a7475c040cc6f2dd7';
const SUBDOMAIN = 'novel2026-goa-8-9-aug';
const DEFAULT_CSV = path.join(__dirname, '..', '..', 'novel2026-goa-8-9-aug.csv');
const PUBLIC_WEB_BASE = (process.env.PUBLIC_WEB_BASE || 'https://web.eventbuzz.live').replace(/\/$/, '');
const EVENT = {
name: 'NOVEL Lung Health Summit - Goa - 8th & 9th August 2026',
shortPlace: 'Goa',
dateLabel: '8th & 9th August 2026',
dateShort: 'Aug 8–9, 2026',
countdownDate: '2026-08-08',
scheduleDay1: 'August 8, 2026',
scheduleDay2: 'August 9, 2026',
location: 'DoubleTree by Hilton Panjim, Goa',
mapQuery: 'DoubleTree+by+Hilton+Goa+Panaji,+Chimbel,+Goa',
};
function argValue(name, fallback) {
const hit = process.argv.find((a) => a.startsWith(`--${name}=`));
return hit ? hit.split('=').slice(1).join('=').trim() : fallback;
}
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
async function findForm(eventId, type) {
return Form.findOne({ event: eventId, type, 'settings.isActive': { $ne: false } })
.sort({ createdAt: 1 })
.select('_id name')
.lean();
}
async function findContactForm(eventId) {
return Form.findOne({ event: eventId, type: 'other', name: /contact/i, 'settings.isActive': { $ne: false } })
.sort({ createdAt: 1 })
.select('_id name')
.lean();
}
async function findPublishUser() {
const platform = await User.findOne({ platform_admin: 'yes', isActive: { $ne: false } }).sort({ createdAt: 1 });
if (platform) return platform;
const superAdmin = await User.findOne({ role: 'super_admin' }).sort({ createdAt: 1 });
if (superAdmin) return superAdmin;
throw new Error('No user found for publish');
}
function loadScheduleFromCsv(csvPath) {
if (!fs.existsSync(csvPath)) {
throw new Error(`Schedule CSV not found: ${csvPath}`);
}
const text = fs.readFileSync(csvPath, 'utf8');
const { days } = parseNovelScheduleCsv(text, {
dayDates: [EVENT.scheduleDay1, EVENT.scheduleDay2],
});
return days;
}
function applyScheduleToConfig(config, days) {
const next = deepClone(config);
const sections = next.sections || {};
sections.event_schedule = sections.event_schedule || {};
sections.event_schedule.show = sections.event_schedule.show !== false;
sections.event_schedule.heading = sections.event_schedule.heading || 'Event Schedule';
sections.event_schedule.subtitle =
sections.event_schedule.subtitle || 'Scientific programme at DoubleTree by Hilton Panjim, Goa.';
sections.event_schedule.days = days;
next.sections = sections;
return next;
}
function applyEventOverrides(config, eventId, forms, heroBannerUrl) {
const next = deepClone(config);
next.meta = next.meta || {};
next.meta.title = EVENT.name;
next.meta.eventId = String(eventId);
const regUrl = forms.registration
? `${PUBLIC_WEB_BASE}/event/${eventId}/form/${forms.registration._id}`
: `${PUBLIC_WEB_BASE}/event/${eventId}/register`;
const feedbackUrl = forms.feedback
? `${PUBLIC_WEB_BASE}/event/${eventId}/form/${forms.feedback._id}`
: null;
const sections = next.sections || {};
if (sections.hero) {
sections.hero.event_name = `${EVENT.shortPlace} - ${EVENT.dateLabel}`;
sections.hero.date_venue = EVENT.location;
if (heroBannerUrl && sections.hero.image) {
sections.hero.image.url = heroBannerUrl;
}
if (sections.hero.cta) {
sections.hero.cta.url = regUrl;
sections.hero.cta.target = '_blank';
}
if (sections.hero.countdown) {
sections.hero.countdown.date = EVENT.countdownDate;
}
}
if (sections.informationBar?.items) {
for (const item of sections.informationBar.items) {
if (item.label === 'Location') item.value = EVENT.location;
if (item.label === 'Date & Time') {
item.value = EVENT.dateShort;
if (item.calendar) {
item.calendar.title = EVENT.name;
item.calendar.start = EVENT.countdownDate;
item.calendar.end = '2026-08-09';
item.calendar.location = EVENT.location;
}
}
}
}
if (sections.map) {
sections.map.embedUrl = `https://maps.google.com/maps?q=${EVENT.mapQuery}&hl=en&z=15&output=embed`;
}
if (sections.contact && forms.contact) {
sections.contact.show = true;
sections.contact.formId = String(forms.contact._id);
sections.contact.apiBaseUrl = sections.contact.apiBaseUrl || 'https://api.eventbuzz.live/api';
}
if (sections.feedback && feedbackUrl) {
sections.feedback.url = feedbackUrl;
}
if (sections.footer?.links) {
for (const link of sections.footer.links) {
if (link.text && /register/i.test(link.text)) {
link.url = regUrl;
link.target = '_blank';
}
if (link.text && /feedback/i.test(link.text) && feedbackUrl) {
link.url = feedbackUrl;
link.target = '_blank';
}
}
}
next.sections = sections;
return next;
}
async function main() {
const shouldPublish = process.argv.includes('--publish');
const csvPath = argValue('csv', DEFAULT_CSV);
await connectDB();
const event = await Event.findById(EVENT_ID).lean();
if (!event) throw new Error(`Event not found: ${EVENT_ID}`);
const scheduleDays = loadScheduleFromCsv(csvPath);
const agendaResult = await importNovelScheduleToAgenda(EVENT_ID, scheduleDays);
console.log(
`Agenda: deleted ${agendaResult.deleted}, created ${agendaResult.created} session(s) on track ${agendaResult.trackId}`,
);
const existingSite = await EventStaticMicrosite.findOne({ event: EVENT_ID }).populate('template');
if (!existingSite) {
throw new Error(`Microsite not found for event ${EVENT_ID}. Run setup-crest-novel-microsite.js first.`);
}
const heroBannerUrl = existingSite.config?.sections?.hero?.image?.url || null;
const subdomain = normalizeSubdomain(SUBDOMAIN);
const avail = await subdomainAvailability(subdomain, EVENT_ID, existingSite._id?.toString());
if (!avail.available) throw new Error(avail.message || 'Subdomain not available');
const [registration, feedback, contact] = await Promise.all([
findForm(EVENT_ID, 'registration'),
findForm(EVENT_ID, 'feedback'),
findContactForm(EVENT_ID),
]);
let config = applyScheduleToConfig(existingSite.config, scheduleDays);
config = applyEventOverrides(config, EVENT_ID, { registration, feedback, contact }, heroBannerUrl);
const user = shouldPublish ? await findPublishUser() : null;
Object.assign(existingSite, {
subdomain,
config,
updatedBy: user?._id,
});
existingSite.markModified('config');
await existingSite.save();
console.log(`Updated microsite ${existingSite._id}`);
console.log(`Event: ${event.name}`);
console.log(`Subdomain: ${subdomain}`);
console.log(`Template: ${existingSite.template?.slug || existingSite.template}`);
console.log(`CSV: ${csvPath}`);
console.log(`Reg form: ${registration?._id || '(none)'}`);
console.log(`Feedback: ${feedback?._id || '(none)'}`);
console.log(`Contact: ${contact?._id || '(none)'}`);
if (shouldPublish) {
const populated = await EventStaticMicrosite.findById(existingSite._id).populate('template');
const result = await publishStaticMicrosite({
staticMicrosite: populated,
template: populated.template,
userId: user._id,
});
Object.assign(populated, result);
await populated.save();
console.log(`Published: ${result.publicUrl}`);
} else {
console.log('Saved as draft. Re-run with --publish to publish.');
}
await mongoose.disconnect();
}
main().catch((err) => {
console.error(err);
process.exit(1);
});