Skip to content

Commit

Permalink
chore(rethinkdb): TemplateDimension: One-shot (#10033)
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Krick <matt.krick@gmail.com>
  • Loading branch information
mattkrick authored Jul 25, 2024
1 parent f8b029d commit 77e163a
Show file tree
Hide file tree
Showing 37 changed files with 359 additions and 415 deletions.
2 changes: 1 addition & 1 deletion codegen.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
"TeamPromptMeeting": "../../database/types/MeetingTeamPrompt#default as MeetingTeamPromptDB",
"TeamPromptMeetingMember": "../../database/types/TeamPromptMeetingMember#default as TeamPromptMeetingMemberDB",
"TeamPromptResponse": "../../postgres/queries/getTeamPromptResponsesByIds#TeamPromptResponse",
"TemplateDimension": "../../database/types/TemplateDimension#default",
"TemplateDimension": "../../postgres/types/index#TemplateDimension as TemplateDimensionDB",
"TimelineEventTeamPromptComplete": "./types/TimelineEventTeamPromptComplete#TimelineEventTeamPromptCompleteSource",
"ToggleFavoriteTemplateSuccess": "./types/ToggleFavoriteTemplateSuccess#ToggleFavoriteTemplateSuccessSource",
"ToggleSummaryEmailSuccess": "./types/ToggleSummaryEmailSuccess#ToggleSummaryEmailSuccessSource",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import LinkButton from '../../../components/LinkButton'
import useAtmosphere from '../../../hooks/useAtmosphere'
import useMutationProps from '../../../hooks/useMutationProps'
import AddPokerTemplateDimensionMutation from '../../../mutations/AddPokerTemplateDimensionMutation'
import dndNoise from '../../../utils/dndNoise'
import {positionAfter} from '../../../shared/sortOrder'

const AddDimensionLink = styled(LinkButton)({
alignItems: 'center',
Expand Down Expand Up @@ -49,8 +49,8 @@ const AddPokerTemplateDimension = (props: Props) => {
const addDimension = () => {
if (submitting) return
submitMutation()
const sortOrders = dimensions.map(({sortOrder}) => sortOrder)
const sortOrder = Math.max(0, ...sortOrders) + 1 + dndNoise()
const lastSortOrder = dimensions.at(-1)?.sortOrder ?? ''
const sortOrder = positionAfter(lastSortOrder)
const dimensionCount = dimensions.length
AddPokerTemplateDimensionMutation(
atmosphere,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {useFragment} from 'react-relay'
import {TemplateDimensionList_dimensions$key} from '../../../__generated__/TemplateDimensionList_dimensions.graphql'
import useAtmosphere from '../../../hooks/useAtmosphere'
import MovePokerTemplateDimensionMutation from '../../../mutations/MovePokerTemplateDimensionMutation'
import {getSortOrder} from '../../../shared/sortOrder'
import {TEMPLATE_DIMENSION} from '../../../utils/constants'
import dndNoise from '../../../utils/dndNoise'
import TemplateDimensionItem from './TemplateDimensionItem'

interface Props {
Expand Down Expand Up @@ -52,20 +52,7 @@ const TemplateDimensionList = (props: Props) => {
) {
return
}

let sortOrder
if (destination.index === 0) {
sortOrder = destinationDimension.sortOrder - 1 + dndNoise()
} else if (destination.index === dimensions.length - 1) {
sortOrder = destinationDimension.sortOrder + 1 + dndNoise()
} else {
const offset = source.index > destination.index ? -1 : 1
sortOrder =
((dimensions[destination.index + offset]?.sortOrder ?? 0) +
destinationDimension.sortOrder) /
2 +
dndNoise()
}
const sortOrder = getSortOrder(dimensions, source.index, destination.index)

const {id: dimensionId} = sourceDimension
const variables = {dimensionId, sortOrder}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import handleAddPokerTemplateDimension from './handlers/handleAddPokerTemplateDi

interface Handlers extends BaseLocalHandlers {
dimensionCount: number
sortOrder: number
sortOrder: string
}

graphql`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ graphql`
`

const mutation = graphql`
mutation MovePokerTemplateDimensionMutation($dimensionId: ID!, $sortOrder: Float!) {
mutation MovePokerTemplateDimensionMutation($dimensionId: ID!, $sortOrder: String!) {
movePokerTemplateDimension(dimensionId: $dimensionId, sortOrder: $sortOrder) {
error {
message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// WARNING: the lexicographical sort assumes a C collation (i.e. compare strings via ASCII code)
// CloudSQL assumes a utf-8 (byte-code) comparision by default, so make sure the column is collated correctly!

import {MaybeReadonly} from '../types/generics'

const START_CHAR_CODE = 32
const END_CHAR_CODE = 126

Expand Down Expand Up @@ -57,7 +59,11 @@ function positionBetween(firstPos: string, secondPos: string) {
return position + String.fromCharCode(avg(START_CHAR_CODE, END_CHAR_CODE))
}

export function getSortOrder(arr: {sortOrder: string}[], fromIdx: number, toIdx: number) {
export function getSortOrder(
arr: MaybeReadonly<{sortOrder: string}[]>,
fromIdx: number,
toIdx: number
) {
const secondPosIdx = fromIdx < toIdx ? toIdx + 1 : toIdx
const firstPos = arr[secondPosIdx - 1]?.sortOrder
const secondPos = arr[secondPosIdx]?.sortOrder
Expand Down
5 changes: 0 additions & 5 deletions packages/server/database/rethinkDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import SuggestedActionCreateNewTeam from './types/SuggestedActionCreateNewTeam'
import SuggestedActionInviteYourTeam from './types/SuggestedActionInviteYourTeam'
import SuggestedActionTryTheDemo from './types/SuggestedActionTryTheDemo'
import Task from './types/Task'
import TemplateDimension from './types/TemplateDimension'

export type RethinkSchema = {
AgendaItem: {
Expand Down Expand Up @@ -149,10 +148,6 @@ export type RethinkSchema = {
type: TeamInvitation
index: 'email' | 'teamId' | 'token'
}
TemplateDimension: {
type: TemplateDimension
index: 'teamId' | 'templateId' | 'scaleId'
}
}

export type DBType = {
Expand Down
36 changes: 0 additions & 36 deletions packages/server/database/types/TemplateDimension.ts

This file was deleted.

21 changes: 20 additions & 1 deletion packages/server/dataloader/foreignKeyLoaderMakers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import getKysely from '../postgres/getKysely'
import {selectTemplateScale} from '../postgres/select'
import {selectTemplateDimension, selectTemplateScale} from '../postgres/select'
import {foreignKeyLoaderMaker} from './foreignKeyLoaderMaker'
import {selectOrganizations, selectRetroReflections, selectTeams} from './primaryKeyLoaderMakers'

Expand Down Expand Up @@ -132,3 +132,22 @@ export const scalesByTeamId = foreignKeyLoaderMaker('templateScales', 'teamId',
.orderBy(['isStarter', 'name'])
.execute()
})

export const templateDimensionsByTemplateId = foreignKeyLoaderMaker(
'templateDimensions',
'templateId',
async (templateIds) => {
return selectTemplateDimension()
.where('templateId', 'in', templateIds)
.orderBy('sortOrder')
.execute()
}
)

export const templateDimensionsByScaleId = foreignKeyLoaderMaker(
'templateDimensions',
'scaleId',
async (scaleIds) => {
return selectTemplateDimension().where('scaleId', 'in', scaleIds).orderBy('sortOrder').execute()
}
)
6 changes: 5 additions & 1 deletion packages/server/dataloader/primaryKeyLoaderMakers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {getTeamPromptResponsesByIds} from '../postgres/queries/getTeamPromptResp
import getTemplateRefsByIds from '../postgres/queries/getTemplateRefsByIds'
import getTemplateScaleRefsByIds from '../postgres/queries/getTemplateScaleRefsByIds'
import {getUsersByIds} from '../postgres/queries/getUsersByIds'
import {selectTemplateScale} from '../postgres/select'
import {selectTemplateDimension, selectTemplateScale} from '../postgres/select'
import {primaryKeyLoaderMaker} from './primaryKeyLoaderMaker'

export const users = primaryKeyLoaderMaker(getUsersByIds)
Expand Down Expand Up @@ -155,3 +155,7 @@ export const teamMembers = primaryKeyLoaderMaker((ids: readonly string[]) => {
export const templateScales = primaryKeyLoaderMaker((ids: readonly string[]) => {
return selectTemplateScale().where('TemplateScale.id', 'in', ids).execute()
})

export const templateDimensions = primaryKeyLoaderMaker((ids: readonly string[]) => {
return selectTemplateDimension().where('id', 'in', ids).execute()
})
17 changes: 0 additions & 17 deletions packages/server/dataloader/rethinkForeignKeyLoaderMakers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,23 +116,6 @@ export const meetingMembersByUserId = new RethinkForeignKeyLoaderMaker(
}
)

export const templateDimensionsByTemplateId = new RethinkForeignKeyLoaderMaker(
'templateDimensions',
'templateId',
async (templateIds) => {
const r = await getRethink()
return (
r
.table('TemplateDimension')
.getAll(r.args(templateIds), {index: 'templateId'})
// NOTE: isActive must be false so we can see meetings in the past that use a now-inactive template
// .filter({isActive: true})
.orderBy('sortOrder')
.run()
)
}
)

export const slackAuthByUserId = new RethinkForeignKeyLoaderMaker(
'slackAuths',
'userId',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,3 @@ export const slackNotifications = new RethinkPrimaryKeyLoaderMaker('SlackNotific
export const suggestedActions = new RethinkPrimaryKeyLoaderMaker('SuggestedAction')
export const tasks = new RethinkPrimaryKeyLoaderMaker('Task')
export const teamInvitations = new RethinkPrimaryKeyLoaderMaker('TeamInvitation')
export const templateDimensions = new RethinkPrimaryKeyLoaderMaker('TemplateDimension')
60 changes: 23 additions & 37 deletions packages/server/graphql/mutations/addPokerTemplateDimension.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {GraphQLID, GraphQLNonNull} from 'graphql'
import {SprintPokerDefaults, SubscriptionChannel, Threshold} from 'parabol-client/types/constEnums'
import dndNoise from 'parabol-client/utils/dndNoise'
import getRethink from '../../database/rethinkDriver'
import {RDatum} from '../../database/stricterR'
import TemplateDimension from '../../database/types/TemplateDimension'
import {positionAfter} from '../../../client/shared/sortOrder'
import generateUID from '../../generateUID'
import getKysely from '../../postgres/getKysely'
import {getUserId, isTeamMember} from '../../utils/authorization'
import publish from '../../utils/publish'
Expand All @@ -24,11 +22,13 @@ const addPokerTemplateDimension = {
{templateId}: {templateId: string},
{authToken, dataLoader, socketId: mutatorId}: GQLContext
) {
const r = await getRethink()
const pg = getKysely()
const operationId = dataLoader.share()
const subOptions = {operationId, mutatorId}
const template = await dataLoader.get('meetingTemplates').load(templateId)
const [template, activeDimensions] = await Promise.all([
dataLoader.get('meetingTemplates').load(templateId),
dataLoader.get('templateDimensionsByTemplateId').load(templateId)
])
const viewerId = getUserId(authToken)

// AUTH
Expand All @@ -41,45 +41,31 @@ const addPokerTemplateDimension = {

// VALIDATION
const {teamId} = template
const activeDimensions = await r
.table('TemplateDimension')
.getAll(teamId, {index: 'teamId'})
.filter({templateId})
.filter((row: RDatum) => row('removedAt').default(null).eq(null))
.run()
if (activeDimensions.length >= Threshold.MAX_POKER_TEMPLATE_DIMENSIONS) {
return standardError(new Error('Too many dimensions'), {userId: viewerId})
}

// RESOLUTION
const sortOrder =
Math.max(0, ...activeDimensions.map((dimension) => dimension.sortOrder)) + 1 + dndNoise()
const lastSortOrder = activeDimensions.at(-1)?.sortOrder ?? ''
const sortOrder = positionAfter(lastSortOrder)
const rawAvailableScales = await dataLoader.get('scalesByTeamId').load(teamId)
const availableScales = rawAvailableScales.sort((a, b) => (a.updatedAt > b.updatedAt ? -1 : 1))
const defaultScaleId =
availableScales.length > 0
? availableScales.map((teamScale) => teamScale.id)[0]
: SprintPokerDefaults.DEFAULT_SCALE_ID

const newDimension = new TemplateDimension({
scaleId: defaultScaleId as string,
description: '',
sortOrder: sortOrder,
name: `*New Dimension #${activeDimensions.length + 1}`,
teamId,
templateId
})

await Promise.all([
r.table('TemplateDimension').insert(newDimension).run(),
pg
.updateTable('MeetingTemplate')
.set({updatedAt: new Date()})
.where('id', '=', templateId)
.execute()
])
const defaultScaleId = availableScales[0]?.id ?? SprintPokerDefaults.DEFAULT_SCALE_ID

const dimensionId = newDimension.id
const res = await pg
.insertInto('TemplateDimension')
.values({
id: generateUID(),
scaleId: defaultScaleId as string,
sortOrder,
name: `*New Dimension #${activeDimensions.length + 1}`,
teamId,
templateId
})
.returning('id')
.executeTakeFirstOrThrow()
dataLoader.clearAll('templateDimensions')
const dimensionId = res.id
const data = {dimensionId}
publish(SubscriptionChannel.TEAM, teamId, 'AddPokerTemplateDimensionPayload', data, subOptions)
return data
Expand Down
2 changes: 1 addition & 1 deletion packages/server/graphql/mutations/addPokerTemplateScale.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {GraphQLID, GraphQLNonNull} from 'graphql'
import {PokerCards, SubscriptionChannel, Threshold} from 'parabol-client/types/constEnums'
import {positionAfter} from '../../../client/shared/sortOrder'
import {PALETTE} from '../../../client/styles/paletteV3'
import generateUID from '../../generateUID'
import getKysely from '../../postgres/getKysely'
import {analytics} from '../../utils/analytics/analytics'
import {getUserId, isTeamMember} from '../../utils/authorization'
import publish from '../../utils/publish'
import {positionAfter} from '../../utils/sortOrder'
import standardError from '../../utils/standardError'
import {GQLContext} from '../graphql'
import AddPokerTemplateScalePayload from '../types/AddPokerTemplateScalePayload'
Expand Down
18 changes: 1 addition & 17 deletions packages/server/graphql/mutations/addPokerTemplateScaleValue.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import {GraphQLID, GraphQLNonNull} from 'graphql'
import {SubscriptionChannel} from 'parabol-client/types/constEnums'
import getRethink from '../../database/rethinkDriver'
import {getSortOrder} from '../../../client/shared/sortOrder'
import getKysely from '../../postgres/getKysely'
import {getUserId, isTeamMember} from '../../utils/authorization'
import publish from '../../utils/publish'
import {getSortOrder} from '../../utils/sortOrder'
import standardError from '../../utils/standardError'
import {GQLContext} from '../graphql'
import AddPokerTemplateScaleValuePayload from '../types/AddPokerTemplateScaleValuePayload'
Expand All @@ -27,9 +26,7 @@ const addPokerTemplateScaleValue = {
{scaleId, scaleValue}: {scaleId: string; scaleValue: AddTemplateScaleInputType},
{authToken, dataLoader, socketId: mutatorId}: GQLContext
) {
const r = await getRethink()
const pg = getKysely()
const now = new Date()
const operationId = dataLoader.share()
const subOptions = {operationId, mutatorId}
const viewerId = getUserId(authToken)
Expand Down Expand Up @@ -71,19 +68,6 @@ const addPokerTemplateScaleValue = {
return {error: {message: 'Could not add scale value'}}
}
dataLoader.clearAll('templateScales')
// mark all templates using this scale as updated
const updatedDimensions = await r
.table('TemplateDimension')
.getAll(scaleId, {index: 'scaleId'})
.run()
const updatedTemplateIds = updatedDimensions.map(({templateId}) => templateId)
if (updatedTemplateIds.length) {
await pg
.updateTable('MeetingTemplate')
.set({updatedAt: now})
.where('id', 'in', updatedTemplateIds)
.execute()
}
const data = {scaleId}
publish(
SubscriptionChannel.TEAM,
Expand Down
Loading

0 comments on commit 77e163a

Please sign in to comment.