feat(Poll): add option to randomize poll choices (#2082)

* feat(Poll): add option to randomize poll choices

* improve

---------

Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
Co-authored-by: k00b <k00b@stacker.news>
This commit is contained in:
Bryan Mutai 2025-04-16 01:19:14 +03:00 committed by GitHub
parent 9b77cf096d
commit 984790ed5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 23 additions and 5 deletions

View File

@ -26,6 +26,7 @@ import performPaidAction from '../paidAction'
import { GqlAuthenticationError, GqlInputError } from '@/lib/error'
import { verifyHmac } from './wallet'
import { parse } from 'tldts'
import { shuffleArray } from '@/lib/rand'
function commentsOrderByClause (me, models, sort) {
const sharedSortsArray = []
@ -1150,7 +1151,8 @@ export default {
poll.meVoted = false
}
poll.options = options
poll.randPollOptions = item?.randPollOptions
poll.options = poll.randPollOptions ? shuffleArray(options) : options
poll.count = options.reduce((t, o) => t + o.count, 0)
return poll

View File

@ -57,7 +57,7 @@ export default gql`
text: String!, url: String!, boost: Int, status: String, logo: Int): ItemPaidAction!
upsertPoll(
id: ID, sub: String, title: String!, text: String, options: [String!]!, boost: Int, forward: [ItemForwardInput], pollExpiresAt: Date,
hash: String, hmac: String): ItemPaidAction!
randPollOptions: Boolean, hash: String, hmac: String): ItemPaidAction!
updateNoteId(id: ID!, noteId: String!): Item!
upsertComment(id: ID, text: String!, parentId: ID, boost: Int, hash: String, hmac: String): ItemPaidAction!
act(id: ID!, sats: Int, act: String, hasSendWallet: Boolean): ItemActPaidAction!
@ -81,6 +81,7 @@ export default gql`
meInvoiceActionState: InvoiceActionState
count: Int!
options: [PollOption!]!
randPollOptions: Boolean
}
type Items {

View File

@ -1,4 +1,4 @@
import { DateTimeInput, Form, Input, MarkdownInput, VariableInput } from '@/components/form'
import { Checkbox, DateTimeInput, Form, Input, MarkdownInput, VariableInput } from '@/components/form'
import { useApolloClient } from '@apollo/client'
import Countdown from './countdown'
import AdvPostForm, { AdvPostInitial } from './adv-post-form'
@ -30,6 +30,7 @@ export function PollForm ({ item, sub, editThreshold, children }) {
text: item?.text || '',
options: initialOptions || ['', ''],
crosspost: item ? !!item.noteId : me?.privates?.nostrCrossposting,
randPollOptions: item?.poll?.randPollOptions || false,
pollExpiresAt: item ? item.pollExpiresAt : datePivot(new Date(), { hours: 25 }),
...AdvPostInitial({ forward: normalizeForwards(item?.forwards), boost: item?.boost }),
...SubSelectInitial({ sub: item?.subName || sub?.name })
@ -68,6 +69,11 @@ export function PollForm ({ item, sub, editThreshold, children }) {
label='poll expiration'
name='pollExpiresAt'
className='pr-4'
groupClassName='mb-0'
/>
<Checkbox
label={<div className='d-flex align-items-center'>randomize order of poll choices</div>}
name='randPollOptions'
/>
</AdvPostForm>
<ItemButtonBar itemId={item?.id} />

View File

@ -152,6 +152,7 @@ export const POLL_FIELDS = gql`
option
count
}
randPollOptions
}
}`

View File

@ -192,10 +192,10 @@ export const UPSERT_POLL = gql`
${PAID_ACTION}
mutation upsertPoll($sub: String, $id: ID, $title: String!, $text: String,
$options: [String!]!, $boost: Int, $forward: [ItemForwardInput], $pollExpiresAt: Date,
${HASH_HMAC_INPUT_1}) {
$randPollOptions: Boolean, ${HASH_HMAC_INPUT_1}) {
upsertPoll(sub: $sub, id: $id, title: $title, text: $text,
options: $options, boost: $boost, forward: $forward, pollExpiresAt: $pollExpiresAt,
${HASH_HMAC_INPUT_2}) {
randPollOptions: $randPollOptions, ${HASH_HMAC_INPUT_2}) {
result {
id
deleteScheduledAt

View File

@ -1,3 +1,7 @@
export function randInRange (min, max) {
return Math.random() * (max - min) + min
}
export function shuffleArray (array) {
return [...array].sort(() => Math.random() - 0.5)
}

View File

@ -291,6 +291,7 @@ export function pollSchema ({ numExistingChoices = 0, ...args }) {
test: arr => arr.length >= MIN_POLL_NUM_CHOICES - numExistingChoices
}),
pollExpiresAt: date().nullable().min(datePivot(new Date(), { days: 1 }), 'Expiration must be at least 1 day in the future'),
randPollOptions: boolean(),
...advPostSchemaMembers(args),
...subSelectSchemaMembers(args)
}).test({

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Item" ADD COLUMN "randPollOptions" BOOLEAN NOT NULL DEFAULT false;

View File

@ -603,6 +603,7 @@ model Item {
PollBlindVote PollBlindVote[]
ItemUserAgg ItemUserAgg[]
AutoSocialPost AutoSocialPost[]
randPollOptions Boolean @default(false)
@@index([uploadId])
@@index([lastZapAt])