From 0bbd0b50044deb6afcee0a25b1a44d5a61f9579f Mon Sep 17 00:00:00 2001 From: Kevin Kipp Date: Fri, 20 Sep 2024 16:50:54 -0500 Subject: [PATCH] Count meetings and associate feedback --- app/components/LeaveRoomButton.tsx | 8 +- app/durableObjects/ChatRoom.server.ts | 109 +++++++++++++-- app/routes/_room.$roomName.room.tsx | 12 +- app/routes/call-quality-feedback.tsx | 41 ++++-- app/types/Messages.ts | 1 + migrations/0001_daily_blink.sql | 17 +++ migrations/meta/0001_snapshot.json | 190 ++++++++++++++++++++++++++ migrations/meta/_journal.json | 7 + package.json | 2 +- schema.ts | 14 +- 10 files changed, 374 insertions(+), 27 deletions(-) create mode 100644 migrations/0001_daily_blink.sql create mode 100644 migrations/meta/0001_snapshot.json diff --git a/app/components/LeaveRoomButton.tsx b/app/components/LeaveRoomButton.tsx index 86b0934d..01da2d46 100644 --- a/app/components/LeaveRoomButton.tsx +++ b/app/components/LeaveRoomButton.tsx @@ -7,10 +7,12 @@ import { Tooltip } from './Tooltip' interface LeaveRoomButtonProps { navigateToFeedbackPage: boolean + meetingId?: string } export const LeaveRoomButton: FC = ({ navigateToFeedbackPage, + meetingId, }) => { const navigate = useNavigate() return ( @@ -18,7 +20,11 @@ export const LeaveRoomButton: FC = ({ - - + {meetingId ? ( + <> +

Experience any issues?

+
+ + + +
+ + ) : ( +

Missing meetingId

+ )} ) } diff --git a/app/types/Messages.ts b/app/types/Messages.ts index f08bd898..b262f0ea 100644 --- a/app/types/Messages.ts +++ b/app/types/Messages.ts @@ -16,6 +16,7 @@ export type User = { } export type RoomState = { + meetingId?: string users: User[] } diff --git a/migrations/0001_daily_blink.sql b/migrations/0001_daily_blink.sql new file mode 100644 index 00000000..68c80917 --- /dev/null +++ b/migrations/0001_daily_blink.sql @@ -0,0 +1,17 @@ +CREATE TABLE `Meetings` ( + `id` text PRIMARY KEY NOT NULL, + `created` text DEFAULT CURRENT_TIMESTAMP NOT NULL, + `modified` text DEFAULT CURRENT_TIMESTAMP NOT NULL, + `deleted` text, + `userCount` integer NOT NULL, + `ended` text +); +--> statement-breakpoint +ALTER TABLE `AnalyticsSimpleCallFeedback` ADD `meetingId` text NOT NULL REFERENCES Meetings(id);--> statement-breakpoint +/* + SQLite does not support "Creating foreign key on existing column" out of the box, we do not generate automatic migration for that, so it has to be done manually + Please refer to: https://www.techonthenet.com/sqlite/tables/alter_table.php + https://www.sqlite.org/lang_altertable.html + + Due to that we don't generate migration automatically and it has to be done manually +*/ \ No newline at end of file diff --git a/migrations/meta/0001_snapshot.json b/migrations/meta/0001_snapshot.json new file mode 100644 index 00000000..2b0ccf7c --- /dev/null +++ b/migrations/meta/0001_snapshot.json @@ -0,0 +1,190 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "0160d517-1dc2-44a6-ac94-fa3dd182c488", + "prevId": "fe0342f9-5cae-44a5-86d3-368c43bf7869", + "tables": { + "AnalyticsRefreshes": { + "name": "AnalyticsRefreshes", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "created": { + "name": "created", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "modified": { + "name": "modified", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "deleted": { + "name": "deleted", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "AnalyticsSimpleCallFeedback": { + "name": "AnalyticsSimpleCallFeedback", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "created": { + "name": "created", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "modified": { + "name": "modified", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "deleted": { + "name": "deleted", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "experiencedIssues": { + "name": "experiencedIssues", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "meetingId": { + "name": "meetingId", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "AnalyticsSimpleCallFeedback_meetingId_Meetings_id_fk": { + "name": "AnalyticsSimpleCallFeedback_meetingId_Meetings_id_fk", + "tableFrom": "AnalyticsSimpleCallFeedback", + "tableTo": "Meetings", + "columnsFrom": [ + "meetingId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "Meetings": { + "name": "Meetings", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "created": { + "name": "created", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "modified": { + "name": "modified", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "deleted": { + "name": "deleted", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "userCount": { + "name": "userCount", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ended": { + "name": "ended", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/migrations/meta/_journal.json b/migrations/meta/_journal.json index 9c25e5d4..adedebf9 100644 --- a/migrations/meta/_journal.json +++ b/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1726697068248, "tag": "0000_warm_siren", "breakpoints": true + }, + { + "idx": 1, + "version": "6", + "when": 1726868649369, + "tag": "0001_daily_blink", + "breakpoints": true } ] } \ No newline at end of file diff --git a/package.json b/package.json index 8d9bd2aa..557edfc4 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "test:e2e": "playwright test --headed", "check": "npm run lint && npm run typecheck && npm run test:ci", "db:generate": "drizzle-kit generate", - "db:migrate:local": "wrangler d1 migrations apply orange-meets-db --local", + "db:migrate:local": "wrangler d1 migrations apply orange-meets-db-development --local", "db:studio:local": "LOCAL_DB_PATH=$(find .wrangler/state/v3/d1/miniflare-D1DatabaseObject -type f -name '*.sqlite' -print -quit) drizzle-kit studio" }, "dependencies": { diff --git a/schema.ts b/schema.ts index f8cf2784..4988ed9e 100644 --- a/schema.ts +++ b/schema.ts @@ -1,7 +1,7 @@ -import type { AppLoadContext } from '@remix-run/cloudflare' import { sql } from 'drizzle-orm' import { drizzle } from 'drizzle-orm/d1' import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core' +import type { Env } from '~/types/Env' const metadataColumns = { id: integer('id').primaryKey({ autoIncrement: true }), @@ -25,10 +25,20 @@ export const AnalyticsSimpleCallFeedback = sqliteTable( ...metadataColumns, version: text('version').notNull(), experiencedIssues: integer('experiencedIssues').notNull(), + meetingId: text('meetingId') + .references(() => Meetings.id) + .notNull(), } ) -export function getDb(context: AppLoadContext) { +export const Meetings = sqliteTable('Meetings', { + ...metadataColumns, + id: text('id').primaryKey(), + peakUserCount: integer('userCount').notNull(), + ended: text('ended'), +}) + +export function getDb(context: { env: Env }) { if (!context.env.DB) { return null }