243 lines
8.4 KiB
JavaScript
243 lines
8.4 KiB
JavaScript
/**
|
||
* 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);
|
||
});
|