diff --git a/packages/client/components/ActivityLibrary/ActivityDetailsSidebar.tsx b/packages/client/components/ActivityLibrary/ActivityDetailsSidebar.tsx
index 3d688e42d93..65f2f386017 100644
--- a/packages/client/components/ActivityLibrary/ActivityDetailsSidebar.tsx
+++ b/packages/client/components/ActivityLibrary/ActivityDetailsSidebar.tsx
@@ -5,16 +5,14 @@ import clsx from 'clsx'
import React, {useEffect, useRef, useState} from 'react'
import {useFragment} from 'react-relay'
import {useHistory} from 'react-router'
+import {RRule} from 'rrule'
import {ActivityDetailsSidebar_teams$key} from '~/__generated__/ActivityDetailsSidebar_teams.graphql'
import {ActivityDetailsSidebar_template$key} from '~/__generated__/ActivityDetailsSidebar_template.graphql'
import StartRetrospectiveMutation from '~/mutations/StartRetrospectiveMutation'
import StartSprintPokerMutation from '~/mutations/StartSprintPokerMutation'
import UpdateReflectTemplateScopeMutation from '~/mutations/UpdateReflectTemplateScopeMutation'
import {MeetingTypeEnum} from '../../__generated__/ActivityDetailsQuery.graphql'
-import {
- CreateGcalEventInput,
- RecurrenceSettingsInput
-} from '../../__generated__/StartRetrospectiveMutation.graphql'
+import {CreateGcalEventInput} from '../../__generated__/StartRetrospectiveMutation.graphql'
import useAtmosphere from '../../hooks/useAtmosphere'
import useMutationProps from '../../hooks/useMutationProps'
import SelectTemplateMutation from '../../mutations/SelectTemplateMutation'
@@ -116,10 +114,7 @@ const ActivityDetailsSidebar = (props: Props) => {
const {onError, onCompleted, submitting, submitMutation, error} = mutationProps
const history = useHistory()
- const handleStartActivity = (
- gcalInput?: CreateGcalEventInput,
- recurrenceSettings?: RecurrenceSettingsInput
- ) => {
+ const handleStartActivity = (name?: string, rrule?: RRule, gcalInput?: CreateGcalEventInput) => {
if (submitting) return
submitMutation()
if (type === 'teamPrompt') {
@@ -127,12 +122,8 @@ const ActivityDetailsSidebar = (props: Props) => {
atmosphere,
{
teamId: selectedTeam.id,
- recurrenceSettings: recurrenceSettings
- ? {
- rrule: recurrenceSettings.rrule?.toString(),
- name: recurrenceSettings.name
- }
- : undefined,
+ name,
+ rrule: rrule?.toString(),
gcalInput
},
{history, onError, onCompleted}
@@ -155,12 +146,8 @@ const ActivityDetailsSidebar = (props: Props) => {
atmosphere,
{
teamId: selectedTeam.id,
- recurrenceSettings: recurrenceSettings
- ? {
- rrule: recurrenceSettings.rrule?.toString(),
- name: recurrenceSettings.name
- }
- : undefined,
+ name,
+ rrule: rrule?.toString(),
gcalInput
},
{history, onError, onCompleted}
diff --git a/packages/client/components/ActivityLibrary/ScheduleMeetingButton.tsx b/packages/client/components/ActivityLibrary/ScheduleMeetingButton.tsx
index 3b66168331c..dda2754f057 100644
--- a/packages/client/components/ActivityLibrary/ScheduleMeetingButton.tsx
+++ b/packages/client/components/ActivityLibrary/ScheduleMeetingButton.tsx
@@ -1,11 +1,9 @@
import graphql from 'babel-plugin-relay/macro'
import React from 'react'
import {useFragment} from 'react-relay'
+import {RRule} from 'rrule'
import {ScheduleMeetingButton_team$key} from '~/__generated__/ScheduleMeetingButton_team.graphql'
-import {
- CreateGcalEventInput,
- RecurrenceSettingsInput
-} from '../../__generated__/StartRetrospectiveMutation.graphql'
+import {CreateGcalEventInput} from '../../__generated__/StartRetrospectiveMutation.graphql'
import useModal from '../../hooks/useModal'
import {MenuMutationProps} from '../../hooks/useMutationProps'
import DialogContainer from '../DialogContainer'
@@ -14,10 +12,7 @@ import SecondaryButton from '../SecondaryButton'
type Props = {
mutationProps: MenuMutationProps
- handleStartActivity: (
- gcalInput?: CreateGcalEventInput,
- recurrenceInput?: RecurrenceSettingsInput
- ) => void
+ handleStartActivity: (name?: string, rrule?: RRule, gcalInput?: CreateGcalEventInput) => void
teamRef: ScheduleMeetingButton_team$key
placeholder: string
withRecurrence?: boolean
@@ -60,11 +55,8 @@ const ScheduleMeetingButton = (props: Props) => {
const handleClick = () => {
toggleModal()
}
- const onStartActivity = (
- gcalInput?: CreateGcalEventInput,
- recurrenceInput?: RecurrenceSettingsInput
- ) => {
- handleStartActivity(gcalInput, recurrenceInput)
+ const onStartActivity = (name?: string, rrule?: RRule, gcalInput?: CreateGcalEventInput) => {
+ handleStartActivity(name, rrule, gcalInput)
closeModal()
}
diff --git a/packages/client/components/Recurrence/EndRecurringMeetingModal.tsx b/packages/client/components/Recurrence/EndRecurringMeetingModal.tsx
index 49c409083d9..2165e45b31f 100644
--- a/packages/client/components/Recurrence/EndRecurringMeetingModal.tsx
+++ b/packages/client/components/Recurrence/EndRecurringMeetingModal.tsx
@@ -86,7 +86,7 @@ export const EndRecurringMeetingModal = (props: Props) => {
if (!isMeetingOnly) {
UpdateRecurrenceSettingsMutation(
atmosphere,
- {meetingId, recurrenceSettings: {name: null, rrule: null}},
+ {meetingId, name: null, rrule: null},
{onError, onCompleted}
)
} else {
diff --git a/packages/client/components/Recurrence/RecurrenceSettings.tsx b/packages/client/components/Recurrence/RecurrenceSettings.tsx
index a1e039e913a..f5cca8d6f43 100644
--- a/packages/client/components/Recurrence/RecurrenceSettings.tsx
+++ b/packages/client/components/Recurrence/RecurrenceSettings.tsx
@@ -255,7 +255,7 @@ export const RecurrenceSettings = (props: Props) => {
The next meeting in this series will be called{' '}
- "{title} - {dayjs(recurrenceStartTime).format('MMM DD')}"
+ "{title} - {dayjs(new Date()).format('MMM DD')}"
)}
diff --git a/packages/client/components/Recurrence/UpdateRecurrenceSettingsModal.tsx b/packages/client/components/Recurrence/UpdateRecurrenceSettingsModal.tsx
index da69cf7f869..63c17f230f6 100644
--- a/packages/client/components/Recurrence/UpdateRecurrenceSettingsModal.tsx
+++ b/packages/client/components/Recurrence/UpdateRecurrenceSettingsModal.tsx
@@ -175,10 +175,8 @@ export const UpdateRecurrenceSettingsModal = (props: Props) => {
atmosphere,
{
meetingId: meeting.id,
- recurrenceSettings: {
- rrule: rrule?.toString(),
- name: title
- }
+ rrule: rrule?.toString(),
+ name: title
},
{onError, onCompleted: onRecurrenceSettingsUpdated}
)
@@ -190,7 +188,7 @@ export const UpdateRecurrenceSettingsModal = (props: Props) => {
UpdateRecurrenceSettingsMutation(
atmosphere,
- {meetingId: meeting.id, recurrenceSettings: {rrule: null}},
+ {meetingId: meeting.id, rrule: null},
{onError, onCompleted: onRecurrenceSettingsUpdated}
)
}
diff --git a/packages/client/components/ScheduleDialog.tsx b/packages/client/components/ScheduleDialog.tsx
index 8f26e708164..351f242064f 100644
--- a/packages/client/components/ScheduleDialog.tsx
+++ b/packages/client/components/ScheduleDialog.tsx
@@ -7,10 +7,7 @@ import React, {ChangeEvent, useState} from 'react'
import {useFragment} from 'react-relay'
import {RRule} from 'rrule'
import {ScheduleDialog_team$key} from '~/__generated__/ScheduleDialog_team.graphql'
-import {
- CreateGcalEventInput,
- RecurrenceSettingsInput
-} from '../__generated__/StartRetrospectiveMutation.graphql'
+import {CreateGcalEventInput} from '../__generated__/StartRetrospectiveMutation.graphql'
import useAtmosphere from '../hooks/useAtmosphere'
import useForm from '../hooks/useForm'
import {MenuMutationProps} from '../hooks/useMutationProps'
@@ -34,7 +31,7 @@ const validateTitle = (title: string) =>
new Legitity(title).trim().min(2, `C’mon, you call that a title?`)
interface Props {
- onStartActivity: (gcalInput?: CreateGcalEventInput, recurrence?: RecurrenceSettingsInput) => void
+ onStartActivity: (name?: string, rrule?: RRule, gcalInput?: CreateGcalEventInput) => void
placeholder: string
teamRef: ScheduleDialog_team$key
onCancel: () => void
@@ -101,16 +98,15 @@ export const ScheduleDialog = (props: Props) => {
}
const handleSubmit = () => {
- const title = fields.title.value || placeholder
- const titleRes = validateTitle(title)
- if (titleRes.error) {
- fields.title.setError(titleRes.error)
+ const name = fields.title.value || placeholder
+ const nameRes = validateTitle(name)
+ if (nameRes.error) {
+ fields.title.setError(nameRes.error)
return
}
const gcalEventInput = addedInvite
? {
- title,
startTimestamp: gcalInput.start.unix(),
endTimestamp: gcalInput.end.unix(),
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
@@ -118,7 +114,7 @@ export const ScheduleDialog = (props: Props) => {
videoType: gcalInput.videoType ?? undefined
}
: undefined
- props.onStartActivity(gcalEventInput, rrule ? {rrule} : undefined)
+ props.onStartActivity(name, rrule ?? undefined, gcalEventInput)
}
const onAddInvite = () => {
@@ -201,7 +197,11 @@ export const ScheduleDialog = (props: Props) => {
-
+
)}
diff --git a/packages/client/mutations/StartRetrospectiveMutation.ts b/packages/client/mutations/StartRetrospectiveMutation.ts
index ec3a120f8b9..5e60fc72048 100644
--- a/packages/client/mutations/StartRetrospectiveMutation.ts
+++ b/packages/client/mutations/StartRetrospectiveMutation.ts
@@ -25,14 +25,11 @@ graphql`
const mutation = graphql`
mutation StartRetrospectiveMutation(
$teamId: ID!
- $recurrenceSettings: RecurrenceSettingsInput
+ $name: String
+ $rrule: RRule
$gcalInput: CreateGcalEventInput
) {
- startRetrospective(
- teamId: $teamId
- recurrenceSettings: $recurrenceSettings
- gcalInput: $gcalInput
- ) {
+ startRetrospective(teamId: $teamId, name: $name, rrule: $rrule, gcalInput: $gcalInput) {
... on ErrorPayload {
error {
message
diff --git a/packages/client/mutations/StartTeamPromptMutation.ts b/packages/client/mutations/StartTeamPromptMutation.ts
index bc8821c3bd7..7320d2b7094 100644
--- a/packages/client/mutations/StartTeamPromptMutation.ts
+++ b/packages/client/mutations/StartTeamPromptMutation.ts
@@ -19,14 +19,11 @@ graphql`
const mutation = graphql`
mutation StartTeamPromptMutation(
$teamId: ID!
- $recurrenceSettings: RecurrenceSettingsInput
+ $name: String
+ $rrule: RRule
$gcalInput: CreateGcalEventInput
) {
- startTeamPrompt(
- teamId: $teamId
- recurrenceSettings: $recurrenceSettings
- gcalInput: $gcalInput
- ) {
+ startTeamPrompt(teamId: $teamId, name: $name, rrule: $rrule, gcalInput: $gcalInput) {
... on ErrorPayload {
error {
message
diff --git a/packages/client/mutations/UpdateRecurrenceSettingsMutation.ts b/packages/client/mutations/UpdateRecurrenceSettingsMutation.ts
index af0168c01ea..8646e886116 100644
--- a/packages/client/mutations/UpdateRecurrenceSettingsMutation.ts
+++ b/packages/client/mutations/UpdateRecurrenceSettingsMutation.ts
@@ -21,11 +21,8 @@ graphql`
`
const mutation = graphql`
- mutation UpdateRecurrenceSettingsMutation(
- $meetingId: ID!
- $recurrenceSettings: RecurrenceSettingsInput!
- ) {
- updateRecurrenceSettings(meetingId: $meetingId, recurrenceSettings: $recurrenceSettings) {
+ mutation UpdateRecurrenceSettingsMutation($meetingId: ID!, $name: String, $rrule: RRule) {
+ updateRecurrenceSettings(meetingId: $meetingId, name: $name, rrule: $rrule) {
... on ErrorPayload {
error {
message
diff --git a/packages/server/__tests__/startRetrospective.test.ts b/packages/server/__tests__/startRetrospective.test.ts
index 17deae321e5..2dc04eb1bd0 100644
--- a/packages/server/__tests__/startRetrospective.test.ts
+++ b/packages/server/__tests__/startRetrospective.test.ts
@@ -8,8 +8,8 @@ test('Retro is named Retro #1 by default', async () => {
const newRetro = await sendPublic({
query: `
- mutation StartRetrospectiveMutation($teamId: ID!, $recurrenceSettings: RecurrenceSettingsInput, $gcalInput: CreateGcalEventInput) {
- startRetrospective(teamId: $teamId, recurrenceSettings: $recurrenceSettings, gcalInput: $gcalInput) {
+ mutation StartRetrospectiveMutation($teamId: ID!, $name: String, $rrule: RRule, $gcalInput: CreateGcalEventInput) {
+ startRetrospective(teamId: $teamId, name: $name, rrule: $rrule, gcalInput: $gcalInput) {
... on ErrorPayload {
error {
message
@@ -34,7 +34,49 @@ test('Retro is named Retro #1 by default', async () => {
startRetrospective: {
meeting: {
id: expect.anything(),
- name: 'Retro 1'
+ name: 'Retro #1'
+ }
+ }
+ }
+ })
+})
+
+test('Single Retro can be named', async () => {
+ await getRethink()
+ const {userId, authToken} = await signUp()
+ const {id: teamId} = (await getUserTeams(userId))[0]
+
+ const name = 'My Retro'
+ const newRetro = await sendPublic({
+ query: `
+ mutation StartRetrospectiveMutation($teamId: ID!, $name: String, $rrule: RRule, $gcalInput: CreateGcalEventInput) {
+ startRetrospective(teamId: $teamId, name: $name, rrule: $rrule, gcalInput: $gcalInput) {
+ ... on ErrorPayload {
+ error {
+ message
+ }
+ }
+ ... on StartRetrospectiveSuccess {
+ meeting {
+ id
+ name
+ }
+ }
+ }
+ }
+ `,
+ variables: {
+ teamId,
+ name
+ },
+ authToken
+ })
+ expect(newRetro).toMatchObject({
+ data: {
+ startRetrospective: {
+ meeting: {
+ id: expect.anything(),
+ name
}
}
}
@@ -49,8 +91,8 @@ test('Recurring retro is named like RetroSeries Jan 1', async () => {
const now = new Date()
const newRetro = await sendPublic({
query: `
- mutation StartRetrospectiveMutation($teamId: ID!, $recurrenceSettings: RecurrenceSettingsInput, $gcalInput: CreateGcalEventInput) {
- startRetrospective(teamId: $teamId, recurrenceSettings: $recurrenceSettings, gcalInput: $gcalInput) {
+ mutation StartRetrospectiveMutation($teamId: ID!, $name: String, $rrule: RRule, $gcalInput: CreateGcalEventInput) {
+ startRetrospective(teamId: $teamId, name: $name, rrule: $rrule, gcalInput: $gcalInput) {
... on ErrorPayload {
error {
message
@@ -67,10 +109,8 @@ test('Recurring retro is named like RetroSeries Jan 1', async () => {
`,
variables: {
teamId,
- recurrenceSettings: {
- rrule: 'DTSTART;TZID=Europe/Berlin:20240117T060000\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=WE',
- name: 'RetroSeries'
- }
+ rrule: 'DTSTART;TZID=Europe/Berlin:20240117T060000\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=WE',
+ name: 'RetroSeries'
},
authToken
})
diff --git a/packages/server/database/types/MeetingAction.ts b/packages/server/database/types/MeetingAction.ts
index bc0157cdd16..fee9b580b8d 100644
--- a/packages/server/database/types/MeetingAction.ts
+++ b/packages/server/database/types/MeetingAction.ts
@@ -9,7 +9,7 @@ interface Input {
id?: string
teamId: string
meetingCount: number
- name?: string
+ name: string
phases: [CheckInMeetingPhase, ...CheckInMeetingPhase[]]
facilitatorUserId: string
}
@@ -32,7 +32,7 @@ export default class MeetingAction extends Meeting {
phases,
facilitatorUserId,
meetingType: 'action',
- name: name ?? `Check-in #${meetingCount + 1}`
+ name
})
}
}
diff --git a/packages/server/database/types/MeetingPoker.ts b/packages/server/database/types/MeetingPoker.ts
index 94c87c2826a..5883fd6d8ac 100644
--- a/packages/server/database/types/MeetingPoker.ts
+++ b/packages/server/database/types/MeetingPoker.ts
@@ -8,7 +8,7 @@ interface Input {
id: string
teamId: string
meetingCount: number
- name?: string
+ name: string
phases: [PokerPhase, ...PokerPhase[]]
facilitatorUserId: string
templateId: string
@@ -35,7 +35,7 @@ export default class MeetingPoker extends Meeting {
phases,
facilitatorUserId,
meetingType: 'poker',
- name: name ?? `Sprint Poker #${meetingCount + 1}`
+ name
})
this.templateId = templateId
this.templateRefId = templateRefId
diff --git a/packages/server/dataloader/customLoaderMakers.ts b/packages/server/dataloader/customLoaderMakers.ts
index 46a03715026..4de0beb1abb 100644
--- a/packages/server/dataloader/customLoaderMakers.ts
+++ b/packages/server/dataloader/customLoaderMakers.ts
@@ -858,3 +858,27 @@ export const fileStoreAsset = (parent: RootDataLoader) => {
}
)
}
+
+export const meetingCount = (parent: RootDataLoader) => {
+ return new DataLoader<{teamId: string; meetingType: MeetingTypeEnum}, number, string>(
+ async (keys) => {
+ const r = await getRethink()
+ const res = await Promise.all(
+ keys.map(async ({teamId, meetingType}) => {
+ return r
+ .table('NewMeeting')
+ .getAll(teamId, {index: 'teamId'})
+ .filter({meetingType: meetingType as any})
+ .count()
+ .default(0)
+ .run()
+ })
+ )
+ return res
+ },
+ {
+ ...parent.dataLoaderOptions,
+ cacheKeyFn: (key) => `${key.teamId}:${key.meetingType}`
+ }
+ )
+}
diff --git a/packages/server/graphql/mutations/helpers/createGcalEvent.ts b/packages/server/graphql/mutations/helpers/createGcalEvent.ts
index 575fc9e4cdd..8aaa7efeddd 100644
--- a/packages/server/graphql/mutations/helpers/createGcalEvent.ts
+++ b/packages/server/graphql/mutations/helpers/createGcalEvent.ts
@@ -24,6 +24,7 @@ const convertRruleToGcal = (rrule: RRule | null | undefined) => {
}
type Input = {
+ name: string
gcalInput?: CreateGcalEventInput | null
meetingId: string
viewerId: string
@@ -35,12 +36,12 @@ type Input = {
const createGcalEvent = async (
input: Input
): Promise<{gcalSeriesId?: string; error?: StandardMutationError}> => {
- const {gcalInput, meetingId, viewerId, dataLoader, teamId, rrule} = input
+ const {name, gcalInput, meetingId, viewerId, dataLoader, teamId, rrule} = input
if (!gcalInput) {
return {}
}
- const {startTimestamp, endTimestamp, title, timeZone, invitees, videoType} = gcalInput
+ const {startTimestamp, endTimestamp, timeZone, invitees, videoType} = gcalInput
const gcalAuth = await dataLoader.get('freshGcalAuth').load({teamId, userId: viewerId})
if (!gcalAuth) {
@@ -78,7 +79,7 @@ const createGcalEvent = async (
const recurrence = convertRruleToGcal(rrule)
const eventInput = {
- summary: title,
+ summary: name,
description,
start: {
dateTime: startDateTime,
@@ -115,14 +116,14 @@ const createGcalEvent = async (
export type UpdateGcalSeriesInput = {
gcalSeriesId: string
- title?: string
+ name?: string
rrule: RRule | null
userId: string
teamId: string
dataLoader: DataLoaderWorker
}
export const updateGcalSeries = async (input: UpdateGcalSeriesInput) => {
- const {gcalSeriesId, title, rrule, userId, teamId, dataLoader} = input
+ const {gcalSeriesId, name, rrule, userId, teamId, dataLoader} = input
const gcalAuth = await dataLoader.get('freshGcalAuth').load({teamId, userId})
if (!gcalAuth) {
@@ -146,7 +147,7 @@ export const updateGcalSeries = async (input: UpdateGcalSeriesInput) => {
eventId: gcalSeriesId,
requestBody: {
recurrence,
- summary: title
+ summary: name
},
conferenceDataVersion: 1
})
diff --git a/packages/server/graphql/mutations/helpers/safeCreateRetrospective.ts b/packages/server/graphql/mutations/helpers/safeCreateRetrospective.ts
index 221557c3b09..a756463e106 100644
--- a/packages/server/graphql/mutations/helpers/safeCreateRetrospective.ts
+++ b/packages/server/graphql/mutations/helpers/safeCreateRetrospective.ts
@@ -1,4 +1,3 @@
-import getRethink from '../../../database/rethinkDriver'
import MeetingRetrospective from '../../../database/types/MeetingRetrospective'
import generateUID from '../../../generateUID'
import {MeetingTypeEnum} from '../../../postgres/types/Meeting'
@@ -16,21 +15,14 @@ const safeCreateRetrospective = async (
videoMeetingURL?: string
meetingSeriesId?: number
scheduledEndTime?: Date
- name?: string
+ name: string
},
dataLoader: DataLoaderWorker
) => {
- const r = await getRethink()
const {teamId, facilitatorUserId, name} = meetingSettings
const meetingType: MeetingTypeEnum = 'retrospective'
const [meetingCount, team] = await Promise.all([
- r
- .table('NewMeeting')
- .getAll(teamId, {index: 'teamId'})
- .filter({meetingType})
- .count()
- .default(0)
- .run(),
+ dataLoader.get('meetingCount').load({teamId, meetingType}),
dataLoader.get('teams').loadNonNull(teamId)
])
@@ -38,7 +30,6 @@ const safeCreateRetrospective = async (
const {showConversionModal} = organization
const meetingId = generateUID()
- const meetingName = name ?? `Retro ${meetingCount + 1}`
const phases = await createNewMeetingPhases(
facilitatorUserId,
teamId,
@@ -54,7 +45,7 @@ const safeCreateRetrospective = async (
phases,
showConversionModal,
...meetingSettings,
- name: meetingName
+ name
})
}
diff --git a/packages/server/graphql/mutations/startSprintPoker.ts b/packages/server/graphql/mutations/startSprintPoker.ts
index 0c5388ba834..b25cc5364de 100644
--- a/packages/server/graphql/mutations/startSprintPoker.ts
+++ b/packages/server/graphql/mutations/startSprintPoker.ts
@@ -1,4 +1,4 @@
-import {GraphQLID, GraphQLNonNull} from 'graphql'
+import {GraphQLID, GraphQLNonNull, GraphQLString} from 'graphql'
import {SubscriptionChannel} from 'parabol-client/types/constEnums'
import toTeamMemberId from '../../../client/utils/relay/toTeamMemberId'
import getRethink from '../../database/rethinkDriver'
@@ -74,6 +74,10 @@ export default {
type: new GraphQLNonNull(GraphQLID),
description: 'The team starting the meeting'
},
+ name: {
+ type: GraphQLString,
+ description: 'The name of the meeting'
+ },
gcalInput: {
type: CreateGcalEventInput,
description: 'The gcal event to create. If not provided, no event will be created'
@@ -81,7 +85,11 @@ export default {
},
async resolve(
_source: unknown,
- {teamId, gcalInput}: {teamId: string; gcalInput?: CreateGcalEventInputType},
+ {
+ teamId,
+ name,
+ gcalInput
+ }: {teamId: string; name: string | null | undefined; gcalInput?: CreateGcalEventInputType},
{authToken, socketId: mutatorId, dataLoader}: GQLContext
) {
const r = await getRethink()
@@ -128,6 +136,7 @@ export default {
const meeting = new MeetingPoker({
id: meetingId,
teamId,
+ name: name ?? `Sprint Poker #${meetingCount + 1}`,
meetingCount,
phases,
facilitatorUserId: viewerId,
@@ -175,7 +184,14 @@ export default {
])
IntegrationNotifier.startMeeting(dataLoader, meetingId, teamId)
analytics.meetingStarted(viewer, meeting, template)
- const {error} = await createGcalEvent({gcalInput, meetingId, teamId, viewerId, dataLoader})
+ const {error} = await createGcalEvent({
+ name: meeting.name,
+ gcalInput,
+ meetingId,
+ teamId,
+ viewerId,
+ dataLoader
+ })
const data = {teamId, meetingId: meetingId, hasGcalError: !!error?.message}
publish(SubscriptionChannel.TEAM, teamId, 'StartSprintPokerSuccess', data, subOptions)
return data
diff --git a/packages/server/graphql/public/mutations/startCheckIn.ts b/packages/server/graphql/public/mutations/startCheckIn.ts
index 9c5f10de62b..c411c3fcd9d 100644
--- a/packages/server/graphql/public/mutations/startCheckIn.ts
+++ b/packages/server/graphql/public/mutations/startCheckIn.ts
@@ -17,7 +17,7 @@ import {MutationResolvers} from '../resolverTypes'
const startCheckIn: MutationResolvers['startCheckIn'] = async (
_source,
- {teamId, gcalInput},
+ {teamId, name, gcalInput},
context
) => {
const r = await getRethink()
@@ -59,6 +59,7 @@ const startCheckIn: MutationResolvers['startCheckIn'] = async (
const meeting = new MeetingAction({
id: meetingId,
teamId,
+ name: name ?? `Check-in #${meetingCount + 1}`,
meetingCount,
phases,
facilitatorUserId: viewerId
@@ -92,7 +93,14 @@ const startCheckIn: MutationResolvers['startCheckIn'] = async (
])
IntegrationNotifier.startMeeting(dataLoader, meetingId, teamId)
analytics.meetingStarted(viewer, meeting)
- const {error} = await createGcalEvent({gcalInput, teamId, meetingId, viewerId, dataLoader})
+ const {error} = await createGcalEvent({
+ name: meeting.name,
+ gcalInput,
+ teamId,
+ meetingId,
+ viewerId,
+ dataLoader
+ })
const data = {teamId, meetingId, hasGcalError: !!error?.message}
publish(SubscriptionChannel.TEAM, teamId, 'StartCheckInSuccess', data, subOptions)
return data
diff --git a/packages/server/graphql/public/mutations/startRetrospective.ts b/packages/server/graphql/public/mutations/startRetrospective.ts
index cc240ec1fb4..b4c7ba3ddad 100644
--- a/packages/server/graphql/public/mutations/startRetrospective.ts
+++ b/packages/server/graphql/public/mutations/startRetrospective.ts
@@ -20,7 +20,7 @@ import {startNewMeetingSeries} from './updateRecurrenceSettings'
const startRetrospective: MutationResolvers['startRetrospective'] = async (
_source,
- {teamId, recurrenceSettings, gcalInput},
+ {teamId, name, rrule, gcalInput},
{authToken, socketId: mutatorId, dataLoader}
) => {
const r = await getRethink()
@@ -36,12 +36,14 @@ const startRetrospective: MutationResolvers['startRetrospective'] = async (
if (unpaidError) return standardError(new Error(unpaidError), {userId: viewerId})
// RESOLUTION
- const viewer = await dataLoader.get('users').loadNonNull(viewerId)
-
const meetingType: MeetingTypeEnum = 'retrospective'
- const meetingSettings = (await dataLoader
- .get('meetingSettingsByType')
- .load({teamId, meetingType})) as MeetingSettingsRetrospective
+ const [viewer, meetingSettings, meetingCount] = await Promise.all([
+ dataLoader.get('users').loadNonNull(viewerId),
+ dataLoader
+ .get('meetingSettingsByType')
+ .load({teamId, meetingType}) as Promise,
+ dataLoader.get('meetingCount').load({teamId, meetingType})
+ ])
const {
id: meetingSettingsId,
@@ -52,9 +54,12 @@ const startRetrospective: MutationResolvers['startRetrospective'] = async (
videoMeetingURL
} = meetingSettings
- const name = recurrenceSettings?.name
- ? createMeetingSeriesTitle(recurrenceSettings.name, new Date(), 'UTC')
- : undefined
+ const meetingName = !name
+ ? `Retro #${meetingCount + 1}`
+ : rrule
+ ? createMeetingSeriesTitle(name, new Date(), 'UTC')
+ : name
+ const meetingSeriesName = name || meetingName
const meeting = await safeCreateRetrospective(
{
@@ -65,7 +70,7 @@ const startRetrospective: MutationResolvers['startRetrospective'] = async (
disableAnonymity,
templateId: selectedTemplateId,
videoMeetingURL: videoMeetingURL ?? undefined,
- name
+ name: meetingName
},
dataLoader
)
@@ -93,8 +98,7 @@ const startRetrospective: MutationResolvers['startRetrospective'] = async (
lastMeetingType: meetingType
}
const [meetingSeries] = await Promise.all([
- recurrenceSettings?.rrule &&
- startNewMeetingSeries(meeting, recurrenceSettings.rrule, recurrenceSettings.name),
+ rrule && startNewMeetingSeries(meeting, rrule, meetingSeriesName),
r
.table('MeetingMember')
.insert(
@@ -120,11 +124,12 @@ const startRetrospective: MutationResolvers['startRetrospective'] = async (
IntegrationNotifier.startMeeting(dataLoader, meetingId, teamId)
analytics.meetingStarted(viewer, meeting, template)
const {error, gcalSeriesId} = await createGcalEvent({
+ name: meetingSeriesName,
gcalInput,
meetingId,
teamId,
viewerId,
- rrule: recurrenceSettings?.rrule,
+ rrule,
dataLoader
})
if (meetingSeries && gcalSeriesId) {
diff --git a/packages/server/graphql/public/mutations/startTeamPrompt.ts b/packages/server/graphql/public/mutations/startTeamPrompt.ts
index 75dcd21b975..393e802e1b7 100644
--- a/packages/server/graphql/public/mutations/startTeamPrompt.ts
+++ b/packages/server/graphql/public/mutations/startTeamPrompt.ts
@@ -18,7 +18,7 @@ const MEETING_START_DELAY_MS = 3000
const startTeamPrompt: MutationResolvers['startTeamPrompt'] = async (
_source,
- {teamId, recurrenceSettings, gcalInput},
+ {teamId, name, rrule, gcalInput},
{authToken, dataLoader, socketId: mutatorId}
) => {
const r = await getRethink()
@@ -46,11 +46,8 @@ const startTeamPrompt: MutationResolvers['startTeamPrompt'] = async (
}
//TODO: use client timezone here (requires sending it from the client and passing it via gql context most likely)
- const meetingName = createMeetingSeriesTitle(
- recurrenceSettings?.name || 'Standup',
- new Date(),
- 'UTC'
- )
+ const meetingName = createMeetingSeriesTitle(name || 'Standup', new Date(), 'UTC')
+ const eventName = rrule ? name || 'Standup' : meetingName
const meeting = await safeCreateTeamPrompt(meetingName, teamId, viewerId, r, dataLoader)
await Promise.all([
@@ -64,19 +61,22 @@ const startTeamPrompt: MutationResolvers['startTeamPrompt'] = async (
])
const {id: meetingId} = meeting
- if (recurrenceSettings?.rrule) {
- const meetingSeries = await startNewMeetingSeries(
- meeting,
- recurrenceSettings.rrule,
- recurrenceSettings.name
- )
+ if (rrule) {
+ const meetingSeries = await startNewMeetingSeries(meeting, rrule, name)
// meeting was modified if a new meeting series was created
dataLoader.get('newMeetings').clear(meetingId)
analytics.recurrenceStarted(viewer, meetingSeries)
}
IntegrationNotifier.startMeeting(dataLoader, meetingId, teamId)
analytics.meetingStarted(viewer, meeting)
- const {error} = await createGcalEvent({gcalInput, meetingId, teamId, viewerId, dataLoader})
+ const {error} = await createGcalEvent({
+ name: eventName,
+ gcalInput,
+ meetingId,
+ teamId,
+ viewerId,
+ dataLoader
+ })
const data = {teamId, meetingId: meetingId, hasGcalError: !!error?.message}
publish(SubscriptionChannel.TEAM, teamId, 'StartTeamPromptSuccess', data, subOptions)
return data
diff --git a/packages/server/graphql/public/mutations/updateRecurrenceSettings.ts b/packages/server/graphql/public/mutations/updateRecurrenceSettings.ts
index d3ce01392c1..96f4f1b590d 100644
--- a/packages/server/graphql/public/mutations/updateRecurrenceSettings.ts
+++ b/packages/server/graphql/public/mutations/updateRecurrenceSettings.ts
@@ -124,7 +124,7 @@ const updateGCalRecurrenceRule = (oldRule: RRule, newRule: RRule | null | undefi
const updateRecurrenceSettings: MutationResolvers['updateRecurrenceSettings'] = async (
_source,
- {meetingId, recurrenceSettings},
+ {meetingId, name, rrule},
{authToken, dataLoader, socketId: mutatorId}
) => {
const viewerId = getUserId(authToken)
@@ -152,46 +152,39 @@ const updateRecurrenceSettings: MutationResolvers['updateRecurrenceSettings'] =
const meetingSeries = await dataLoader.get('meetingSeries').loadNonNull(meetingSeriesId)
const {gcalSeriesId, teamId, facilitatorId, recurrenceRule} = meetingSeries
- if (!recurrenceSettings.rrule) {
+ if (!rrule) {
await stopMeetingSeries(meetingSeries)
analytics.recurrenceStopped(viewer, meetingSeries)
} else {
- await updateMeetingSeries(meetingSeries, recurrenceSettings.rrule)
+ await updateMeetingSeries(meetingSeries, rrule)
analytics.recurrenceStarted(viewer, meetingSeries)
}
if (gcalSeriesId) {
- const rrule = updateGCalRecurrenceRule(
- RRule.fromString(recurrenceRule),
- recurrenceSettings.rrule
- )
+ const newRrule = updateGCalRecurrenceRule(RRule.fromString(recurrenceRule), rrule)
await updateGcalSeries({
gcalSeriesId,
- title: recurrenceSettings.name ?? undefined,
- rrule,
+ name: name ?? undefined,
+ rrule: newRrule,
teamId,
userId: facilitatorId,
dataLoader
})
}
- if (recurrenceSettings.name) {
- await updateMeetingSeriesQuery({title: recurrenceSettings.name}, meetingSeries.id)
+ if (name) {
+ await updateMeetingSeriesQuery({title: name}, meetingSeries.id)
}
dataLoader.get('meetingSeries').clear(meetingSeries.id)
} else {
- if (!recurrenceSettings.rrule) {
+ if (!rrule) {
return standardError(
new Error('When meeting is not recurring, recurrence rule has to be provided'),
{userId: viewerId}
)
}
- const newMeetingSeries = await startNewMeetingSeries(
- meeting,
- recurrenceSettings.rrule,
- recurrenceSettings.name
- )
+ const newMeetingSeries = await startNewMeetingSeries(meeting, rrule, name)
analytics.recurrenceStarted(viewer, newMeetingSeries)
}
diff --git a/packages/server/graphql/public/typeDefs/CreateGcalEventInput.graphql b/packages/server/graphql/public/typeDefs/CreateGcalEventInput.graphql
new file mode 100644
index 00000000000..634041f5edd
--- /dev/null
+++ b/packages/server/graphql/public/typeDefs/CreateGcalEventInput.graphql
@@ -0,0 +1,22 @@
+input CreateGcalEventInput {
+ """
+ The start timestamp of the event
+ """
+ startTimestamp: Int!
+ """
+ The end timestamp of the event
+ """
+ endTimestamp: Int!
+ """
+ The timezone of the event
+ """
+ timeZone: String!
+ """
+ The type of video call to added to the gcal event. If not provided, no video call will be added
+ """
+ videoType: GcalVideoTypeEnum
+ """
+ The emails that will be invited to the gcal event. If not provided, the no one will be invited
+ """
+ invitees: [Email!]
+}
diff --git a/packages/server/graphql/public/typeDefs/RecurrenceSettingsInput.graphql b/packages/server/graphql/public/typeDefs/RecurrenceSettingsInput.graphql
deleted file mode 100644
index 04a67753120..00000000000
--- a/packages/server/graphql/public/typeDefs/RecurrenceSettingsInput.graphql
+++ /dev/null
@@ -1,14 +0,0 @@
-"""
-Recurrence settings for a meeting series, used to create or update a meeting series
-"""
-input RecurrenceSettingsInput {
- """
- The recurrence rule for the meeting series in RRULE format
- """
- rrule: RRule
-
- """
- Meeting series name, by default "Standup"
- """
- name: String
-}
diff --git a/packages/server/graphql/public/typeDefs/_legacy.graphql b/packages/server/graphql/public/typeDefs/_legacy.graphql
index 4b4a247f5b1..bcf909a9706 100644
--- a/packages/server/graphql/public/typeDefs/_legacy.graphql
+++ b/packages/server/graphql/public/typeDefs/_legacy.graphql
@@ -5851,6 +5851,10 @@ type Mutation {
"""
teamId: ID!
"""
+ The name of the meeting
+ """
+ name: String
+ """
The gcal input if creating a gcal event
"""
gcalInput: CreateGcalEventInput
diff --git a/packages/server/graphql/public/typeDefs/startCheckIn.graphql b/packages/server/graphql/public/typeDefs/startCheckIn.graphql
index 35a8c0f4b69..ba6eb2e8cc9 100644
--- a/packages/server/graphql/public/typeDefs/startCheckIn.graphql
+++ b/packages/server/graphql/public/typeDefs/startCheckIn.graphql
@@ -20,6 +20,10 @@ extend type Mutation {
"""
teamId: ID!
"""
+ The name of the meeting
+ """
+ name: String
+ """
The gcal input if creating a gcal event
"""
gcalInput: CreateGcalEventInput
diff --git a/packages/server/graphql/public/typeDefs/startRetrospective.graphql b/packages/server/graphql/public/typeDefs/startRetrospective.graphql
index 91bb03261c2..8c60c60d8ef 100644
--- a/packages/server/graphql/public/typeDefs/startRetrospective.graphql
+++ b/packages/server/graphql/public/typeDefs/startRetrospective.graphql
@@ -8,9 +8,13 @@ extend type Mutation {
"""
teamId: ID!
"""
- The recurrence settings of the meeting
+ Name of the meeting or series
"""
- recurrenceSettings: RecurrenceSettingsInput
+ name: String
+ """
+ The recurrence rule for the meeting series in RRULE format
+ """
+ rrule: RRule
"""
The gcal input if creating a gcal event
"""
@@ -29,30 +33,3 @@ type StartRetrospectiveSuccess {
team: Team!
hasGcalError: Boolean
}
-
-input CreateGcalEventInput {
- """
- The title of the event
- """
- title: String!
- """
- The start timestamp of the event
- """
- startTimestamp: Int!
- """
- The end timestamp of the event
- """
- endTimestamp: Int!
- """
- The timezone of the event
- """
- timeZone: String!
- """
- The type of video call to added to the gcal event. If not provided, no video call will be added
- """
- videoType: GcalVideoTypeEnum
- """
- The emails that will be invited to the gcal event. If not provided, the no one will be invited
- """
- invitees: [Email!]
-}
diff --git a/packages/server/graphql/public/typeDefs/startTeamPrompt.graphql b/packages/server/graphql/public/typeDefs/startTeamPrompt.graphql
index 01bd98483b5..ea02edf4a2b 100644
--- a/packages/server/graphql/public/typeDefs/startTeamPrompt.graphql
+++ b/packages/server/graphql/public/typeDefs/startTeamPrompt.graphql
@@ -8,9 +8,13 @@ extend type Mutation {
"""
teamId: ID!
"""
- The recurrence settings of the meeting
+ Meeting or series name, by default "Standup"
"""
- recurrenceSettings: RecurrenceSettingsInput
+ name: String
+ """
+ The recurrence rule for the meeting series in RRULE format
+ """
+ rrule: RRule
"""
The gcal input if creating a gcal event. If not provided, no gcal event will be created
"""
@@ -37,30 +41,3 @@ type StartTeamPromptSuccess {
"""
hasGcalError: Boolean
}
-
-input CreateGcalEventInput {
- """
- The title of the event
- """
- title: String!
- """
- The start timestamp of the event
- """
- startTimestamp: Int!
- """
- The end timestamp of the event
- """
- endTimestamp: Int!
- """
- The timezone of the event
- """
- timeZone: String!
- """
- The type of video call to added to the gcal event. If not provided, no video call will be added
- """
- videoType: GcalVideoTypeEnum
- """
- The emails that will be invited to the gcal event. If not provided, the no one will be invited
- """
- invitees: [Email!]
-}
diff --git a/packages/server/graphql/public/typeDefs/updateRecurrenceSettings.graphql b/packages/server/graphql/public/typeDefs/updateRecurrenceSettings.graphql
index 1715cb3fa79..fad9895053d 100644
--- a/packages/server/graphql/public/typeDefs/updateRecurrenceSettings.graphql
+++ b/packages/server/graphql/public/typeDefs/updateRecurrenceSettings.graphql
@@ -12,9 +12,14 @@ extend type Mutation {
meetingId: ID!
"""
- Updated recurrence settings
+ New meeting series name
"""
- recurrenceSettings: RecurrenceSettingsInput!
+ name: String
+
+ """
+ The recurrence rule for the meeting series in RRULE format
+ """
+ rrule: RRule
): UpdateRecurrenceSettingsPayload!
}
diff --git a/packages/server/graphql/public/types/CreateGcalEventInput.ts b/packages/server/graphql/public/types/CreateGcalEventInput.ts
index 49172372bd2..97a4e6ad98c 100644
--- a/packages/server/graphql/public/types/CreateGcalEventInput.ts
+++ b/packages/server/graphql/public/types/CreateGcalEventInput.ts
@@ -11,10 +11,6 @@ import GraphQLEmailType from '../../types/GraphQLEmailType'
const CreateGcalEventInput = new GraphQLInputObjectType({
name: 'CreateGcalEventInput',
fields: () => ({
- title: {
- type: new GraphQLNonNull(GraphQLString),
- description: 'The title of the meeting'
- },
startTimestamp: {
type: new GraphQLNonNull(GraphQLInt),
description: 'The start dateTime of the meeting'
@@ -40,14 +36,11 @@ const CreateGcalEventInput = new GraphQLInputObjectType({
})
})
-type GcalVideoTypeEnum = 'meet' | 'zoom'
-
export type CreateGcalEventInputType = {
- title: string
startTimestamp: number
endTimestamp: number
timeZone: string
- videoType?: GcalVideoTypeEnum
+ videoType?: 'meet' | 'zoom'
invitees?: string[]
}