From 85d2b58ede945b552c479a4e9b6933bad12f9321 Mon Sep 17 00:00:00 2001 From: techpixel Date: Tue, 25 Jun 2024 22:43:18 +0000 Subject: [PATCH 1/5] add verification status --- src/extensions/arcade/slack/shop.ts | 2 ++ src/extensions/arcade/slack/views/shop.ts | 4 +++- src/lib/airtable.ts | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/extensions/arcade/slack/shop.ts b/src/extensions/arcade/slack/shop.ts index b304a571..3cc97cb1 100644 --- a/src/extensions/arcade/slack/shop.ts +++ b/src/extensions/arcade/slack/shop.ts @@ -40,6 +40,7 @@ Slack.command(Commands.SHOP, async ({ command }) => { awaitingApproval: Math.floor(airtableUser.fields["Minutes (Pending Approval)"] / 60), inOrders: Math.floor(airtableUser.fields["In Pending (Minutes)"] / 60), spent: Math.floor(airtableUser.fields["Spent Fulfilled (Minutes)"] / 60), + verification: airtableUser.fields["Verification Status (from YSWS Verification User)"] ?? "" }) }) }); @@ -78,6 +79,7 @@ Slack.action(Actions.OPEN_SHOP, async ({ body }) => { awaitingApproval: Math.floor(airtableUser.fields["Minutes (Pending Approval)"] / 60), inOrders: Math.floor(airtableUser.fields["In Pending (Minutes)"] / 60), spent: Math.floor(airtableUser.fields["Spent Fulfilled (Minutes)"] / 60), + verification: airtableUser.fields["Verification Status (from YSWS Verification User)"] ?? "" }) }) }); \ No newline at end of file diff --git a/src/extensions/arcade/slack/views/shop.ts b/src/extensions/arcade/slack/views/shop.ts index a0b11248..10e1bcff 100644 --- a/src/extensions/arcade/slack/views/shop.ts +++ b/src/extensions/arcade/slack/views/shop.ts @@ -8,6 +8,7 @@ export class Shop { awaitingApproval, inOrders, spent, + verification // lifetime, // lifetimeTickets }: { @@ -16,6 +17,7 @@ export class Shop { awaitingApproval: number, inOrders: number, spent: number, + verification: string }): View { return { "type": "modal", @@ -83,7 +85,7 @@ _How do I get tickets?_\n- Provide Date: Tue, 25 Jun 2024 23:19:44 +0000 Subject: [PATCH 2/5] add an orders view --- src/extensions/arcade/index.ts | 4 +- src/extensions/arcade/slack/orders.ts | 38 ++++++++++++++ src/extensions/arcade/slack/views/orders.ts | 55 +++++++++++++++++++++ src/extensions/arcade/slack/views/shop.ts | 11 ++++- src/lib/airtable.ts | 26 ++++++++++ src/lib/constants.ts | 2 + 6 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 src/extensions/arcade/slack/orders.ts create mode 100644 src/extensions/arcade/slack/views/orders.ts diff --git a/src/extensions/arcade/index.ts b/src/extensions/arcade/index.ts index fa1193b7..0867b350 100644 --- a/src/extensions/arcade/index.ts +++ b/src/extensions/arcade/index.ts @@ -6,7 +6,9 @@ import "./slack/index.js"; import "./slack/sessions.js"; import "./slack/scrapbook.js"; import "./slack/shop.js"; -import "./slack/walkthrough.js" +import "./slack/walkthrough.js"; +import "./slack/orders.js"; + import { emitter } from "../../lib/emitter.js"; emitter.on('init', () => { diff --git a/src/extensions/arcade/slack/orders.ts b/src/extensions/arcade/slack/orders.ts new file mode 100644 index 00000000..6527b28b --- /dev/null +++ b/src/extensions/arcade/slack/orders.ts @@ -0,0 +1,38 @@ +import { AirtableAPI } from "../../../lib/airtable.js"; +import { Slack } from "../../../lib/bolt.js"; +import { Actions } from "../../../lib/constants.js"; +import { prisma } from "../../../lib/prisma.js"; +import { t } from "../../../lib/templates.js"; +import { Loading } from "../../slack/views/loading.js"; +import { Orders } from "./views/orders.js"; + +Slack.action(Actions.ORDERS, async ({ body, client }) => { + const view = await client.views.push({ + trigger_id: (body as any).trigger_id, + view: Loading.loading(), + }); + + const user = await prisma.user.findFirst({ + where: { + slackUser: { + slackId: body.user.id, + } + } + }); + + if (!user || !user.metadata.airtable) { + await Slack.views.update({ + view_id: view.view?.id, + view: Loading.error(t('error.not_a_user')) + }); + + return; + } + + const orders = await AirtableAPI.Orders.findByUser(user.metadata.airtable.id); + + await Slack.views.update({ + view_id: view.view?.id, + view: Orders.order(orders) + }); +}); \ No newline at end of file diff --git a/src/extensions/arcade/slack/views/orders.ts b/src/extensions/arcade/slack/views/orders.ts new file mode 100644 index 00000000..a30f6b08 --- /dev/null +++ b/src/extensions/arcade/slack/views/orders.ts @@ -0,0 +1,55 @@ +import { KnownBlock, View } from "@slack/bolt"; +import { AirtableOrdersRead } from "../../../../lib/airtable.js"; + +export class Orders { + public static order(orders: AirtableOrdersRead[]): View { + const blocks: KnownBlock[] = []; + + if (orders.length === 0) { + blocks.push({ + type: "section", + text: { + type: "mrkdwn", + text: "You have no orders." + } + }); + } else { + + for (const order of orders) { + blocks.push({ + type: "section", + text: { + type: "mrkdwn", + text: + `*${order["Item: Name"]}* +_Status:_ ${order["Status"]} +_Quantity:_ ${order["Quantity"]} +_Price:_ ${Math.floor(order["Order Price (Minutes)"] / 60)}` + }, + accessory: { + type: "image", + image_url: order["Item: Image"], + alt_text: order["Item: Name"], + } + }, { + type: "divider", + }); + } + } + + return { + type: "modal" as const, + title: { + type: "plain_text" as const, + text: "orders", + emoji: true, + }, + close: { + type: "plain_text" as const, + text: "close", + emoji: true, + }, + blocks, + }; + } +} \ No newline at end of file diff --git a/src/extensions/arcade/slack/views/shop.ts b/src/extensions/arcade/slack/views/shop.ts index 10e1bcff..dd095660 100644 --- a/src/extensions/arcade/slack/views/shop.ts +++ b/src/extensions/arcade/slack/views/shop.ts @@ -97,7 +97,16 @@ _How do I get tickets?_\n- Provide { @@ -355,6 +366,21 @@ export const AirtableAPI = { // Return a list of endpoints return records.map(record => ({id: record.id, fields: record.fields as AirtableAPIRead})); } + }, + Orders: { + async findByUser(user: AirtableRecordID): Promise { + console.log(`[AirtableAPI.Orders.findByUser] Finding orders for ${user}`) + + const now = Date.now(); + + const records = await orders.select({ + filterByFormula: `{User} = "${user}"` + }).all(); + + console.log(`[AirtableAPI.Orders.findByUser] Took ${Date.now() - now}ms`) + + return records.map(record => record.fields as AirtableOrdersRead); + } } }; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 4624a32a..37d0ded4 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -113,6 +113,8 @@ export const Actions = { SESSIONS_PREVIOUS: 'sessionsprevious', SESSIONS_NEXT: 'sessionsnext', + + ORDERS: 'orders', }; export const Callbacks = { From c8563d079459e7405e46af39767dd7389986a719 Mon Sep 17 00:00:00 2001 From: techpixel Date: Tue, 25 Jun 2024 23:34:31 +0000 Subject: [PATCH 3/5] complete orders view --- src/extensions/arcade/slack/orders.ts | 5 ++++- src/extensions/arcade/slack/views/orders.ts | 11 +++++------ src/lib/airtable.ts | 10 ++++++---- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/extensions/arcade/slack/orders.ts b/src/extensions/arcade/slack/orders.ts index 6527b28b..e385f7fa 100644 --- a/src/extensions/arcade/slack/orders.ts +++ b/src/extensions/arcade/slack/orders.ts @@ -29,7 +29,10 @@ Slack.action(Actions.ORDERS, async ({ body, client }) => { return; } - const orders = await AirtableAPI.Orders.findByUser(user.metadata.airtable.id); + // const orders = await AirtableAPI.Orders.findByUser(user.metadata.airtable.id); + const orders = await AirtableAPI.Orders.findByUser('rec6p5Fv3KCgYuemQ'); + + console.log(JSON.stringify(Orders.order(orders))); await Slack.views.update({ view_id: view.view?.id, diff --git a/src/extensions/arcade/slack/views/orders.ts b/src/extensions/arcade/slack/views/orders.ts index a30f6b08..20e46a5c 100644 --- a/src/extensions/arcade/slack/views/orders.ts +++ b/src/extensions/arcade/slack/views/orders.ts @@ -14,7 +14,6 @@ export class Orders { } }); } else { - for (const order of orders) { blocks.push({ type: "section", @@ -24,13 +23,13 @@ export class Orders { `*${order["Item: Name"]}* _Status:_ ${order["Status"]} _Quantity:_ ${order["Quantity"]} -_Price:_ ${Math.floor(order["Order Price (Minutes)"] / 60)}` +_Price:_ ${Math.floor(order["Order Price (Minutes)"] / 60)} :tw_admission_tickets:` }, - accessory: { + accessory: order["Item: Image"][0] ? { type: "image", - image_url: order["Item: Image"], - alt_text: order["Item: Name"], - } + image_url: order["Item: Image"][0], + alt_text: order["Item: Name"][0], + } : undefined }, { type: "divider", }); diff --git a/src/lib/airtable.ts b/src/lib/airtable.ts index 12081798..977f9b9e 100644 --- a/src/lib/airtable.ts +++ b/src/lib/airtable.ts @@ -130,11 +130,12 @@ type AirtableAPIRead = { export type AirtableOrdersRead = { "User": [AirtableRecordID], - "Item: Name": string, - "Item: Image": string, + "Item: Name": [string], + "Item: Image": [string], "Status": "Awaiting Fulfillment" | "Fulfilled" | "Declined (Insufficient balance)" | "Declined (Failed age verification)" | "Declined (Other reason)" | "Incomplete Fillout Submission" "Quantity": number, "Order Price (Minutes)": number, + "User: Record ID": AirtableRecordID, } export const AirtableAPI = { @@ -374,8 +375,9 @@ export const AirtableAPI = { const now = Date.now(); const records = await orders.select({ - filterByFormula: `{User} = "${user}"` - }).all(); + filterByFormula: `{User: Record ID} = "${user}"` + }).all() + .catch(error => { console.error(error); return [] }); console.log(`[AirtableAPI.Orders.findByUser] Took ${Date.now() - now}ms`) From 35d62c218a715a0505839ce8f6e1072011ccfbee Mon Sep 17 00:00:00 2001 From: techpixel Date: Tue, 25 Jun 2024 23:45:56 +0000 Subject: [PATCH 4/5] remove locked logging --- src/extensions/arcade/slack/orders.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/extensions/arcade/slack/orders.ts b/src/extensions/arcade/slack/orders.ts index e385f7fa..2d54e47c 100644 --- a/src/extensions/arcade/slack/orders.ts +++ b/src/extensions/arcade/slack/orders.ts @@ -29,8 +29,7 @@ Slack.action(Actions.ORDERS, async ({ body, client }) => { return; } - // const orders = await AirtableAPI.Orders.findByUser(user.metadata.airtable.id); - const orders = await AirtableAPI.Orders.findByUser('rec6p5Fv3KCgYuemQ'); + const orders = await AirtableAPI.Orders.findByUser(user.metadata.airtable.id); console.log(JSON.stringify(Orders.order(orders))); From 01d3eeeacbb6bdd782bc0224014a5d11ad445595 Mon Sep 17 00:00:00 2001 From: techpixel Date: Tue, 25 Jun 2024 23:50:49 +0000 Subject: [PATCH 5/5] cleanup --- src/extensions/arcade/slack/orders.ts | 2 -- src/extensions/arcade/slack/views/shop.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/extensions/arcade/slack/orders.ts b/src/extensions/arcade/slack/orders.ts index 2d54e47c..6527b28b 100644 --- a/src/extensions/arcade/slack/orders.ts +++ b/src/extensions/arcade/slack/orders.ts @@ -31,8 +31,6 @@ Slack.action(Actions.ORDERS, async ({ body, client }) => { const orders = await AirtableAPI.Orders.findByUser(user.metadata.airtable.id); - console.log(JSON.stringify(Orders.order(orders))); - await Slack.views.update({ view_id: view.view?.id, view: Orders.order(orders) diff --git a/src/extensions/arcade/slack/views/shop.ts b/src/extensions/arcade/slack/views/shop.ts index dd095660..716ba526 100644 --- a/src/extensions/arcade/slack/views/shop.ts +++ b/src/extensions/arcade/slack/views/shop.ts @@ -69,7 +69,7 @@ _How do I get tickets?_\n- Provide