generated from hack4impact-uiuc/mern-template
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Create basic endpoint skeleton * get endpoint 500 error * Fix routing * Get member endpoint to work * Return more fields from endpoint * Return object id from endpoint * Add filterSensitiveInfo util * Give all non-required Member fields a default of null * Move passport-setup to utils * Remove console.log * Add members endpoints * Fix filterSensitiveInfo util * Use passport-setup.js in utils * Use auth endpoint * Move /api/auth/user to /api/members/current * Add omit fields to GET /:memberId * Change current user endpoint in frontend * Add more auth utils * Use isDirector from module in members routes * Change level default in model back to TBD * Add level priority explanation * Add detailed permission checking in members endpoint * Fix difference function * Fix typos in user-utils * Add _id as neverEditable field * Fix allFields not being checked correctly * Filter viewable fields when returning from PUT * Pull enum options from backend * Add status options to endpoint * Disable dropdowns * Add labels to fields * Create wrapper for getting member by ID * Add boolean selector * Add number fields * Add fields for basic string attributes * Retrieve schema type from DB * Move preprocessing to backend * Fix enum type detection * Remove duplicated code * Fix attribute change error * Run formatter * Remove warnings * Format client * Populate edit fields from DB * Add types to props * Run formatter * Remove alert * Run formatter * Get permissions from backend * Disable input boxes if missing permissions * Add enum dropdowns * Format client * Remove user ID override * Change to ES6 defaults * Remove unused package * Change var to let * Concisen member options endpoint * Delete env file * Unexport schema * Use concise property iteration * Make /options endpoint concise * Remove unneeded exports * Capitalize constant * Shorten attribute change callback * Run formatter * Turn off default-props in linter * Fix var name typo * Change member page routing * Run formatter * Use useParams hook * Change object syntax * Run formatter * Start creating tool to transfer data * Consolidate envs and clean up app.js * Fix yarn test not using .env * Add lint-staged pre-commit hook (#27) * Add lint-staged pre-commit hook * Format "unstaged" files * Sync prettier versions * Format all files using new Prettier config * Finish writing tool * Format remaining fields * Check for member uniqueness * Fix enum formatting * Run formatter * Run formatter * Run format with new hook * Remove duplicate of Profile.js Co-authored-by: ishaansharma <[email protected]> Co-authored-by: Jeffrey Tang <[email protected]> Co-authored-by: Yousef Ahmed <[email protected]>
- Loading branch information
Showing
7 changed files
with
248 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"singleQuote": true, | ||
"tabWidth": 2, | ||
"trailingComma": "all" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
const dotenv = require('dotenv'); | ||
const path = require('path'); | ||
dotenv.config({ | ||
path: path.resolve(__dirname, '../src/.env'), | ||
}); | ||
|
||
const csv = require('csvtojson'); | ||
const Member = require('../src/models/member'); | ||
require('../src/utils/mongo-setup'); | ||
|
||
// Regex to capture each part the grad sem year column | ||
// Ex: "Fall 2020 (Freshman)" captures "Fall", "2020", "Freshman" | ||
const REGEX_GRAD_SEM_YEAR = /([A-Za-z]+)\s([0-9]+)\s+\(([A-Za-z\s+]+)\)/; | ||
const REGEX_GENERATION_YEAR = /([A-Za-z]+)\s([0-9]+)/; | ||
|
||
// Download the CSV file onto your machine and use abs path | ||
const csvFilePath = 'C:\\Users\\mattw\\Downloads\\FA20Membership.csv'; | ||
|
||
// These are the columns that requie special processing. I.e. the data can't be directly copy and pasted | ||
const SPECIAL_COLUMNS_ENUM = { | ||
NAME: 'NAME', | ||
GRAD_SEM_YEAR: 'GRAD_SEM_YEAR', | ||
GENERATION: 'GENERATION', | ||
BIRTHDATE: 'BIRTHDATE', | ||
DUES: 'DUES', | ||
}; | ||
|
||
// These are the columns that are an enum value. Formatting is done to ensure they meet the backend options. | ||
const ENUM_COLUMNS_ENUM = { | ||
LOCATION: 'location', | ||
ROLE: 'role', | ||
LEVEL: 'level', | ||
STATUS: 'status', | ||
}; | ||
|
||
// The names of the columns in order from left to right. Name each column according to it's DB field name except for special fields | ||
const columns = [ | ||
SPECIAL_COLUMNS_ENUM.NAME, | ||
'email', | ||
'phone', | ||
'netID', | ||
'UIN', | ||
'major', | ||
SPECIAL_COLUMNS_ENUM.BIRTHDATE, | ||
'github', | ||
'snapchat', | ||
'instagram', | ||
SPECIAL_COLUMNS_ENUM.GRAD_SEM_YEAR, | ||
SPECIAL_COLUMNS_ENUM.GENERATION, | ||
ENUM_COLUMNS_ENUM.LOCATION, | ||
ENUM_COLUMNS_ENUM.ROLE, | ||
ENUM_COLUMNS_ENUM.LEVEL, | ||
ENUM_COLUMNS_ENUM.STATUS, | ||
SPECIAL_COLUMNS_ENUM.DUES, | ||
]; | ||
const specialColumns = Object.values(SPECIAL_COLUMNS_ENUM); | ||
const enumColumns = Object.values(ENUM_COLUMNS_ENUM); | ||
|
||
async function main() { | ||
// Data is array of JSON objects, where each key is field1, field2, ..., field19. | ||
const sheetData = await csv({ noheader: true }).fromFile(csvFilePath); | ||
|
||
// Remove the header row | ||
sheetData.shift(); | ||
sheetData.forEach((memberJSON) => saveJSONIntoDB(memberJSON)); | ||
} | ||
|
||
function saveJSONIntoDB(memberJSON) { | ||
try { | ||
const model = createModelFromJSON(memberJSON); | ||
insertModelIntoDB(model); | ||
} catch (error) { | ||
console.log( | ||
`Could not add member to database. \n Error: ${error} \n Data: ${memberJSON}`, | ||
); | ||
} | ||
} | ||
|
||
function createModelFromJSON(memberJSON) { | ||
const memberObj = {}; | ||
|
||
for (let i = 0; i < columns.length; i++) { | ||
const fieldLabel = `field${i + 1}`; | ||
if (specialColumns.includes(columns[i])) { | ||
processSpecialField(memberObj, columns[i], memberJSON[fieldLabel]); | ||
} else if (enumColumns.includes(columns[i])) { | ||
processEnumField(memberObj, columns[i], memberJSON[fieldLabel]); | ||
} else { | ||
processSimpleField(memberObj, columns[i], memberJSON[fieldLabel]); | ||
} | ||
} | ||
|
||
return memberObj; | ||
} | ||
|
||
async function insertModelIntoDB(model) { | ||
const duplicateUsers = await Member.find({ email: model.email }); | ||
if (duplicateUsers.length > 0) | ||
console.log(`Member ${model.firstName} ${model.lastName} already in DB!`); | ||
else Member.create(model); | ||
} | ||
|
||
function processSimpleField(memberObj, fieldName, fieldValue) { | ||
memberObj[fieldName] = fieldValue; | ||
} | ||
|
||
function processSpecialField(memberObj, fieldName, fieldValue) { | ||
switch (fieldName) { | ||
case SPECIAL_COLUMNS_ENUM.NAME: | ||
processName(memberObj, fieldValue); | ||
break; | ||
case SPECIAL_COLUMNS_ENUM.GRAD_SEM_YEAR: | ||
prcoessGradSemYear(memberObj, fieldValue); | ||
break; | ||
case SPECIAL_COLUMNS_ENUM.GENERATION: | ||
processGeneration(memberObj, fieldValue); | ||
break; | ||
case SPECIAL_COLUMNS_ENUM.BIRTHDATE: | ||
processBirthdate(memberObj, fieldValue); | ||
break; | ||
case SPECIAL_COLUMNS_ENUM.DUES: | ||
processDues(memberObj, fieldValue); | ||
break; | ||
} | ||
} | ||
|
||
/** | ||
* The spreadsheet stores name as one field, yet the DB stores first and last. We need | ||
* to split the name so it can be stored in the DB. | ||
*/ | ||
function processName(memberObj, nameValue) { | ||
const nameComponents = nameValue.split(' '); | ||
if (nameComponents.length != 2) | ||
throw `${nameValue}, has an unparsable name. They must be entered manually.`; | ||
|
||
[memberObj['firstName'], memberObj['lastName']] = nameComponents; | ||
} | ||
|
||
/** | ||
* This field contains class standing, grad year, and grad month | ||
*/ | ||
function prcoessGradSemYear(memberObj, gradSemYearValue) { | ||
let match = gradSemYearValue.match(REGEX_GRAD_SEM_YEAR); | ||
if (!match || match.length != 4) | ||
throw `Could not parse Grad Semester/Year column (${gradSemYearValue}).`; | ||
|
||
match = match.slice(1, 4); | ||
[ | ||
memberObj['gradSemester'], | ||
memberObj['gradYear'], | ||
memberObj['classStanding'], | ||
] = formatEnumFields(match); | ||
} | ||
|
||
function processGeneration(memberObj, generationValue) { | ||
let match = generationValue.match(REGEX_GENERATION_YEAR); | ||
if (!match || match.length != 3) | ||
throw `Could not parse Generation Year column (${generationValue}).`; | ||
|
||
match = match.slice(1, 3); | ||
[ | ||
memberObj['generationSemester'], | ||
memberObj['generationYear'], | ||
] = formatEnumFields(match); | ||
} | ||
|
||
function processBirthdate(memberObj, birthdateValue) { | ||
memberObj['birthdate'] = Date.parse(birthdateValue); | ||
} | ||
|
||
function processEnumField(memberObj, fieldName, enumValue) { | ||
memberObj[fieldName] = formatEnumField(enumValue); | ||
} | ||
|
||
/** | ||
* Formats the enum fields as follows: | ||
* - Replace spaces and dashes with underscores | ||
* - Captialize entire string | ||
*/ | ||
function formatEnumField(enumValue) { | ||
let underscoredValue = enumValue.replace(/-|\s/g, '_'); | ||
return underscoredValue.toUpperCase(); | ||
} | ||
|
||
function formatEnumFields(enumValues) { | ||
return enumValues.map((val) => formatEnumField(val)); | ||
} | ||
|
||
function processDues(memberObj, duesValue) { | ||
memberObj['areDuesPaid'] = ['Y', 'YES', 'T', 'TRUE'].includes( | ||
duesValue.toUpperCase(), | ||
); | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -913,6 +913,11 @@ [email protected]: | |
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" | ||
integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== | ||
|
||
bluebird@^3.5.1: | ||
version "3.7.2" | ||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" | ||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== | ||
|
||
[email protected]: | ||
version "1.18.3" | ||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" | ||
|
@@ -1347,6 +1352,15 @@ cssstyle@^2.0.0: | |
dependencies: | ||
cssom "~0.3.6" | ||
|
||
csvtojson@^2.0.10: | ||
version "2.0.10" | ||
resolved "https://registry.yarnpkg.com/csvtojson/-/csvtojson-2.0.10.tgz#11e7242cc630da54efce7958a45f443210357574" | ||
integrity sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ== | ||
dependencies: | ||
bluebird "^3.5.1" | ||
lodash "^4.17.3" | ||
strip-bom "^2.0.0" | ||
|
||
dashdash@^1.12.0: | ||
version "1.14.1" | ||
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" | ||
|
@@ -2648,6 +2662,11 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: | |
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" | ||
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= | ||
|
||
is-utf8@^0.2.0: | ||
version "0.2.1" | ||
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" | ||
integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= | ||
|
||
is-windows@^1.0.2: | ||
version "1.0.2" | ||
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" | ||
|
@@ -3285,7 +3304,7 @@ lodash.sortby@^4.7.0: | |
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" | ||
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= | ||
|
||
lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20: | ||
lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.3: | ||
version "4.17.20" | ||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" | ||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== | ||
|
@@ -4757,6 +4776,13 @@ strip-ansi@^6.0.0: | |
dependencies: | ||
ansi-regex "^5.0.0" | ||
|
||
strip-bom@^2.0.0: | ||
version "2.0.0" | ||
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" | ||
integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= | ||
dependencies: | ||
is-utf8 "^0.2.0" | ||
|
||
strip-bom@^4.0.0: | ||
version "4.0.0" | ||
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.