Skip to content

Commit

Permalink
crowdin integration
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeKarow committed Apr 30, 2024
1 parent 24cd37c commit 1a89f86
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 135 deletions.
21 changes: 17 additions & 4 deletions packages/api/router/orgEmail/mutation.create.handler.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import { addSingleKey } from '@weareinreach/crowdin/api'
import { getAuditedClient } from '@weareinreach/db'
import { type TRPCHandlerParams } from '~api/types/handler'

import { type TCreateSchema } from './mutation.create.schema'

const create = async ({ ctx, input }: TRPCHandlerParams<TCreateSchema, 'protected'>) => {
const prisma = getAuditedClient(ctx.actorId)
const newEmail = await prisma.orgEmail.create({
data: input,
select: { id: true },

const result = await prisma.$transaction(async (tx) => {
if (input.description) {
const crowdinId = await addSingleKey({
isDatabaseString: true,
key: input.description.create.tsKey.create.key,
text: input.description.create.tsKey.create.text,
})
input.description.create.tsKey.create.crowdinId = crowdinId.id
}
const newEmail = await tx.orgEmail.create({
data: input,
select: { id: true },
})
return newEmail
})
return newEmail
return result
}
export default create
38 changes: 22 additions & 16 deletions packages/api/router/orgEmail/mutation.create.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,33 @@ export const ZCreateSchema = z
.transform(({ orgId, data, title, titleId, description }) => {
const id = generateId('orgEmail')

const handleTitle = () => {
if (title) {
return {
create: {
title,
key: {
create: {
text: title,
key: slug(title),
namespace: { connect: { name: namespace.userTitle } },
},
},
},
}
}
if (titleId) {
return { connect: { id: titleId } }
}
return undefined
}

return Prisma.validator<Prisma.OrgEmailCreateInput>()({
...data,
description: description
? generateNestedFreeText({ orgId, itemId: id, text: description, type: 'emailDesc' })
: undefined,
title: title
? {
create: {
title,
key: {
create: {
text: title,
key: slug(title),
namespace: { connect: { name: namespace.userTitle } },
},
},
},
}
: titleId
? { connect: { id: titleId } }
: undefined,
title: handleTitle(),
})
})
export type TCreateSchema = z.infer<typeof ZCreateSchema>
110 changes: 58 additions & 52 deletions packages/api/router/orgEmail/mutation.update.handler.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import { generateNestedFreeText, generateNestedFreeTextUpsert, getAuditedClient } from '@weareinreach/db'
import { upsertSingleKey } from '@weareinreach/crowdin/api'
import { generateNestedFreeTextUpsert, getAuditedClient } from '@weareinreach/db'
import { type TRPCHandlerParams } from '~api/types/handler'

import { type TUpdateSchema } from './mutation.update.schema'

const select = {
id: true,
deleted: true,
description: { select: { tsKey: { select: { text: true, key: true, ns: true } } } },
descriptionId: true,
email: true,
firstName: true,
lastName: true,
locationOnly: true,
primary: true,
published: true,
serviceOnly: true,
titleId: true,
} as const
const update = async ({ ctx, input }: TRPCHandlerParams<TUpdateSchema, 'protected'>) => {
const prisma = getAuditedClient(ctx.actorId)
const { id, orgId, description, descriptionId, titleId, email, linkLocationId, ...record } = input
Expand All @@ -17,58 +32,49 @@ const update = async ({ ctx, input }: TRPCHandlerParams<TUpdateSchema, 'protecte
})
: undefined

const select = {
id: true,
deleted: true,
description: { select: { tsKey: { select: { text: true, key: true, ns: true } } } },
descriptionId: true,
email: true,
firstName: true,
lastName: true,
locationOnly: true,
primary: true,
published: true,
serviceOnly: true,
titleId: true,
} as const

const updated = email
? await prisma.orgEmail.upsert({
where: { id },
create: {
id,
email,
...record,
...(description && {
description: generateNestedFreeText({
orgId,
type: 'emailDesc',
itemId: id,
freeTextId: descriptionId,
text: description,
}),
}),
...(linkLocationId && {
locations: { createMany: { data: [{ orgLocationId: linkLocationId }], skipDuplicates: true } },
}),
},
update: {
...record,
description: updateDescriptionText,
title: titleId ? { connect: { id: titleId } } : undefined,
},
select,
})
: await prisma.orgEmail.update({
where: { id },
data: {
...record,
description: updateDescriptionText,
title: titleId ? { connect: { id: titleId } } : undefined,
},
select,
const result = await prisma.$transaction(async (tx) => {
if (updateDescriptionText) {
const crowdin = await upsertSingleKey({
isDatabaseString: true,
key: updateDescriptionText.upsert.create.tsKey.create.key,
text: updateDescriptionText.upsert.create.tsKey.create.text,
})
const { description: updatedDescription, ...rest } = updated
if (crowdin.id) {
updateDescriptionText.upsert.create.tsKey.create.crowdinId = crowdin.id
}
}
const updated = email
? await tx.orgEmail.upsert({
where: { id },
create: {
id,
email,
...record,
description: updateDescriptionText?.upsert,
...(linkLocationId && {
locations: { createMany: { data: [{ orgLocationId: linkLocationId }], skipDuplicates: true } },
}),
},
update: {
...record,
description: updateDescriptionText,
title: titleId ? { connect: { id: titleId } } : undefined,
},
select,
})
: await tx.orgEmail.update({
where: { id },
data: {
...record,
description: updateDescriptionText,
title: titleId ? { connect: { id: titleId } } : undefined,
},
select,
})
return updated
})

const { description: updatedDescription, ...rest } = result

const reformatted = {
...rest,
Expand Down
107 changes: 63 additions & 44 deletions packages/api/router/orgEmail/mutation.upsertMany.handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import compact from 'just-compact'

import { generateNestedFreeText, getAuditedClient } from '@weareinreach/db'
import { upsertSingleKey } from '@weareinreach/crowdin/api'
import { generateId, generateNestedFreeTextUpsert, getAuditedClient } from '@weareinreach/db'
import {
connectOneId,
connectOrDisconnectId,
Expand All @@ -21,53 +22,71 @@ const upsertMany = async ({ ctx, input }: TRPCHandlerParams<TUpsertManySchema, '
},
include: { services: true, locations: true },
})
const upserts = await prisma.$transaction(
data.map(
({ title, services: servicesArr, locations: locationsArr, description, id: passedId, ...record }) => {
const before = passedId ? existing.find(({ id: existingId }) => existingId === passedId) : undefined
const servicesBefore = before?.services?.map(({ serviceId }) => ({ serviceId })) ?? []
const locationsBefore = before?.locations?.map(({ orgLocationId }) => ({ orgLocationId })) ?? []
const id = passedId ?? ctx.generateId('orgEmail')

const services = servicesArr.map((serviceId) => ({ serviceId }))
const locations = locationsArr.map((orgLocationId) => ({ orgLocationId }))
const results: Array<{ id: string }> = []

return prisma.orgEmail.upsert({
where: { id },
create: {
id,
...record,
title: connectOneId(title),
services: createManyOptional(services),
locations: createManyOptional(locations),
description: description
? generateNestedFreeText({ orgId, text: description, type: 'emailDesc', itemId: id })
: undefined,
},
update: {
id,
...record,
title: connectOrDisconnectId(title),
services: diffConnectionsMtoN(services, servicesBefore, 'serviceId'),
locations: diffConnectionsMtoN(locations, locationsBefore, 'orgLocationId'),
description: description
? {
upsert: {
...generateNestedFreeText({
orgId,
text: description,
type: 'emailDesc',
itemId: id,
}),
update: { tsKey: { update: { text: description } } },
},
}
: undefined,
},
const upserts = await prisma.$transaction(async (tx) => {
for (const {
title,
services: servicesArr,
locations: locationsArr,
description,
id: passedId,
...record
} of data) {
const before = passedId ? existing.find(({ id: existingId }) => existingId === passedId) : undefined
const servicesBefore = before?.services?.map(({ serviceId }) => ({ serviceId })) ?? []
const locationsBefore = before?.locations?.map(({ orgLocationId }) => ({ orgLocationId })) ?? []
const id = passedId ?? ctx.generateId('orgEmail')

const services = servicesArr.map((serviceId) => ({ serviceId }))
const locations = locationsArr.map((orgLocationId) => ({ orgLocationId }))

const descriptionText = description
? generateNestedFreeTextUpsert({
orgId,
text: description,
type: 'emailDesc',
itemId: id,
freeTextId: generateId('freeText'),
})
: undefined

if (descriptionText) {
const crowdin = await upsertSingleKey({
isDatabaseString: true,
key: descriptionText.upsert.create.tsKey.create.key,
text: descriptionText.upsert.create.tsKey.create.text,
})
if (crowdin.id) {
descriptionText.upsert.create.tsKey.create.crowdinId = crowdin.id
}
}
)
)

const txnResult = await tx.orgEmail.upsert({
where: { id },
create: {
id,
...record,
title: connectOneId(title),
services: createManyOptional(services),
locations: createManyOptional(locations),
description: descriptionText?.upsert,
},
update: {
id,
...record,
title: connectOrDisconnectId(title),
services: diffConnectionsMtoN(services, servicesBefore, 'serviceId'),
locations: diffConnectionsMtoN(locations, locationsBefore, 'orgLocationId'),
description: descriptionText,
},
select: { id: true },
})
results.push(txnResult)
}
return results
})
return upserts
}
export default upsertMany
36 changes: 32 additions & 4 deletions packages/api/router/orgPhone/mutation.create.handler.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,42 @@
import invariant from 'tiny-invariant'

import { addSingleKey } from '@weareinreach/crowdin/api'
import { getAuditedClient } from '@weareinreach/db'
import { type TRPCHandlerParams } from '~api/types/handler'

import { type TCreateSchema } from './mutation.create.schema'

const create = async ({ ctx, input }: TRPCHandlerParams<TCreateSchema, 'protected'>) => {
const prisma = getAuditedClient(ctx.actorId)
const newPhone = await prisma.orgPhone.create({
data: input,
select: { id: true },

const result = await prisma.$transaction(async (tx) => {
if (input.description) {
const crowdinDesc = await addSingleKey({
isDatabaseString: true,
key: input.description.create.tsKey.create.key,
text: input.description.create.tsKey.create.text,
})
input.description.create.tsKey.create.crowdinId = crowdinDesc.id
}
if (input.phoneType?.create) {
invariant(
input.phoneType.create.key?.create && input.phoneType.create.key.create.namespace?.connect?.name
)
const crowdinPhoneType = await addSingleKey({
isDatabaseString: false,
key: input.phoneType.create.key.create.key,
text: input.phoneType.create.key.create.text,
ns: input.phoneType.create.key.create.namespace.connect.name as 'phone-type',
})
input.phoneType.create.key.create.crowdinId = crowdinPhoneType.id
}

const newPhone = await tx.orgPhone.create({
data: input,
select: { id: true },
})
return newPhone
})
return newPhone
return result
}
export default create
Loading

0 comments on commit 1a89f86

Please sign in to comment.