Skip to content

Commit

Permalink
Merge pull request #683 from CodeForAfrica/feature/write-to-spreadsheet
Browse files Browse the repository at this point in the history
Add spreadsheet script to update sheet
  • Loading branch information
koechkevin authored Mar 22, 2024
2 parents 062daff + b75725d commit f012d18
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 30 deletions.
2 changes: 1 addition & 1 deletion apps/vpnmanager/.env.template
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
NEXT_APP_GOOGLE_CREDENTIALS=/path/to/credentials.json
NEXT_APP_GOOGLE_SHEET_ID=
NEXT_APP_GOOGLE_SHEET_RANGE=New Hires!A:Z
NEXT_APP_GOOGLE_SHEET_NAME="New Hires"
NEXT_APP_VPN_API_URL=
SENTRY_AUTH_TOKEN=
SENTRY_DSN=
4 changes: 3 additions & 1 deletion apps/vpnmanager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"build": "pnpm run build-ts && next build",
"start": "next start",
"build-ts": "tsc --project tsconfig.server.json && tsc-alias -p tsconfig.server.json",
"process-new-hires": "node dist/src/lib/processNewHires.js"
"process-spreadsheet": "node dist/scripts/processGsheet.js"
},
"dependencies": {
"@babel/core": "^7.23.6",
Expand All @@ -20,6 +20,8 @@
"@emotion/styled": "^11.11.0",
"@mui/material": "^5.14.20",
"@mui/utils": "^5.14.20",
"@next/env": "^14.1.4",
"@sendgrid/mail": "^8.1.1",
"@sentry/nextjs": "^7.105.0",
"@svgr/webpack": "^8.1.0",
"@types/jest": "^29.5.12",
Expand Down
7 changes: 7 additions & 0 deletions apps/vpnmanager/scripts/processGsheet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { processNewUsers } from "@/vpnmanager/lib/processUsers";
import { loadEnvConfig } from "@next/env";

const projectDir = process.cwd();
loadEnvConfig(projectDir);

processNewUsers();
70 changes: 62 additions & 8 deletions apps/vpnmanager/src/lib/data/spreadsheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import { toCamelCase } from "@/vpnmanager/utils";
function gSheet() {
const auth = new google.auth.GoogleAuth({
keyFile: process.env.NEXT_APP_GOOGLE_CREDENTIALS,
scopes: ["https://www.googleapis.com/auth/spreadsheets.readonly"],
scopes: ["https://www.googleapis.com/auth/spreadsheets"],
});
return google.sheets({ version: "v4", auth });
}

async function list(
async function fetchRange(
spreadsheetId?: string,
range?: string,
): Promise<SheetRow[]> {
Expand Down Expand Up @@ -44,16 +44,70 @@ async function list(
return data;
}

async function newHires() {
async function newUsers() {
const spreadsheetId = process.env.NEXT_APP_GOOGLE_SHEET_ID;
const range = process.env.NEXT_APP_GOOGLE_SHEET_RANGE;
const data = await list(spreadsheetId, range);
const range = `${process.env.NEXT_APP_GOOGLE_SHEET_NAME}!A:Z`;
const data = await fetchRange(spreadsheetId, range);
return data.filter(
(row: SheetRow) => row.emailAddress && row.keySent !== "Yes",
(row: SheetRow) => row.emailAddress && row.keySent?.trim() !== "Yes",
);
}

function processRow(rows: string[][], row: Partial<SheetRow>) {
const { emailAddress, outlineKeyCreated, keySent } = row;
const titles = rows[0];
const emailIndex = titles.findIndex(
(item) => item?.toLowerCase()?.trim() === "email address",
);
const rowIndexToUpdate = rows.findIndex(
(item: string[]) => item[emailIndex] === emailAddress,
);
if (rowIndexToUpdate < 0) {
return rows;
}
const rowToUpdate = rows[rowIndexToUpdate];
if (outlineKeyCreated) {
const outlineKeyCreatedIndex = titles.findIndex(
(item) => item?.toLowerCase()?.trim() === "outline key created?",
);
rowToUpdate[outlineKeyCreatedIndex] = outlineKeyCreated;
}
if (keySent) {
const keySentIndex = titles.findIndex(
(item) => item?.toLowerCase()?.trim() === "key sent",
);
rowToUpdate[keySentIndex] = keySent;
}
rows[rowIndexToUpdate] = rowToUpdate;
return rows;
}

export async function updateSheet(toUpdate: Partial<SheetRow>[]) {
const spreadsheetId = process.env.NEXT_APP_GOOGLE_SHEET_ID;
const range = `${process.env.NEXT_APP_GOOGLE_SHEET_NAME}!A:Z`;
const sheets = gSheet();
const response = await sheets.spreadsheets.values.get({
spreadsheetId,
range,
});
const rows = response.data.values;
if (!rows?.length) {
return null;
}

const values = toUpdate.reduce((acc, curr) => processRow(acc, curr), rows);
return sheets.spreadsheets.values.update({
spreadsheetId,
range,
valueInputOption: "USER_ENTERED",
requestBody: {
values,
},
});
}

export default {
list,
newHires,
fetchRange,
newUsers,
updateSheet,
};
17 changes: 0 additions & 17 deletions apps/vpnmanager/src/lib/processNewHires.ts

This file was deleted.

21 changes: 21 additions & 0 deletions apps/vpnmanager/src/lib/processUsers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import spreadsheet, { updateSheet } from "@/vpnmanager/lib/data/spreadsheet";
import { SheetRow } from "@/vpnmanager/types";

export async function processUser(item: SheetRow) {
return {
...item,
keySent: "Yes",
};
}

export async function processNewUsers() {
const users = await spreadsheet.newUsers();
const promises = users.map((item) => processUser(item));
const settled = await Promise.allSettled(promises);
const fulfilled = settled
.filter((item) => item.status === "fulfilled")
.map(({ value }: any) => value);
if (fulfilled.length) {
updateSheet(fulfilled);
}
}
3 changes: 1 addition & 2 deletions apps/vpnmanager/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import fetchJson from "./fetchJson";
import toCamelCase from "./wordToCamelCase";

export { fetchJson, toCamelCase };
export { toCamelCase };
2 changes: 1 addition & 1 deletion apps/vpnmanager/tsconfig.server.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"outDir": "./dist",
"rootDir": "./"
},
"include": ["src/lib/**/*.ts", "src/utils/**/*.ts"]
"include": ["src/lib/**/*.ts", "src/utils/**/*.ts", "scripts/**/*.ts"]
}
75 changes: 75 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f012d18

Please sign in to comment.