From 7aef5fa12b9a5075b9aa676f6bc369598d1f0da7 Mon Sep 17 00:00:00 2001 From: katien Date: Sat, 24 Oct 2020 16:15:55 -0600 Subject: [PATCH 1/6] add nullable url column to model, create migration to add url column to event table, update event seeders to generate fake event urls --- db/generator/factories/events.factory.ts | 3 ++- db/migrations/1603576293055-AddUrlColumnToEvent.ts | 13 +++++++++++++ server/models/Event.ts | 7 +++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 db/migrations/1603576293055-AddUrlColumnToEvent.ts diff --git a/db/generator/factories/events.factory.ts b/db/generator/factories/events.factory.ts index 3a74867139..f415c999c8 100644 --- a/db/generator/factories/events.factory.ts +++ b/db/generator/factories/events.factory.ts @@ -1,4 +1,4 @@ -import { company, lorem } from 'faker'; +import { company, lorem, internet } from 'faker'; import { Event, Venue, @@ -21,6 +21,7 @@ const createEvents = async ( name: company.companyName(), chapter: randomItem(chapters), description: lorem.words(), + url: internet.url(), capacity: random(1000), venue: randomItem(venues), canceled: Math.random() > 0.5, diff --git a/db/migrations/1603576293055-AddUrlColumnToEvent.ts b/db/migrations/1603576293055-AddUrlColumnToEvent.ts new file mode 100644 index 0000000000..ab0d3afc06 --- /dev/null +++ b/db/migrations/1603576293055-AddUrlColumnToEvent.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddUrlColumnToEvent1603576293055 implements MigrationInterface { + name = 'AddUrlColumnToEvent1603576293055'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "events" ADD "url" character varying`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "events" DROP COLUMN "url"`); + } +} diff --git a/server/models/Event.ts b/server/models/Event.ts index 1a17246849..a5e905f637 100644 --- a/server/models/Event.ts +++ b/server/models/Event.ts @@ -18,6 +18,10 @@ export class Event extends BaseModel { @Column({ nullable: false }) description!: string; + @Field(() => String, { nullable: true }) + @Column({ nullable: true }) + url?: string; + @Field(() => Date) @Column({ type: 'timestamp' }) start_at!: Date; @@ -77,6 +81,7 @@ export class Event extends BaseModel { constructor(params: { name: string; description: string; + url?: string; start_at: Date; ends_at: Date; canceled?: boolean; @@ -89,6 +94,7 @@ export class Event extends BaseModel { const { name, description, + url, start_at, ends_at, canceled, @@ -99,6 +105,7 @@ export class Event extends BaseModel { this.name = name; this.description = description; + this.url = url; this.start_at = start_at; this.ends_at = ends_at; this.canceled = canceled || false; From 9fb800cb9eea0ecf9503f889c2f50a234b3216d8 Mon Sep 17 00:00:00 2001 From: katien Date: Sat, 24 Oct 2020 17:31:53 -0600 Subject: [PATCH 2/6] update UI to display event url --- client/graphql.schema.json | 36 +++++++++++++++++++ client/src/generated/index.tsx | 20 +++++++++-- .../Events/components/EventFormUtils.ts | 7 ++++ .../dashboard/Events/components/EventItem.tsx | 1 + .../dashboard/Events/graphql/queries.ts | 4 +++ .../dashboard/Events/pages/EventPage.tsx | 3 +- server/controllers/Events/inputs.ts | 6 ++++ server/controllers/Events/resolver.ts | 1 + 8 files changed, 74 insertions(+), 4 deletions(-) diff --git a/client/graphql.schema.json b/client/graphql.schema.json index 48aaaa7e0c..222c726d78 100644 --- a/client/graphql.schema.json +++ b/client/graphql.schema.json @@ -547,6 +547,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "url", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "start_at", "description": null, @@ -2761,6 +2773,20 @@ }, "defaultValue": null }, + { + "name": "url", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, { "name": "start_at", "description": null, @@ -2862,6 +2888,16 @@ }, "defaultValue": null }, + { + "name": "url", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, { "name": "start_at", "description": null, diff --git a/client/src/generated/index.tsx b/client/src/generated/index.tsx index 14c9046155..83ef9bc8c0 100644 --- a/client/src/generated/index.tsx +++ b/client/src/generated/index.tsx @@ -63,6 +63,7 @@ export type Event = { updated_at: Scalars['DateTime']; name: Scalars['String']; description: Scalars['String']; + url?: Maybe; start_at: Scalars['DateTime']; ends_at: Scalars['DateTime']; canceled: Scalars['Boolean']; @@ -280,6 +281,7 @@ export type UpdateVenueInputs = { export type CreateEventInputs = { name: Scalars['String']; description: Scalars['String']; + url: Scalars['String']; start_at: Scalars['DateTime']; ends_at: Scalars['DateTime']; capacity: Scalars['Float']; @@ -290,6 +292,7 @@ export type CreateEventInputs = { export type UpdateEventInputs = { name?: Maybe; description?: Maybe; + url?: Maybe; start_at?: Maybe; ends_at?: Maybe; capacity?: Maybe; @@ -302,7 +305,7 @@ export type EventsQuery = { __typename?: 'Query' } & { events: Array< { __typename?: 'Event' } & Pick< Event, - 'id' | 'name' | 'canceled' | 'description' | 'capacity' + 'id' | 'name' | 'canceled' | 'description' | 'url' | 'capacity' > & { tags?: Maybe>>; } @@ -320,6 +323,7 @@ export type EventQuery = { __typename?: 'Query' } & { | 'id' | 'name' | 'description' + | 'url' | 'canceled' | 'capacity' | 'start_at' @@ -356,7 +360,13 @@ export type EventVenuesQuery = { __typename?: 'Query' } & { event?: Maybe< { __typename?: 'Event' } & Pick< Event, - 'id' | 'name' | 'description' | 'capacity' | 'start_at' | 'ends_at' + | 'id' + | 'name' + | 'description' + | 'url' + | 'capacity' + | 'start_at' + | 'ends_at' > & { tags?: Maybe>>; venue: { __typename?: 'Venue' } & Pick; @@ -372,7 +382,7 @@ export type CreateEventMutationVariables = Exact<{ export type CreateEventMutation = { __typename?: 'Mutation' } & { createEvent: { __typename?: 'Event' } & Pick< Event, - 'id' | 'name' | 'canceled' | 'description' | 'capacity' + 'id' | 'name' | 'canceled' | 'description' | 'url' | 'capacity' > & { tags?: Maybe>>; }; @@ -489,6 +499,7 @@ export const EventsDocument = gql` name canceled description + url capacity tags { id @@ -547,6 +558,7 @@ export const EventDocument = gql` id name description + url canceled capacity start_at @@ -627,6 +639,7 @@ export const EventVenuesDocument = gql` id name description + url capacity start_at ends_at @@ -698,6 +711,7 @@ export const CreateEventDocument = gql` name canceled description + url capacity tags { id diff --git a/client/src/modules/dashboard/Events/components/EventFormUtils.ts b/client/src/modules/dashboard/Events/components/EventFormUtils.ts index ae0a9eab3b..6072b62ecc 100644 --- a/client/src/modules/dashboard/Events/components/EventFormUtils.ts +++ b/client/src/modules/dashboard/Events/components/EventFormUtils.ts @@ -21,6 +21,12 @@ export const fields: IField[] = [ label: 'Description', placeholder: '', }, + { + key: 'url', + type: 'text', + label: 'url', + placeholder: '', + }, { key: 'capacity', type: 'number', @@ -52,6 +58,7 @@ export const fields: IField[] = [ export interface IEventFormData { name: string; description: string; + url?: string; capacity: number; tags: string; start_at: string; diff --git a/client/src/modules/dashboard/Events/components/EventItem.tsx b/client/src/modules/dashboard/Events/components/EventItem.tsx index 7db388cd3b..be0532d058 100644 --- a/client/src/modules/dashboard/Events/components/EventItem.tsx +++ b/client/src/modules/dashboard/Events/components/EventItem.tsx @@ -37,6 +37,7 @@ const EventItem: React.FC = ({ loading, event }) => { {event.description} + {event.url} {event.capacity} diff --git a/client/src/modules/dashboard/Events/graphql/queries.ts b/client/src/modules/dashboard/Events/graphql/queries.ts index 6060cfd0e8..13fcbbfc77 100644 --- a/client/src/modules/dashboard/Events/graphql/queries.ts +++ b/client/src/modules/dashboard/Events/graphql/queries.ts @@ -7,6 +7,7 @@ export const EVENTS = gql` name canceled description + url capacity tags { id @@ -22,6 +23,7 @@ export const EVENT = gql` id name description + url canceled capacity start_at @@ -58,6 +60,7 @@ export const EVENT_WITH_VENU = gql` id name description + url capacity start_at ends_at @@ -83,6 +86,7 @@ export const createEvent = gql` name canceled description + url capacity tags { id diff --git a/client/src/modules/dashboard/Events/pages/EventPage.tsx b/client/src/modules/dashboard/Events/pages/EventPage.tsx index 4f2ea2eec0..fdbe4f8179 100644 --- a/client/src/modules/dashboard/Events/pages/EventPage.tsx +++ b/client/src/modules/dashboard/Events/pages/EventPage.tsx @@ -24,7 +24,7 @@ export const EventPage: NextPage = () => { {loading ? 'Loading...' : !error - ? 'Cant find event :(' + ? "Can't find event :(" : 'Error...'} @@ -48,6 +48,7 @@ export const EventPage: NextPage = () => { {data.event.description} + {data.event.url} {data.event.capacity} diff --git a/server/controllers/Events/inputs.ts b/server/controllers/Events/inputs.ts index d70e473607..0998f88718 100644 --- a/server/controllers/Events/inputs.ts +++ b/server/controllers/Events/inputs.ts @@ -8,6 +8,9 @@ export class CreateEventInputs { @Field(() => String) description: string; + @Field(() => String, { nullable: true }) + url?: string; + @Field(() => Date) start_at: number; @@ -32,6 +35,9 @@ export class UpdateEventInputs { @Field(() => String, { nullable: true }) description: string; + @Field(() => String, { nullable: true }) + url?: string; + @Field(() => Date, { nullable: true }) start_at: number; diff --git a/server/controllers/Events/resolver.ts b/server/controllers/Events/resolver.ts index c21eca6771..5996c6e2aa 100644 --- a/server/controllers/Events/resolver.ts +++ b/server/controllers/Events/resolver.ts @@ -47,6 +47,7 @@ export class EventResolver { event.name = data.name ?? event.name; event.description = data.description ?? event.description; + event.url = data.url ?? event.url; event.start_at = new Date(data.start_at) ?? event.start_at; event.ends_at = new Date(data.ends_at) ?? event.ends_at; event.capacity = data.capacity ?? event.capacity; From a688f8645a9f9b8b9e56f8b67c68150d6ff1c675 Mon Sep 17 00:00:00 2001 From: katien Date: Sat, 24 Oct 2020 17:39:31 -0600 Subject: [PATCH 3/6] conditionally render anchor if event has a url, add missing type info --- .../src/modules/dashboard/Events/components/EventFormUtils.ts | 2 +- client/src/modules/dashboard/Events/components/EventItem.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/modules/dashboard/Events/components/EventFormUtils.ts b/client/src/modules/dashboard/Events/components/EventFormUtils.ts index 6072b62ecc..06b79f3bc0 100644 --- a/client/src/modules/dashboard/Events/components/EventFormUtils.ts +++ b/client/src/modules/dashboard/Events/components/EventFormUtils.ts @@ -58,7 +58,7 @@ export const fields: IField[] = [ export interface IEventFormData { name: string; description: string; - url?: string; + url?: string | null; capacity: number; tags: string; start_at: string; diff --git a/client/src/modules/dashboard/Events/components/EventItem.tsx b/client/src/modules/dashboard/Events/components/EventItem.tsx index be0532d058..83c9c93d24 100644 --- a/client/src/modules/dashboard/Events/components/EventItem.tsx +++ b/client/src/modules/dashboard/Events/components/EventItem.tsx @@ -10,7 +10,7 @@ import Actions from './Actions'; interface IEventItemProps { event: Pick< Event, - 'id' | 'name' | 'description' | 'capacity' | 'canceled' + 'id' | 'name' | 'description' | 'url' | 'capacity' | 'canceled' > & { tags?: Pick[] | null }; loading: boolean; } @@ -37,7 +37,7 @@ const EventItem: React.FC = ({ loading, event }) => { {event.description} - {event.url} + {event.url && {event.url}} {event.capacity} From b7a27095d7b5ba0b858e7bec138f27222944a531 Mon Sep 17 00:00:00 2001 From: katien Date: Sun, 25 Oct 2020 15:01:00 -0600 Subject: [PATCH 4/6] event url validation --- server/controllers/Events/resolver.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/server/controllers/Events/resolver.ts b/server/controllers/Events/resolver.ts index 5996c6e2aa..82d9f5eb27 100644 --- a/server/controllers/Events/resolver.ts +++ b/server/controllers/Events/resolver.ts @@ -31,6 +31,7 @@ export class EventResolver { venue, chapter, }); + if (event.url != undefined) this.validateEventUrl(event.url); return event.save(); } @@ -57,7 +58,7 @@ export class EventResolver { if (!venue) throw new Error('Cant find venue'); event.venue = venue; } - + if (event.url != undefined) this.validateEventUrl(event.url); return event.save(); } @@ -81,4 +82,12 @@ export class EventResolver { return true; } + + validateEventUrl(url) { + try { + new URL(url); + } catch (e) { + throw new Error('Invalid event URL supplied'); + } + } } From a1f1d3042f00a996721a9d674e653ab534ec4528 Mon Sep 17 00:00:00 2001 From: katien Date: Sun, 25 Oct 2020 15:03:10 -0600 Subject: [PATCH 5/6] handle empty strings event urls --- server/controllers/Events/resolver.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/controllers/Events/resolver.ts b/server/controllers/Events/resolver.ts index 82d9f5eb27..e09ee0f943 100644 --- a/server/controllers/Events/resolver.ts +++ b/server/controllers/Events/resolver.ts @@ -31,7 +31,7 @@ export class EventResolver { venue, chapter, }); - if (event.url != undefined) this.validateEventUrl(event.url); + if (event.url) this.validateEventUrl(event.url); return event.save(); } @@ -58,7 +58,7 @@ export class EventResolver { if (!venue) throw new Error('Cant find venue'); event.venue = venue; } - if (event.url != undefined) this.validateEventUrl(event.url); + if (event.url) this.validateEventUrl(event.url); return event.save(); } From 5b2c4b700c11abf9d2f0e078a0e370f5b6ee9211 Mon Sep 17 00:00:00 2001 From: katien Date: Mon, 26 Oct 2020 13:06:50 -0600 Subject: [PATCH 6/6] remove URL validation --- server/controllers/Events/resolver.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/server/controllers/Events/resolver.ts b/server/controllers/Events/resolver.ts index e09ee0f943..6665134667 100644 --- a/server/controllers/Events/resolver.ts +++ b/server/controllers/Events/resolver.ts @@ -31,7 +31,6 @@ export class EventResolver { venue, chapter, }); - if (event.url) this.validateEventUrl(event.url); return event.save(); } @@ -58,7 +57,6 @@ export class EventResolver { if (!venue) throw new Error('Cant find venue'); event.venue = venue; } - if (event.url) this.validateEventUrl(event.url); return event.save(); } @@ -82,12 +80,4 @@ export class EventResolver { return true; } - - validateEventUrl(url) { - try { - new URL(url); - } catch (e) { - throw new Error('Invalid event URL supplied'); - } - } }