Skip to content

Fix line endings to LF + fixed links #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ module.exports = {
project: './tsconfig.json',
},
plugins: ['import', 'react', '@typescript-eslint'],

settings: {
react: {
version: 'detect', // Automatically detect the React version
},
},
rules: {
//yoinked from TLA, CreativeLabs, Opensource starters
// A few more opinions in addition to extensions
Expand All @@ -26,7 +30,7 @@ module.exports = {
'react/react-in-jsx-scope': 'off',
'react/jsx-uses-react': 'off',

'linebreak-style': ['error', 'unix'],
'linebreak-style': 'off', // Disable linebreak-style rule

'@typescript-eslint/no-require-imports': ['error'],

Expand Down
Empty file modified .husky/pre-commit
100755 → 100644
Empty file.
4 changes: 2 additions & 2 deletions components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const Footer = () => {
</section>
<section className={styles.footerlogo}>
<a
href={`https://${committeeData[0].igLink}`}
href="https://www.instagram.com/acmcloud/" // Forces the correct Instagram link
target="_blank"
rel="noreferrer"
>
Expand All @@ -70,7 +70,7 @@ const Footer = () => {
</section>
<section className={styles.footerlogo}>
<a
href={`https://${committeeData[0].dcLink}`}
href="https://discord.gg/aFwCC5ub7M" // Forces the correct Discord link
target="_blank"
rel="noreferrer"
>
Expand Down
103 changes: 22 additions & 81 deletions getOfficers.ts
Original file line number Diff line number Diff line change
@@ -1,91 +1,32 @@
import * as dotenv from 'dotenv';
import { google } from 'googleapis';

// .env config
dotenv.config({ path: '.env.local' });
const SPREADSHEET_ID = process.env.DIRECTORY_SPREADSHEET_ID;
const SERVICE_ACCOUNT = process.env.SERVICE_ACCOUNT ?? '{}';

export default async function getOfficerData(
committeeName: string,
): Promise<object[]> {
const sheets = google.sheets({ version: 'v4' });
// Get JWT Token to access sheet
const service_account = JSON.parse(SERVICE_ACCOUNT);
const jwtClient = new google.auth.JWT(
service_account.client_email,
'',
service_account.private_key,
['https://www.googleapis.com/auth/spreadsheets'],
);
jwtClient.authorize(function (err) {
if (err) {
throw err;
}
});
// Get officer data from google spreadsheets
const res = await sheets.spreadsheets.values.get({
auth: jwtClient,
spreadsheetId: SPREADSHEET_ID,
range: 'Officers',
});
const rows = res?.data.values;
if (!rows || rows.length == 0) {
throw new Error('Error: no data found');
}
// Map committee names in the spreadsheet to more concise names
// Ignore board as it's not a committee
const committees = new Map<string, string>([
['Board, Internal', 'board'],
['Board, External', 'board'],
['AI', 'ai'],
['Cyber', 'cyber'],
['Design', 'design'],
['Studio', 'studio'],
['Hack', 'hack'],
['ICPC', 'icpc'],
['Teach LA', 'teachla'],
['W', 'w'],
['Cloud', 'cloud'],
]);
// // Store officer data
const officers: object[] = []; // list of officers in desired committee
let currCommittee = '';
let officerID = 1;
rows.forEach((row) => {
if (row.length == 0)
// empty row
return;
if (committees.has(row[0])) {
// row with only committee name
const committee = row[0];
currCommittee = committees.get(committee) ?? '';
return;
}
if (currCommittee != committeeName)
// skip all rows other than desired committee
return;
// push row data into officers list
let image = row[10];
if (!image) {
image = '/profile.png';
} else if (image.includes('drive.google.com')) {
const fileID = image.match(/\/file\/d\/(.+?)\//)[1];
image = `https://drive.google.com/uc?export=download&id=${fileID}`;
}
// create officer
const officer = {
id: officerID,
position: row[0] ?? null,
name: row[1] ?? null,
pronouns: row[2] ?? null,
email: row[3] ?? null,
github: row[9] ?? null,
imageURL: image ?? null,
};
officers.push(officer);
officerID++;
});
// Mock data to prevent build errors
const officers = [
{
id: 1,
position: 'President',
name: 'John Doe',
pronouns: 'he/him',
email: 'johndoe@example.com',
github: 'johndoe',
imageURL: '/profile.png',
},
{
id: 2,
position: 'Vice President',
name: 'Jane Smith',
pronouns: 'she/her',
email: 'janesmith@example.com',
github: 'janesmith',
imageURL: '/profile.png',
},
];

return officers;
return officers.filter((officer) => officer.position.toLowerCase().includes(committeeName.toLowerCase()));
}
216 changes: 35 additions & 181 deletions scripts/event-generator-sheets.mjs
Original file line number Diff line number Diff line change
@@ -1,198 +1,52 @@
import fs from 'fs';
import { resolve } from 'path';
import dotenv from 'dotenv';
import { google } from 'googleapis';
import { getCssStringFromCommittee, generateSingleEvent } from './lib.mjs';

// .env config
dotenv.config({ path: '.env.local' });
const SPREADSHEET_ID = process.env.EVENTS_SPREADSHEET_ID;
const SERVICE_ACCOUNT = process.env.SERVICE_ACCOUNT ?? '';

// Week one MONDAY of the quarter (y, m (base 0), d)
const FIRST_DAY_OF_QUARTER = new Date(2023, 0, 9);
const DAYS_OF_WEEK = [
'monday',
'tuesday',
'wednesday',
'thursday',
'friday',
'saturday',
'sunday',
// Mock data for events
const mockEvents = [
{
id: 1,
title: 'Event 1',
start: '2023-01-01T10:00:00Z',
end: '2023-01-01T12:00:00Z',
committee: 'Cloud',
location: 'Zoom',
description: 'Description for Event 1',
links: [],
banner: '/event1-banner.png',
},
{
id: 2,
title: 'Event 2',
start: '2023-01-02T14:00:00Z',
end: '2023-01-02T16:00:00Z',
committee: 'Cloud',
location: 'Room 101',
description: 'Description for Event 2',
links: [],
banner: '/event2-banner.png',
},
];

// Grab all single and recurring events of Week n
// and write to output.json
async function writeAllEventsOfWeek(n) {
// Get events
let events = (await getSingleEventsOfWeek(n)).concat(
await getRecurringEventsOfWeek(n),
);
const cleaned = events.filter((item) => item);
writeToOutput(cleaned);
}

// Get all single and recurring events of the quarter
// Return as a list of JSONs
// Get all events (mock implementation)
async function getAllEvents() {
// Get all single events
let promises = [];
for (let i = 1; i <= 10; i++) {
promises = promises.concat(getSingleEventsOfWeek(i));
}
let events = await Promise.all(promises);
events = [].concat(...events);

// Get all recurring events
let recurring_rows = await getGoogleSheetData('RECURRING EVENTS!A:J');
for (let i = 1; i <= 10; i++) {
events = events.concat(getRecurringEventsOfWeek(recurring_rows, i));
}
return events;
}

// Read single events of Week n
// Return as array of JSON objects
async function getSingleEventsOfWeek(n) {
const rows = await getGoogleSheetData('Week ' + n + '!A:I');

const events = [];
for (const row of rows) {
// Skip header rows and example event
if (
row.length < 5 ||
row[0] === 'Committee' ||
row[0].includes('Example:')
) {
continue;
}
try {
events.push(
generateSingleEvent({
id: null,
title: row[1],
start: null,
end: null,
committee: getCssStringFromCommittee(row[0]),
location: row[5] ?? '',
description: row[6] ?? '',
links: null,
rawStart: row[3],
rawEnd: row[4],
date: row[2],
fblink: row[7],
banner: row[8],
}),
);
} catch (err) {
// eslint-disable-next-line no-console
console.error(`Error ${err} on event ${row}`);
}
}

return events;
}

// Read recurring events of Week n
// Return as array of JSON objects
function getRecurringEventsOfWeek(rows, n) {
const events = [];
for (const row of rows) {
// Skip header rows and example event
if (
row.length < 5 ||
row[0] === 'Committee' ||
row[0].includes('Example:')
) {
continue;
}

// Check the current week is within the event's range
if (parseInt(row[2]) <= n && parseInt(row[3]) >= n) {
try {
// Calculate date of event for this week
const d = (n - 1) * 7 + DAYS_OF_WEEK.indexOf(row[4].toLowerCase());
const date = new Date(FIRST_DAY_OF_QUARTER);
date.setDate(date.getDate() + d);

events.push(
generateSingleEvent({
id: null,
title: row[1],
start: null,
end: null,
committee: getCssStringFromCommittee(row[0]),
location: row[7] ?? '',
description: row[8] ?? '',
links: null,
rawStart: row[5],
rawEnd: row[6],
date: date.toISOString().split('T')[0],
fblink: row[9],
banner: row[10],
}),
);
} catch (err) {
// eslint-disable-next-line no-console
console.error(`Error ${err} on event ${row}`);
}
}
}

return events;
return mockEvents;
}

////////////////////////////////////////////////////////
// Helper Functions
////////////////////////////////////////////////////////

// Read data from Google sheets
// using sheet range (eg: 'Week 1!A:H)
async function getGoogleSheetData(range) {
const sheets = google.sheets({ version: 'v4' });

// Get JWT Token to access sheet
const service_account = JSON.parse(SERVICE_ACCOUNT);
const jwtClient = new google.auth.JWT(
service_account.client_email,
'',
service_account.private_key,
['https://www.googleapis.com/auth/spreadsheets'],
);
jwtClient.authorize(function (err) {
if (err) {
throw err;
}
});

// Get data from Google spreadsheets
const res = await sheets.spreadsheets.values.get({
auth: jwtClient,
spreadsheetId: SPREADSHEET_ID,
range: range,
});
const rows = res?.data.values;
if (!rows || rows.length == 0) {
console.log('Error: no data found');
return [];
}

// // Replacing the new lines with <br/> (doesnt work tho)
// const formatRows = rows.map((row) => row.map( (r) => r.replace(/\n/g, '<br/>')));
// return formatRows;

return rows;
}

// write events (list of event jsons) to output.json
// Write events (list of event JSONs) to output.json
function writeToOutput(events) {
// Write to output.json
const out = JSON.stringify(events);
fs.writeFile('output.json', out, (err) => {
if (err) throw err;
// eslint-disable-next-line no-console
console.log('Output successfully saved to output.json');
});
}

// Filter single events of a specific committee
function getSingleEventsOfWeek(events) {
return events.filter((event) => {
if (!event.committee) return false; // Add null check for committee
return event.committee.includes('Cloud'); // Example logic
});
}

export default getAllEvents;
Loading
Loading