Release 202507061803
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Service" ADD COLUMN "strictCommentingEnabled" BOOLEAN NOT NULL DEFAULT false;
|
||||||
@@ -406,6 +406,8 @@ model Service {
|
|||||||
Notification Notification[]
|
Notification Notification[]
|
||||||
affiliatedUsers ServiceUser[] @relation("ServiceUsers")
|
affiliatedUsers ServiceUser[] @relation("ServiceUsers")
|
||||||
|
|
||||||
|
strictCommentingEnabled Boolean @default(false)
|
||||||
|
|
||||||
@@index([listedAt])
|
@@index([listedAt])
|
||||||
@@index([approvedAt])
|
@@index([approvedAt])
|
||||||
@@index([verifiedAt])
|
@@index([verifiedAt])
|
||||||
|
|||||||
@@ -720,6 +720,7 @@ const generateFakeService = (users: User[]) => {
|
|||||||
}),
|
}),
|
||||||
{ probability: 0.33 }
|
{ probability: 0.33 }
|
||||||
),
|
),
|
||||||
|
strictCommentingEnabled: faker.datatype.boolean(0.33333),
|
||||||
} as const satisfies Prisma.ServiceCreateInput
|
} as const satisfies Prisma.ServiceCreateInput
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ const serviceSchemaBase = z.object({
|
|||||||
overallScore: zodCohercedNumber(z.number().int().min(0).max(10)).optional(),
|
overallScore: zodCohercedNumber(z.number().int().min(0).max(10)).optional(),
|
||||||
serviceVisibility: z.nativeEnum(ServiceVisibility),
|
serviceVisibility: z.nativeEnum(ServiceVisibility),
|
||||||
internalNote: z.string().optional(),
|
internalNote: z.string().optional(),
|
||||||
|
strictCommentingEnabled: z.boolean().optional().default(false),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Define schema for the create action input
|
// Define schema for the create action input
|
||||||
@@ -127,6 +128,7 @@ export const adminServiceActions = {
|
|||||||
verificationSummary: input.verificationSummary,
|
verificationSummary: input.verificationSummary,
|
||||||
verificationProofMd: input.verificationProofMd,
|
verificationProofMd: input.verificationProofMd,
|
||||||
acceptedCurrencies: input.acceptedCurrencies,
|
acceptedCurrencies: input.acceptedCurrencies,
|
||||||
|
strictCommentingEnabled: input.strictCommentingEnabled,
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
||||||
referral: input.referral || null,
|
referral: input.referral || null,
|
||||||
serviceVisibility: input.serviceVisibility,
|
serviceVisibility: input.serviceVisibility,
|
||||||
@@ -247,6 +249,7 @@ export const adminServiceActions = {
|
|||||||
verificationSummary: input.verificationSummary,
|
verificationSummary: input.verificationSummary,
|
||||||
verificationProofMd: input.verificationProofMd,
|
verificationProofMd: input.verificationProofMd,
|
||||||
acceptedCurrencies: input.acceptedCurrencies,
|
acceptedCurrencies: input.acceptedCurrencies,
|
||||||
|
strictCommentingEnabled: input.strictCommentingEnabled,
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
||||||
referral: input.referral || null,
|
referral: input.referral || null,
|
||||||
serviceVisibility: input.serviceVisibility,
|
serviceVisibility: input.serviceVisibility,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Props = HTMLAttributes<'div'> & {
|
|||||||
highlightedCommentId: number | null
|
highlightedCommentId: number | null
|
||||||
serviceSlug: string
|
serviceSlug: string
|
||||||
itemReviewedId: string
|
itemReviewedId: string
|
||||||
|
strictCommentingEnabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -42,6 +43,7 @@ const {
|
|||||||
highlightedCommentId = null,
|
highlightedCommentId = null,
|
||||||
serviceSlug,
|
serviceSlug,
|
||||||
itemReviewedId,
|
itemReviewedId,
|
||||||
|
strictCommentingEnabled,
|
||||||
class: className,
|
class: className,
|
||||||
...htmlProps
|
...htmlProps
|
||||||
} = Astro.props
|
} = Astro.props
|
||||||
@@ -492,6 +494,7 @@ const commentUrl = makeCommentUrl({ serviceSlug, commentId: comment.id, origin:
|
|||||||
serviceId={comment.serviceId}
|
serviceId={comment.serviceId}
|
||||||
parentId={comment.id}
|
parentId={comment.id}
|
||||||
commentId={comment.id}
|
commentId={comment.id}
|
||||||
|
strictCommentingEnabled={strictCommentingEnabled}
|
||||||
class="mt-2 hidden peer-checked/collapse:hidden peer-checked/reply:block"
|
class="mt-2 hidden peer-checked/collapse:hidden peer-checked/reply:block"
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ type Props = Omit<HTMLAttributes<'form'>, 'action' | 'enctype' | 'method'> & {
|
|||||||
serviceId: number
|
serviceId: number
|
||||||
parentId?: number
|
parentId?: number
|
||||||
commentId?: number
|
commentId?: number
|
||||||
|
strictCommentingEnabled?: boolean
|
||||||
activeRatingComment?: Prisma.CommentGetPayload<{
|
activeRatingComment?: Prisma.CommentGetPayload<{
|
||||||
select: {
|
select: {
|
||||||
id: true
|
id: true
|
||||||
@@ -28,7 +29,15 @@ type Props = Omit<HTMLAttributes<'form'>, 'action' | 'enctype' | 'method'> & {
|
|||||||
}> | null
|
}> | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const { serviceId, parentId, commentId, activeRatingComment, class: className, ...htmlProps } = Astro.props
|
const {
|
||||||
|
serviceId,
|
||||||
|
parentId,
|
||||||
|
commentId,
|
||||||
|
activeRatingComment,
|
||||||
|
strictCommentingEnabled,
|
||||||
|
class: className,
|
||||||
|
...htmlProps
|
||||||
|
} = Astro.props
|
||||||
|
|
||||||
const MIN_COMMENT_LENGTH = parentId ? 10 : 30
|
const MIN_COMMENT_LENGTH = parentId ? 10 : 30
|
||||||
|
|
||||||
@@ -117,6 +126,7 @@ const userCommentsDisabled = user ? user.karmaUnlocks.commentsDisabled : false
|
|||||||
maxlength: 100,
|
maxlength: 100,
|
||||||
placeholder: 'Order ID / URL / Proof',
|
placeholder: 'Order ID / URL / Proof',
|
||||||
class: 'bg-night-800',
|
class: 'bg-night-800',
|
||||||
|
required: strictCommentingEnabled,
|
||||||
}}
|
}}
|
||||||
descriptionLabel="Only visible to admins, to verify your comment"
|
descriptionLabel="Only visible to admins, to verify your comment"
|
||||||
class="grow"
|
class="grow"
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ type Props = {
|
|||||||
name: true
|
name: true
|
||||||
description: true
|
description: true
|
||||||
createdAt: true
|
createdAt: true
|
||||||
|
strictCommentingEnabled: true
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
@@ -173,7 +174,12 @@ function makeReplySchema(comment: CommentWithRepliesPopulated): Comment {
|
|||||||
comment: comments.map(makeReplySchema),
|
comment: comments.map(makeReplySchema),
|
||||||
} as WithContext<DiscussionForumPosting>}
|
} as WithContext<DiscussionForumPosting>}
|
||||||
/>
|
/>
|
||||||
<CommentReply serviceId={service.id} activeRatingComment={activeRatingComment} class="xs:mb-4 mb-2" />
|
<CommentReply
|
||||||
|
serviceId={service.id}
|
||||||
|
activeRatingComment={activeRatingComment}
|
||||||
|
strictCommentingEnabled={service.strictCommentingEnabled}
|
||||||
|
class="xs:mb-4 mb-2"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="mb-6 flex flex-wrap items-center justify-between gap-2">
|
<div class="mb-6 flex flex-wrap items-center justify-between gap-2">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
@@ -258,6 +264,7 @@ function makeReplySchema(comment: CommentWithRepliesPopulated): Comment {
|
|||||||
showPending={params.showPending}
|
showPending={params.showPending}
|
||||||
serviceSlug={service.slug}
|
serviceSlug={service.slug}
|
||||||
itemReviewedId={itemReviewedId}
|
itemReviewedId={itemReviewedId}
|
||||||
|
strictCommentingEnabled={service.strictCommentingEnabled}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import type { ComponentProps } from 'astro/types'
|
|||||||
|
|
||||||
type Props = Pick<ComponentProps<typeof InputWrapper>, 'error' | 'name' | 'required'> & {
|
type Props = Pick<ComponentProps<typeof InputWrapper>, 'error' | 'name' | 'required'> & {
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
checked?: boolean
|
||||||
|
descriptionInline?: string
|
||||||
id?: string
|
id?: string
|
||||||
} & (
|
} & (
|
||||||
| {
|
| {
|
||||||
@@ -19,13 +21,11 @@ type Props = Pick<ComponentProps<typeof InputWrapper>, 'error' | 'name' | 'requi
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const { disabled, name, required, error, id, label } = Astro.props
|
const { disabled, name, required, error, id, label, checked, descriptionInline } = Astro.props
|
||||||
|
|
||||||
const hasError = !!error && error.length > 0
|
const hasError = !!error && error.length > 0
|
||||||
---
|
---
|
||||||
|
|
||||||
{}
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
class={cn(
|
class={cn(
|
||||||
@@ -41,9 +41,11 @@ const hasError = !!error && error.length > 0
|
|||||||
name={name}
|
name={name}
|
||||||
required={required}
|
required={required}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
checked={checked}
|
||||||
class={cn(disabled && 'opacity-50')}
|
class={cn(disabled && 'opacity-50')}
|
||||||
/>
|
/>
|
||||||
<span class="text-sm leading-none text-pretty">{label ?? <slot />}</span>
|
<span class="text-sm leading-none text-pretty">{label ?? <slot />}</span>
|
||||||
|
{descriptionInline && <p class="text-day-400 text-xs">{descriptionInline}</p>}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import Button from '../../../../components/Button.astro'
|
|||||||
import FormSection from '../../../../components/FormSection.astro'
|
import FormSection from '../../../../components/FormSection.astro'
|
||||||
import FormSubSection from '../../../../components/FormSubSection.astro'
|
import FormSubSection from '../../../../components/FormSubSection.astro'
|
||||||
import InputCardGroup from '../../../../components/InputCardGroup.astro'
|
import InputCardGroup from '../../../../components/InputCardGroup.astro'
|
||||||
|
import InputCheckbox from '../../../../components/InputCheckbox.astro'
|
||||||
import InputCheckboxGroup from '../../../../components/InputCheckboxGroup.astro'
|
import InputCheckboxGroup from '../../../../components/InputCheckboxGroup.astro'
|
||||||
import InputImageFile from '../../../../components/InputImageFile.astro'
|
import InputImageFile from '../../../../components/InputImageFile.astro'
|
||||||
import InputSelect from '../../../../components/InputSelect.astro'
|
import InputSelect from '../../../../components/InputSelect.astro'
|
||||||
@@ -545,6 +546,13 @@ const apiCalls = await Astro.locals.banners.try(
|
|||||||
cardSize="sm"
|
cardSize="sm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<InputCheckbox
|
||||||
|
label="Strict Commenting"
|
||||||
|
name="strictCommentingEnabled"
|
||||||
|
checked={service.strictCommentingEnabled}
|
||||||
|
descriptionInline="Require proof of being a client for comments."
|
||||||
|
/>
|
||||||
|
|
||||||
<InputSubmitButton label="Update" icon="ri:save-line" hideCancel />
|
<InputSubmitButton label="Update" icon="ri:save-line" hideCancel />
|
||||||
</form>
|
</form>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { AttributeCategory, Currency, VerificationStatus } from '@prisma/client'
|
|||||||
import { Icon } from 'astro-icon/components'
|
import { Icon } from 'astro-icon/components'
|
||||||
import { actions, isInputError } from 'astro:actions'
|
import { actions, isInputError } from 'astro:actions'
|
||||||
|
|
||||||
|
import InputCheckbox from '../../../components/InputCheckbox.astro'
|
||||||
import BaseLayout from '../../../layouts/BaseLayout.astro'
|
import BaseLayout from '../../../layouts/BaseLayout.astro'
|
||||||
import { cn } from '../../../lib/cn'
|
import { cn } from '../../../lib/cn'
|
||||||
import { prisma } from '../../../lib/prisma'
|
import { prisma } from '../../../lib/prisma'
|
||||||
@@ -368,6 +369,13 @@ const inputErrors = isInputError(result?.error) ? result.error.fields : {}
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<InputCheckbox
|
||||||
|
label="Strict Commenting"
|
||||||
|
name="strictCommentingEnabled"
|
||||||
|
checked={false}
|
||||||
|
descriptionInline="Require proof of being a client for comments."
|
||||||
|
/>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
class="font-title inline-flex justify-center rounded-md border border-green-500/30 bg-green-500/10 px-4 py-2 text-sm text-green-400 shadow-xs transition-colors duration-200 hover:bg-green-500/20 focus:ring-2 focus:ring-green-500 focus:ring-offset-2 focus:ring-offset-black focus:outline-hidden"
|
class="font-title inline-flex justify-center rounded-md border border-green-500/30 bg-green-500/10 px-4 py-2 text-sm text-green-400 shadow-xs transition-colors duration-200 hover:bg-green-500/20 focus:ring-2 focus:ring-green-500 focus:ring-offset-2 focus:ring-offset-black focus:outline-hidden"
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ const [service, dbNotificationPreferences] = await Astro.locals.banners.tryMany(
|
|||||||
userSentimentAt: true,
|
userSentimentAt: true,
|
||||||
averageUserRating: true,
|
averageUserRating: true,
|
||||||
isRecentlyApproved: true,
|
isRecentlyApproved: true,
|
||||||
|
strictCommentingEnabled: true,
|
||||||
contactMethods: {
|
contactMethods: {
|
||||||
select: {
|
select: {
|
||||||
value: true,
|
value: true,
|
||||||
@@ -1533,6 +1534,20 @@ const activeEventToShow =
|
|||||||
<li>Moderation is light.</li>
|
<li>Moderation is light.</li>
|
||||||
<li>Double-check before trusting.</li>
|
<li>Double-check before trusting.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
{
|
||||||
|
service.strictCommentingEnabled && (
|
||||||
|
<p class="mt-2">
|
||||||
|
<Icon
|
||||||
|
name="ri:verified-badge-fill"
|
||||||
|
class="me-0.5 inline-block size-4 align-[-0.3em] text-orange-100/95"
|
||||||
|
/>
|
||||||
|
<span class="font-medium text-orange-100/95">Proof of being a client required</span>, for this
|
||||||
|
service.
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
<div class="absolute inset-y-2 right-2 flex flex-col justify-center">
|
<div class="absolute inset-y-2 right-2 flex flex-col justify-center">
|
||||||
<Icon name="ri:alert-line" class="xs:opacity-20 h-full max-h-16 w-auto opacity-10" />
|
<Icon name="ri:alert-line" class="xs:opacity-20 h-full max-h-16 w-auto opacity-10" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user