Release 202505312236
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Service" ADD COLUMN "previousSlugs" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "Service_previousSlugs_idx" ON "Service"("previousSlugs");
|
||||||
@@ -336,6 +336,7 @@ model Service {
|
|||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
name String
|
name String
|
||||||
slug String @unique
|
slug String @unique
|
||||||
|
previousSlugs String[] @default([])
|
||||||
description String
|
description String
|
||||||
categories Category[] @relation("ServiceToCategory")
|
categories Category[] @relation("ServiceToCategory")
|
||||||
kycLevel Int @default(4)
|
kycLevel Int @default(4)
|
||||||
@@ -396,6 +397,7 @@ model Service {
|
|||||||
@@index([createdAt])
|
@@index([createdAt])
|
||||||
@@index([updatedAt])
|
@@index([updatedAt])
|
||||||
@@index([slug])
|
@@index([slug])
|
||||||
|
@@index([previousSlugs])
|
||||||
}
|
}
|
||||||
|
|
||||||
model ServiceContactMethod {
|
model ServiceContactMethod {
|
||||||
|
|||||||
@@ -612,6 +612,7 @@ const generateFakeService = (users: User[]) => {
|
|||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
slug,
|
slug,
|
||||||
|
previousSlugs: faker.helpers.maybe(() => [`${slug}-old`], { probability: 0.5 }),
|
||||||
description: faker.helpers.arrayElement(serviceDescriptions),
|
description: faker.helpers.arrayElement(serviceDescriptions),
|
||||||
kycLevel: faker.helpers.arrayElement(kycLevels.map((level) => level.value)),
|
kycLevel: faker.helpers.arrayElement(kycLevels.map((level) => level.value)),
|
||||||
overallScore: 0,
|
overallScore: 0,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Currency, ServiceVisibility, VerificationStatus } from '@prisma/client'
|
import { Currency, ServiceVisibility, VerificationStatus } from '@prisma/client'
|
||||||
import { z } from 'astro/zod'
|
import { z } from 'astro/zod'
|
||||||
import { ActionError } from 'astro:actions'
|
import { ActionError } from 'astro:actions'
|
||||||
|
import { uniq } from 'lodash-es'
|
||||||
import slugify from 'slugify'
|
import slugify from 'slugify'
|
||||||
|
|
||||||
import { defineProtectedAction } from '../../lib/defineProtectedAction'
|
import { defineProtectedAction } from '../../lib/defineProtectedAction'
|
||||||
@@ -164,11 +165,22 @@ export const adminServiceActions = {
|
|||||||
|
|
||||||
const existingService = await prisma.service.findUnique({
|
const existingService = await prisma.service.findUnique({
|
||||||
where: { id: input.id },
|
where: { id: input.id },
|
||||||
include: {
|
select: {
|
||||||
categories: true,
|
slug: true,
|
||||||
|
previousSlugs: true,
|
||||||
|
categories: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
attributes: {
|
attributes: {
|
||||||
include: {
|
select: {
|
||||||
attribute: true,
|
attributeId: true,
|
||||||
|
attribute: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -213,6 +225,14 @@ export const adminServiceActions = {
|
|||||||
serviceVisibility: input.serviceVisibility,
|
serviceVisibility: input.serviceVisibility,
|
||||||
slug: input.slug,
|
slug: input.slug,
|
||||||
overallScore: input.overallScore,
|
overallScore: input.overallScore,
|
||||||
|
previousSlugs:
|
||||||
|
existingService.slug !== input.slug
|
||||||
|
? {
|
||||||
|
set: uniq([...existingService.previousSlugs, existingService.slug]).filter(
|
||||||
|
(slug) => slug !== input.slug
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
|
||||||
imageUrl,
|
imageUrl,
|
||||||
categories: {
|
categories: {
|
||||||
|
|||||||
@@ -44,7 +44,30 @@ export const apiServiceActions = {
|
|||||||
.flatMap((url) => [url, url.endsWith('/') ? url.slice(0, -1) : `${url}/`])
|
.flatMap((url) => [url, url.endsWith('/') ? url.slice(0, -1) : `${url}/`])
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
const service = await prisma.service.findFirst({
|
const select = {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
slug: true,
|
||||||
|
description: true,
|
||||||
|
kycLevel: true,
|
||||||
|
verificationStatus: true,
|
||||||
|
categories: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
slug: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
serviceUrls: true,
|
||||||
|
onionUrls: true,
|
||||||
|
i2pUrls: true,
|
||||||
|
tosUrls: true,
|
||||||
|
referral: true,
|
||||||
|
listedAt: true,
|
||||||
|
verifiedAt: true,
|
||||||
|
serviceVisibility: true,
|
||||||
|
} as const satisfies Prisma.ServiceSelect
|
||||||
|
|
||||||
|
let service = await prisma.service.findFirst({
|
||||||
where: {
|
where: {
|
||||||
listedAt: { lte: new Date() },
|
listedAt: { lte: new Date() },
|
||||||
serviceVisibility: { in: ['PUBLIC', 'ARCHIVED', 'UNLISTED'] },
|
serviceVisibility: { in: ['PUBLIC', 'ARCHIVED', 'UNLISTED'] },
|
||||||
@@ -61,30 +84,21 @@ export const apiServiceActions = {
|
|||||||
: []),
|
: []),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
select: {
|
select,
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
slug: true,
|
|
||||||
description: true,
|
|
||||||
kycLevel: true,
|
|
||||||
verificationStatus: true,
|
|
||||||
categories: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
slug: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
serviceUrls: true,
|
|
||||||
onionUrls: true,
|
|
||||||
i2pUrls: true,
|
|
||||||
tosUrls: true,
|
|
||||||
referral: true,
|
|
||||||
listedAt: true,
|
|
||||||
verifiedAt: true,
|
|
||||||
serviceVisibility: true,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!service && input.slug) {
|
||||||
|
service = await prisma.service.findFirst({
|
||||||
|
where: {
|
||||||
|
listedAt: { lte: new Date() },
|
||||||
|
serviceVisibility: { in: ['PUBLIC', 'ARCHIVED', 'UNLISTED'] },
|
||||||
|
|
||||||
|
previousSlugs: { has: input.slug },
|
||||||
|
},
|
||||||
|
select,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!service ||
|
!service ||
|
||||||
(service.serviceVisibility !== 'PUBLIC' &&
|
(service.serviceVisibility !== 'PUBLIC' &&
|
||||||
|
|||||||
@@ -183,7 +183,21 @@ const [service, categories, attributes] = await Astro.locals.banners.tryMany([
|
|||||||
],
|
],
|
||||||
])
|
])
|
||||||
|
|
||||||
if (!service) return Astro.rewrite('/404')
|
if (!service) {
|
||||||
|
try {
|
||||||
|
const serviceWithOldSlug = await prisma.service.findFirst({
|
||||||
|
where: { previousSlugs: { has: slug } },
|
||||||
|
select: { slug: true },
|
||||||
|
})
|
||||||
|
if (serviceWithOldSlug) {
|
||||||
|
return Astro.redirect(`/admin/services/${serviceWithOldSlug.slug}/edit`, 301)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Astro.rewrite('/404')
|
||||||
|
}
|
||||||
|
|
||||||
const apiCalls = await Astro.locals.banners.try(
|
const apiCalls = await Astro.locals.banners.try(
|
||||||
'Error fetching api calls',
|
'Error fetching api calls',
|
||||||
@@ -264,7 +278,9 @@ const apiCalls = await Astro.locals.banners.try(
|
|||||||
|
|
||||||
<InputText
|
<InputText
|
||||||
label="Slug"
|
label="Slug"
|
||||||
description="Auto-generated if empty"
|
description={`Auto-generated if empty. ${
|
||||||
|
service.previousSlugs.length > 0 ? `Old slugs: ${service.previousSlugs.join(', ')}` : ''
|
||||||
|
}`}
|
||||||
name="slug"
|
name="slug"
|
||||||
inputProps={{
|
inputProps={{
|
||||||
value: service.slug,
|
value: service.slug,
|
||||||
|
|||||||
@@ -67,7 +67,11 @@ const [service, dbNotificationPreferences] = await Astro.locals.banners.tryMany(
|
|||||||
'Error fetching service',
|
'Error fetching service',
|
||||||
async () =>
|
async () =>
|
||||||
prisma.service.findUnique({
|
prisma.service.findUnique({
|
||||||
where: { slug },
|
where: {
|
||||||
|
slug,
|
||||||
|
serviceVisibility: { in: ['PUBLIC', 'UNLISTED', 'ARCHIVED'] },
|
||||||
|
listedAt: { lte: new Date() },
|
||||||
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
slug: true,
|
slug: true,
|
||||||
@@ -219,6 +223,34 @@ const [service, dbNotificationPreferences] = await Astro.locals.banners.tryMany(
|
|||||||
],
|
],
|
||||||
])
|
])
|
||||||
|
|
||||||
|
if (!service) {
|
||||||
|
try {
|
||||||
|
const serviceWithOldSlug = await prisma.service.findFirst({
|
||||||
|
where: {
|
||||||
|
previousSlugs: { has: slug },
|
||||||
|
serviceVisibility: { in: ['PUBLIC', 'UNLISTED', 'ARCHIVED'] },
|
||||||
|
listedAt: { lte: new Date() },
|
||||||
|
},
|
||||||
|
select: { slug: true },
|
||||||
|
})
|
||||||
|
if (serviceWithOldSlug) {
|
||||||
|
return Astro.redirect(`/service/${serviceWithOldSlug.slug}`, 301)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Astro.rewrite('/404')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
service.serviceVisibility !== 'PUBLIC' &&
|
||||||
|
service.serviceVisibility !== 'UNLISTED' &&
|
||||||
|
service.serviceVisibility !== 'ARCHIVED'
|
||||||
|
) {
|
||||||
|
return Astro.rewrite('/404')
|
||||||
|
}
|
||||||
|
|
||||||
const makeWatchingDetails = (
|
const makeWatchingDetails = (
|
||||||
dbNotificationPreferences: Prisma.NotificationPreferencesGetPayload<{
|
dbNotificationPreferences: Prisma.NotificationPreferencesGetPayload<{
|
||||||
select: {
|
select: {
|
||||||
@@ -254,17 +286,7 @@ const makeWatchingDetails = (
|
|||||||
} as const
|
} as const
|
||||||
}
|
}
|
||||||
|
|
||||||
const watchingDetails = makeWatchingDetails(dbNotificationPreferences, service?.id)
|
const watchingDetails = makeWatchingDetails(dbNotificationPreferences, service.id)
|
||||||
|
|
||||||
if (!service) return Astro.rewrite('/404')
|
|
||||||
|
|
||||||
if (
|
|
||||||
service.serviceVisibility !== 'PUBLIC' &&
|
|
||||||
service.serviceVisibility !== 'UNLISTED' &&
|
|
||||||
service.serviceVisibility !== 'ARCHIVED'
|
|
||||||
) {
|
|
||||||
return Astro.rewrite('/404')
|
|
||||||
}
|
|
||||||
|
|
||||||
const statusIcon = {
|
const statusIcon = {
|
||||||
...verificationStatusesByValue,
|
...verificationStatusesByValue,
|
||||||
|
|||||||
Reference in New Issue
Block a user