Skip to content

Commit

Permalink
Merge pull request #29 from RotaractMora/dev
Browse files Browse the repository at this point in the history
Navbar fixes
  • Loading branch information
SakinduRansindu authored Nov 24, 2024
2 parents f472c6a + cb89eb6 commit da08ed2
Show file tree
Hide file tree
Showing 39 changed files with 2,822 additions and 875 deletions.
7 changes: 0 additions & 7 deletions .env.example

This file was deleted.

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# dependencies
/node_modules
/node_modules*
/.pnp
.pnp.*
.yarn/*
Expand Down Expand Up @@ -30,9 +31,11 @@ yarn-debug.log*
yarn-error.log*

# env files (can opt-in for committing if needed)
.env.local
.env*
!.env.example


# vercel
.vercel

Expand Down
1 change: 1 addition & 0 deletions functions/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ module.exports = {
"import/no-commonjs": "off", // Allow 'require' in ESM, commonjs modules
// Change linebreak-style from error to warning
"linebreak-style": ["warn", "unix"],
"max-len": ["error", {"code": 120}],
},
};
122 changes: 122 additions & 0 deletions functions/src/companyDataAggregator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import {db} from "./firebaseSetup";
import {FieldValue} from "firebase-admin/firestore";
import {
onDocumentCreated,
onDocumentUpdated,
onDocumentDeleted,
} from "firebase-functions/v2/firestore";
import {https, logger} from "firebase-functions";

const REGION = "asia-southeast1";

const AGGREGATED_COMPANIES_DOC_PATH = "metadata/agregatedCompanies";
const COMPANIES_COLLECTION_PATH = "campaigns/rur-25/companies";


// Fields to be aggregated
const SELECTED_FIELDS = [
"companyId",
"name",
"description",
"logoUrl",
"preferredFields",
"qualitiesToLook",
"dataConfirmed",
];


const filterSelectedFields = (data: Record<string, any>): Record<string, any> =>
Object.fromEntries(
Object.entries(data).filter(([key]) => SELECTED_FIELDS.includes(key))
);


export const manualAggregateCompanies = https.onRequest({
region: REGION,
}, async (req, res) => {
try {
const aggregatedCompanies: Record<string, any> = {};
const companiesSnapshot = await db.collection(COMPANIES_COLLECTION_PATH).get();

companiesSnapshot.forEach((doc) => {
// Include only if dataConfirmed is true
if (doc.data().dataConfirmed) {
aggregatedCompanies[doc.id] = filterSelectedFields(doc.data());
}
});

await db.doc(AGGREGATED_COMPANIES_DOC_PATH)
.set({companies: aggregatedCompanies});

logger.info("Manual aggregation completed:", AGGREGATED_COMPANIES_DOC_PATH);
res.status(200).send({message: "Manual aggregation completed."});
} catch (error) {
logger.error("Error during manual aggregation:", error);
res.status(500).send({error: "Internal Server Error"});
}
});


export const incrementalAggregateCompanies = {
onCreate: onDocumentCreated({
document: COMPANIES_COLLECTION_PATH + "/{docId}",
region: REGION,
}, async (event) => {
try {
const newData = event.data?.data();
if (!newData?.dataConfirmed) return;

const newDoc = filterSelectedFields(newData);
const docId = event.params.docId;

// Update the aggregated document with the new data
await db.doc(AGGREGATED_COMPANIES_DOC_PATH).update({
[`companies.${docId}`]: newDoc,
});

logger.info(`Incrementally added document: ${docId}`);
} catch (error) {
logger.error("Error during onCreate incremental update:", error);
}
}),

onUpdate: onDocumentUpdated({
document: COMPANIES_COLLECTION_PATH + "/{docId}",
region: REGION,
}, async (event) => {
try {
const updatedData = event.data?.after.data();
if (!updatedData?.dataConfirmed) return;

const updatedDoc = filterSelectedFields(updatedData);
const docId = event.params.docId;

// Update the aggregated document with the updated data
await db.doc(AGGREGATED_COMPANIES_DOC_PATH).update({
[`companies.${docId}`]: updatedDoc,
});

logger.info(`Incrementally updated document: ${docId}`);
} catch (error) {
logger.error("Error during onUpdate incremental update:", error);
}
}),

onDelete: onDocumentDeleted({
document: COMPANIES_COLLECTION_PATH + "/{docId}",
region: REGION,
}, async (event) => {
try {
const docId = event.params.docId;

// Remove the deleted document from the aggregated document
await db.doc(AGGREGATED_COMPANIES_DOC_PATH).update({
[`companies.${docId}`]: FieldValue.delete(),
});

logger.info(`Incrementally deleted document: ${docId}`);
} catch (error) {
logger.error("Error during onDelete incremental update:", error);
}
}),
};
6 changes: 6 additions & 0 deletions functions/src/firebaseSetup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {initializeApp} from "firebase-admin/app";
import {getFirestore} from "firebase-admin/firestore";

// Initialize Firebase
initializeApp();
export const db = getFirestore();
100 changes: 20 additions & 80 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,86 +1,26 @@
// Import Firebase Functions and Admin SDK
const logger = require("firebase-functions/logger");
const {initializeApp} = require("firebase-admin/app");
const {getFirestore} = require("firebase-admin/firestore");
const {
onDocumentCreated,
onDocumentUpdated,
onDocumentDeleted,
} = require("firebase-functions/v2/firestore");
import {createInfoTriggers} from "./infoAggregator";
import {
incrementalAggregateCompanies,
manualAggregateCompanies,
} from "./companyDataAggregator";

initializeApp();
const db = getFirestore();
// Exporting triggers for /info-sponsors and /info-timeline collections
const sponsorsTriggers = createInfoTriggers("info-sponsors");
const timelineTriggers = createInfoTriggers("info-timeline");

// Path for the aggregated document
const AGGREGATED_DOC_PATH = "metadata/aggregatedInfo";
export const infoSponsorsOnCreate = sponsorsTriggers.onCreate;
export const infoSponsorsOnUpdate = sponsorsTriggers.onUpdate;
export const infoSponsorsOnDelete = sponsorsTriggers.onDelete;

// Aggregates data from /info-sponsors and /info-timeline into a single document
const aggregateData = async () => {
try {
const aggregatedData: {
"info-sponsors": Record<string, any>;
"info-timeline": Record<string, any>;
} = {"info-sponsors": {}, "info-timeline": {}};
export const infoTimelineOnCreate = timelineTriggers.onCreate;
export const infoTimelineOnUpdate = timelineTriggers.onUpdate;
export const infoTimelineOnDelete = timelineTriggers.onDelete;

// Aggregate data from info-sponsors
const sponsorsSnapshot = await db.collection("info-sponsors").get();
sponsorsSnapshot.forEach((doc: any) => {
aggregatedData["info-sponsors"][doc.id] = doc.data();
});

// Aggregate data from info-timeline
const timelineSnapshot = await db.collection("info-timeline").get();
timelineSnapshot.forEach((doc: any) => {
aggregatedData["info-timeline"][doc.id] = doc.data();
});
// Exporting Firestore triggers for incremental company aggregation
export const companyOnCreate = incrementalAggregateCompanies.onCreate;
export const companyOnUpdate = incrementalAggregateCompanies.onUpdate;
export const companyOnDelete = incrementalAggregateCompanies.onDelete;

// Save the aggregated data to the Firestore document
await db.doc(AGGREGATED_DOC_PATH).set(aggregatedData);

logger.info("Successfully aggregated data into:", AGGREGATED_DOC_PATH);
} catch (error) {
logger.error("Error aggregating data:", error);
}
};

// Helper to create triggers for a given collection
const createTriggers = (collectionPath: string) => {
return {
onCreate: onDocumentCreated(
`${collectionPath}/{docId}`,
async (event: any) => {
logger.info(
`Document created in ${collectionPath}:`,
event.params.docId
);
await aggregateData();
}
),
onUpdate: onDocumentUpdated(
`${collectionPath}/{docId}`,
async (event: any) => {
logger.info(
`Document updated in ${collectionPath}:`,
event.params.docId
);
await aggregateData();
}
),
onDelete: onDocumentDeleted(
`${collectionPath}/{docId}`,
async (event: any) => {
logger.info(
`Document deleted in ${collectionPath}:`,
event.params.docId
);
await aggregateData();
}
),
};
};

// Export triggers for /info-sponsors
exports.aggregateInfoSponsors = createTriggers("info-sponsors");

// Export triggers for /info-timeline
exports.aggregateInfoTimeline = createTriggers("info-timeline");
// Exporting HTTP function for manual aggregation
export const aggregateCompaniesManually = manualAggregateCompanies;
61 changes: 61 additions & 0 deletions functions/src/infoAggregator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {db} from "./firebaseSetup";
import {
onDocumentCreated,
onDocumentUpdated,
onDocumentDeleted,
} from "firebase-functions/v2/firestore";
import {logger} from "firebase-functions";

const REGION = "asia-southeast1";

// Path for the aggregated document
const AGGREGATED_DOC_PATH = "metadata/aggregatedInfo";

// Aggregates data from /info-sponsors and /info-timeline into a single document
const aggregateData = async () => {
try {
const aggregatedData: {
"info-sponsors": Record<string, unknown>;
"info-timeline": Record<string, unknown>;
} = {"info-sponsors": {}, "info-timeline": {}};

// Aggregate data from info-sponsors
const sponsorsSnapshot = await db.collection("info-sponsors").get();
sponsorsSnapshot.forEach((doc) => {
aggregatedData["info-sponsors"][doc.id] = doc.data();
});

// Aggregate data from info-timeline
const timelineSnapshot = await db.collection("info-timeline").get();
timelineSnapshot.forEach((doc) => {
aggregatedData["info-timeline"][doc.id] = doc.data();
});

// Save the aggregated data to the Firestore document
await db.doc(AGGREGATED_DOC_PATH).set(aggregatedData);
logger.info("Successfully aggregated data into:", AGGREGATED_DOC_PATH);
} catch (error) {
logger.error("Error aggregating data:", error);
}
};

// Helper to create triggers for a given collection
export const createInfoTriggers = (collectionPath: string) => {
return {
onCreate: onDocumentCreated({document: `${collectionPath}/{docId}`, region: REGION},
async (event) => {
logger.info(`Document created in ${collectionPath}:`, event.params.docId);
await aggregateData();
}),
onUpdate: onDocumentUpdated({document: `${collectionPath}/{docId}`, region: REGION},
async (event) => {
logger.info(`Document updated in ${collectionPath}:`, event.params.docId);
await aggregateData();
}),
onDelete: onDocumentDeleted({document: `${collectionPath}/{docId}`, region: REGION},
async (event) => {
logger.info(`Document deleted in ${collectionPath}:`, event.params.docId);
await aggregateData();
}),
};
};
Loading

0 comments on commit da08ed2

Please sign in to comment.