Skip to content

Commit

Permalink
stable v1
Browse files Browse the repository at this point in the history
* created catalog table

* AT - created the published schedule table

* fixed enum name

* removed brackets around exist conditionals

* added create table users statement

* added drop table if exists

* updated drop table statement

* Made CRUD SQL queries for Published Schedule Table

* added catalog CRUD queries

* Attempt to figure out ENV variable issue with workflows

* fix typo

* try moving env variables

* Revert changes

* Make CRUD SQL queries for Users Table (#25)

* Added UPDATE and DELETE queries for user table

* added Get, Get pending accounts, and Post

* implemented changes from pr feedback

---------

Co-authored-by: Sean Fong <[email protected]>
Co-authored-by: Philip Jian <[email protected]>

* fixed published schedule types

* added connection to db

* 23-make-backend-routes-for-users (#26)

* Create a pull trequest for branch 23-make-backend-routes-for-users

* Co-authored-by: cherhchen <[email protected]>

* Finished backend routes

Co-authored-by: cherhchen <[email protected]>

* Refactor users.js for minor updates and delete users.sql

Co-authored-by: cherhchen <[email protected]>

---------

Co-authored-by: Ethan Ho <[email protected]>
Co-authored-by: cherhchen <[email protected]>

* Make backend routes for Catelog (#27)

* created catalog.js, made progress

* added :id to the router functions, changed delete query

* Completed code for routes. Running into db.query is not a function error

* Completed Routes for Catelog

* removed comments, fixed yarn lock

* removed console logs

* fixed ?

Co-authored-by: liannejl <[email protected]>

---------

Co-authored-by: Alyssia Tan <[email protected]>
Co-authored-by: liannejl <[email protected]>
Co-authored-by: liannejl <[email protected]>

* Set up the nodeMailer route and the transporter (#28)

* nodeMailer.js setup

* Added nodeMailer.js code and transporter.js that is called within nodeMailer

* Updated package.json to include nodeMailer dependency, added endpoint for emailRouter in app.js, set cors credentials to true so it doesn't block req

---------

Co-authored-by: subinqkim <[email protected]>

* Make Backend Routes for Published Schedule (#29)

* Modified GET queries with joins on catalog table

* created publishSchedule.js file

* Mounted published schedule route on app.js

* Added GET and POST route controller functions for published schedule

* put and delete, not yet complete

* updated publishedSchedule.js

* updated to use numeric syntax for sql queries

* small fixes in ppublishedSchedule.js

* pull request feedback

* pull request feedback cont.

* fixed misc bugs

---------

Co-authored-by: Sean Fong <[email protected]>
Co-authored-by: Philip Jian <[email protected]>
Co-authored-by: michellelin1 <[email protected]>
Co-authored-by: ThatMegamind <[email protected]>

* Minor DB Updates (#32)

* Create a pull trequest for branch 31-minor-db-updates

* updated db model and queries

---------

Co-authored-by: michellelin1 <[email protected]>

---------

Co-authored-by: Kristen Yee <[email protected]>
Co-authored-by: Alyssia Tan <[email protected]>
Co-authored-by: Cheryl Chen <[email protected]>
Co-authored-by: subinqkim <[email protected]>
Co-authored-by: chloecheng8 <[email protected]>
Co-authored-by: Andrew Lee <[email protected]>
Co-authored-by: ThatMegamind <[email protected]>
Co-authored-by: ctc-devops <[email protected]>
Co-authored-by: Sean Fong <[email protected]>
Co-authored-by: Philip Jian <[email protected]>
Co-authored-by: Ethan Ho <[email protected]>
Co-authored-by: cherhchen <[email protected]>
Co-authored-by: liannejl <[email protected]>
Co-authored-by: liannejl <[email protected]>
  • Loading branch information
15 people authored Jan 8, 2024
1 parent db6533e commit 9556edd
Show file tree
Hide file tree
Showing 15 changed files with 656 additions and 11 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ name: CI

on:
[pull_request]

permissions: read-all

jobs:
eslint:
eslint:
runs-on: ubuntu-latest
steps:
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
Expand All @@ -21,7 +21,7 @@ jobs:
reporter: github-pr-review
fail_on_error: false
eslint_flags: '**/*.{js,jsx}'

detect-secrets:
runs-on: ubuntu-latest
steps:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/scripts/reviewReviewed.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ const messageAssignee = async ({ context }) => {
try {
const UserModel = getUserModel();
const slackAssignees = await Promise.allSettled(
githubAssignees.map(assignee => UserModel.findOne({ github: assignee.login })),
githubAssignees.map((assignee) => UserModel.findOne({ github: assignee.login })),
);
if (context.payload.review.state === 'approved') {
await Promise.all(
slackAssignees.map(assignee =>
slackAssignees.map((assignee) =>
Bot.client.chat.postMessage({
channel: assignee.value?.slackId,
text: `One of your pull requests has been APPROVED by ${reviewer}! <${url}|View Review> :shrek::thumbsup:`,
Expand All @@ -53,7 +53,7 @@ const messageAssignee = async ({ context }) => {
);
} else {
await Promise.all(
slackAssignees.map(assignee =>
slackAssignees.map((assignee) =>
Bot.client.chat.postMessage({
channel: assignee.value?.slackId,
text: `One of your pull requests has been REVIEWED by ${reviewer}! <${url}|View Review> :shrek:`,
Expand Down
18 changes: 18 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
const express = require('express');
const cors = require('cors');
const publishedScheduleRouter = require('./routes/publishedSchedule');

require('dotenv').config();

// routes
const users = require('./routes/users');

const email = require('./routes/nodeMailer');

const app = express();

const catalogRouter = require('./routes/catalog');

const PORT = process.env.PORT || 3001;

app.use(
cors({
origin: `${process.env.REACT_APP_HOST}:${process.env.REACT_APP_PORT}`,
credentials: true,
}),
);

// app.use(cors({ origin: 'http://localhost:3000', credentials: true }));

// add all routes under here
app.use(express.json()); // for req.body
app.use('/published-schedule', publishedScheduleRouter);
app.use('/users', users);
app.use('/catalog', catalogRouter);
app.use('/nodeMailer', email);

app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});
55 changes: 55 additions & 0 deletions common/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// toCamel, isArray, and isObject are helper functions used within utils only
const toCamel = (s) => {
return s.replace(/([-_][a-z])/g, ($1) => {
return $1.toUpperCase().replace('-', '').replace('_', '');
});
};

const isArray = (a) => {
return Array.isArray(a);
};

const isISODate = (str) => {
try {
const ISOString = str.toISOString();
if (!/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(ISOString)) return false;
const d = new Date(ISOString);
return d.toISOString() === ISOString;
} catch (err) {
return false;
}
};

const isObject = (o) => {
return o === Object(o) && !isArray(o) && typeof o !== 'function' && !isISODate(o);
};

// Database columns are in snake case. JavaScript is suppose to be in camel case
// This function converts the keys from the sql query to camel case so it follows JavaScript conventions
const keysToCamel = (data) => {
if (isObject(data)) {
const newData = {};
Object.keys(data).forEach((key) => {
newData[toCamel(key)] = keysToCamel(data[key]);
});
return newData;
}
if (isArray(data)) {
return data.map((i) => {
return keysToCamel(i);
});
}
if (
typeof data === 'string' &&
data.length > 0 &&
data[0] === '{' &&
data[data.length - 1] === '}'
) {
let parsedList = data.replaceAll('"', '');
parsedList = parsedList.slice(1, parsedList.length - 1).split(',');
return parsedList;
}
return data;
};

module.exports = { keysToCamel };
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-prettier": "^4.0.0",
"express": "^4.17.1",
"express-promise-router": "^4.1.1",
"nodemailer": "^6.9.7",
"nodemon": "^2.0.14",
"pg": "^8.8.0",
"pg-promise": "^10.12.1",
"prettier": "^2.4.1"
},
"devDependencies": {
"eslint-config-prettier": "^8.3.0",
"lint-staged": "^11.2.6",
"lint-staged": "^11.2.6",
"husky": "^7.0.4"
"husky": "^7.0.4",
"lint-staged": "^11.2.6"
}
}
93 changes: 93 additions & 0 deletions routes/catalog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const express = require('express');

const { db } = require('../server/db');

const catalogRouter = express.Router();
const { keysToCamel } = require('../common/utils');

// -- GET - Returns all data from the catalog table
catalogRouter.get('/', async (req, res) => {
try {
const allInfo = await db.query(`SELECT * from catalog;`);
res.status(200).json(keysToCamel(allInfo));
} catch (err) {
res.status(500).send(err.message);
}
});

// -- GET/:id - Returns the row that matches the id
catalogRouter.get('/:id', async (req, res) => {
try {
const { id } = req.params;
const allUsers = await db.query(`SELECT * FROM catalog WHERE id = $1;`, [id]);
res.status(200).json(keysToCamel(allUsers));
} catch (err) {
res.status(500).send(err.message);
}
});

// -- POST - Adds a new row to the catalog table
catalogRouter.post('/', async (req, res) => {
const { host, title, eventType, subject, description, year } = req.body;
try {
const returnedData = await db.query(
`INSERT INTO catalog (id, host, title, event_type, subject, description, year)
VALUES (nextval('catalog_id_seq'), $1, $2, $3, $4, $5, $6)
RETURNING id;`,
[host, title, eventType, subject, description, year],
);
res.status(201).json({ id: returnedData[0].id, status: 'Success' });
} catch (err) {
res.status(500).json({
status: 'Failed',
msg: err.message,
});
}
});

// -- PUT - Updates an existing row given an id
// -- All fields are optional
catalogRouter.put('/:id', async (req, res) => {
try {
const { id } = req.params;
const { host, title, eventType, subject, description, year } = req.body;

const updatedCatalog = await db.query(
`UPDATE catalog SET
${host ? 'host = $(host), ' : ''}
${title ? 'title = $(title),' : ''}
${eventType ? 'event_type = $(eventType), ' : ''}
${subject ? 'subject = $(subject), ' : ''}
${description ? 'description = $(description), ' : ''}
${year ? 'year = $(year), ' : ''}
id = '${id}'
WHERE id = '${id}'
RETURNING *;`,
{
host,
title,
eventType,
subject,
description,
year,
id,
},
);
res.status(200).send(keysToCamel(updatedCatalog));
} catch (err) {
res.status(500).send(err.message);
}
});

// -- DELETE - deletes an existing row given an id
catalogRouter.delete('/:id', async (req, res) => {
try {
const { id } = req.params;
const delUser = await db.query(`DELETE FROM catalog WHERE id = $1 RETURNING *;`, [id]);
res.status(200).send(keysToCamel(delUser));
} catch (err) {
res.status(500).send(err.message);
}
});

module.exports = catalogRouter;
37 changes: 37 additions & 0 deletions routes/nodeMailer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const express = require('express');
// const cors = require('cors');
const transporter = require('../transporter');
// TODO: add verifyToken

const emailRouter = express();
// emailRouter.use(
// cors({
// origin: 'http://localhost:3000',
// methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
// credentials: true,
// }),
// );

emailRouter.use(express.json());

emailRouter.post('/send', (req, res) => {
const { email, messageHtml, subject } = req.body;
console.log('req.body', req.body);
console.log('email', email);
const mail = {
from: `${process.env.REACT_APP_EMAIL_FIRST_NAME} ${process.env.REACT_APP_EMAIL_LAST_NAME} ${process.env.REACT_APP_EMAIL_USERNAME}`,
to: email,
subject,
html: messageHtml,
};

transporter.sendMail(mail, (err) => {
if (err) {
res.status(500).send(`Transporter Error: ${err}`);
} else {
res.status(200).send('Transporter Backend Successfully Sent');
}
});
});

module.exports = emailRouter;
Loading

0 comments on commit 9556edd

Please sign in to comment.