Updates to profile
This commit is contained in:
parent
1b8dacf92a
commit
970b185151
16 changed files with 652 additions and 1585 deletions
163
scripts/migrate-profile-fields.js
Normal file
163
scripts/migrate-profile-fields.js
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/**
|
||||
* Migration Script: Profile Fields Restructure
|
||||
*
|
||||
* This script migrates member data from the old schema to the new schema:
|
||||
* - Removes `skills` field
|
||||
* - Converts `offering` from String to { text: String, tags: [String] }
|
||||
* - Converts `lookingFor` from String to { text: String, tags: [String] }
|
||||
* - Converts `peerSupport.topics` to `peerSupport.skillTopics` and `peerSupport.supportTopics`
|
||||
* - Removes `privacy.skills`
|
||||
*/
|
||||
|
||||
import mongoose from 'mongoose';
|
||||
import Member from '../server/models/member.js';
|
||||
import { connectDB } from '../server/utils/mongoose.js';
|
||||
|
||||
// Curated list of conversational support topics
|
||||
const CONVERSATIONAL_TOPICS = [
|
||||
'Co-founder relationships',
|
||||
'Burnout prevention',
|
||||
'Impostor syndrome',
|
||||
'Work-life boundaries',
|
||||
'Conflict resolution',
|
||||
'General chat & support',
|
||||
];
|
||||
|
||||
async function migrateProfileFields() {
|
||||
try {
|
||||
await connectDB();
|
||||
console.log('Connected to database');
|
||||
|
||||
// Find all members
|
||||
const members = await Member.find({});
|
||||
console.log(`Found ${members.length} members to migrate`);
|
||||
|
||||
let migratedCount = 0;
|
||||
let skippedCount = 0;
|
||||
|
||||
for (const member of members) {
|
||||
let needsUpdate = false;
|
||||
const updates = {};
|
||||
|
||||
// Migrate skills -> offering.tags (if offering doesn't have tags yet)
|
||||
if (member.skills && member.skills.length > 0) {
|
||||
console.log(`\nMember ${member.name} (${member.email}):`);
|
||||
console.log(` - Has skills: ${member.skills.join(', ')}`);
|
||||
|
||||
// If offering is still a string, convert it and add skills as tags
|
||||
if (typeof member.offering === 'string') {
|
||||
updates['offering'] = {
|
||||
text: member.offering || '',
|
||||
tags: member.skills, // Move skills to offering tags
|
||||
};
|
||||
console.log(` - Migrating skills to offering.tags`);
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
// Remove skills field
|
||||
updates.$unset = { skills: 1 };
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
// Migrate offering from string to object (if not already done)
|
||||
if (typeof member.offering === 'string' && !updates['offering']) {
|
||||
updates['offering'] = {
|
||||
text: member.offering || '',
|
||||
tags: [],
|
||||
};
|
||||
console.log(` - Converting offering to object structure`);
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
// Migrate lookingFor from string to object
|
||||
if (typeof member.lookingFor === 'string') {
|
||||
updates['lookingFor'] = {
|
||||
text: member.lookingFor || '',
|
||||
tags: [],
|
||||
};
|
||||
console.log(` - Converting lookingFor to object structure`);
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
// Migrate peer support topics
|
||||
if (member.peerSupport?.topics && member.peerSupport.topics.length > 0) {
|
||||
const skillTopics = [];
|
||||
const supportTopics = [];
|
||||
|
||||
// Split topics into skill-based and conversational
|
||||
for (const topic of member.peerSupport.topics) {
|
||||
if (CONVERSATIONAL_TOPICS.includes(topic)) {
|
||||
supportTopics.push(topic);
|
||||
} else {
|
||||
skillTopics.push(topic);
|
||||
}
|
||||
}
|
||||
|
||||
updates['peerSupport.skillTopics'] = skillTopics;
|
||||
updates['peerSupport.supportTopics'] = supportTopics;
|
||||
updates['$unset'] = {
|
||||
...(updates['$unset'] || {}),
|
||||
'peerSupport.topics': 1
|
||||
};
|
||||
|
||||
console.log(` - Splitting peer support topics:`);
|
||||
console.log(` Skill topics: ${skillTopics.join(', ') || 'none'}`);
|
||||
console.log(` Support topics: ${supportTopics.join(', ') || 'none'}`);
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
// Remove privacy.skills if it exists
|
||||
if (member.privacy?.skills) {
|
||||
updates['$unset'] = {
|
||||
...(updates['$unset'] || {}),
|
||||
'privacy.skills': 1
|
||||
};
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
// Apply updates
|
||||
if (needsUpdate) {
|
||||
const updateOps = { ...updates };
|
||||
const unsetOps = updateOps.$unset;
|
||||
delete updateOps.$unset;
|
||||
|
||||
const finalUpdate = {};
|
||||
if (Object.keys(updateOps).length > 0) {
|
||||
finalUpdate.$set = updateOps;
|
||||
}
|
||||
if (unsetOps && Object.keys(unsetOps).length > 0) {
|
||||
finalUpdate.$unset = unsetOps;
|
||||
}
|
||||
|
||||
await Member.updateOne({ _id: member._id }, finalUpdate);
|
||||
console.log(` ✓ Updated`);
|
||||
migratedCount++;
|
||||
} else {
|
||||
skippedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n=== Migration Complete ===');
|
||||
console.log(`Total members: ${members.length}`);
|
||||
console.log(`Migrated: ${migratedCount}`);
|
||||
console.log(`Skipped (already migrated): ${skippedCount}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Migration error:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
await mongoose.connection.close();
|
||||
console.log('\nDatabase connection closed');
|
||||
}
|
||||
}
|
||||
|
||||
// Run migration
|
||||
migrateProfileFields()
|
||||
.then(() => {
|
||||
console.log('\n✓ Migration script completed successfully');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('\n✗ Migration script failed:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue