Skip to content

Commit 1f3f6a0

Browse files
committed
feat(Poll): add option to randomize poll choices
1 parent 6e23709 commit 1f3f6a0

File tree

11 files changed

+41
-4
lines changed

11 files changed

+41
-4
lines changed

api/resolvers/item.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,13 @@ export default {
11521152

11531153
poll.options = options
11541154
poll.count = options.reduce((t, o) => t + o.count, 0)
1155+
const pollSettings = await models.item.findFirst({
1156+
where: {
1157+
id: item.id
1158+
},
1159+
select: { randPollOptions: true }
1160+
})
1161+
poll.randPollOptions = pollSettings?.randPollOptions || false
11551162

11561163
return poll
11571164
},

api/typeDefs/item.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default gql`
5757
text: String!, url: String!, boost: Int, status: String, logo: Int): ItemPaidAction!
5858
upsertPoll(
5959
id: ID, sub: String, title: String!, text: String, options: [String!]!, boost: Int, forward: [ItemForwardInput], pollExpiresAt: Date,
60-
hash: String, hmac: String): ItemPaidAction!
60+
randPollOptions: Boolean, hash: String, hmac: String): ItemPaidAction!
6161
updateNoteId(id: ID!, noteId: String!): Item!
6262
upsertComment(id: ID, text: String!, parentId: ID, boost: Int, hash: String, hmac: String): ItemPaidAction!
6363
act(id: ID!, sats: Int, act: String, hasSendWallet: Boolean): ItemActPaidAction!
@@ -81,6 +81,7 @@ export default gql`
8181
meInvoiceActionState: InvoiceActionState
8282
count: Int!
8383
options: [PollOption!]!
84+
randPollOptions: Boolean
8485
}
8586
8687
type Items {

components/adv-post-form.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,16 @@ export default function AdvPostForm ({ children, item, sub, storageKeyPrefix })
311311
}
312312
name='crosspost'
313313
/>}
314+
{me && itemType === 'poll' &&
315+
<Checkbox
316+
label={
317+
<div className='d-flex align-items-center'>randomize order of poll choices
318+
</div>
319+
}
320+
name='randPollOptions'
321+
checked={formik?.values.randPollOptions}
322+
onChange={formik.handleChange}
323+
/>}
314324
</>
315325
}
316326
/>

components/poll-form.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export function PollForm ({ item, sub, editThreshold, children }) {
3030
text: item?.text || '',
3131
options: initialOptions || ['', ''],
3232
crosspost: item ? !!item.noteId : me?.privates?.nostrCrossposting,
33+
randPollOptions: item?.poll?.randPollOptions || false,
3334
pollExpiresAt: item ? item.pollExpiresAt : datePivot(new Date(), { hours: 25 }),
3435
...AdvPostInitial({ forward: normalizeForwards(item?.forwards), boost: item?.boost }),
3536
...SubSelectInitial({ sub: item?.subName || sub?.name })

components/poll.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import { useState, useLayoutEffect } from 'react'
12
import Button from 'react-bootstrap/Button'
23
import { fixedDecimal, numWithUnits } from '@/lib/format'
4+
import { shuffleArray } from '@/lib/rand'
35
import { timeLeft } from '@/lib/time'
46
import { useMe } from './me'
57
import styles from './poll.module.css'
@@ -14,6 +16,13 @@ export default function Poll ({ item }) {
1416
const { me } = useMe()
1517
const pollVote = usePollVote({ query: POLL_VOTE, itemId: item.id })
1618
const toaster = useToast()
19+
const [pollOptions, setPollOptions] = useState(item.poll.options)
20+
21+
useLayoutEffect(() => {
22+
if (item.poll.randPollOptions) {
23+
setPollOptions(shuffleArray(item.poll.options))
24+
}
25+
}, [])
1726

1827
const PollButton = ({ v }) => {
1928
return (
@@ -75,7 +84,7 @@ export default function Poll ({ item }) {
7584
const pollCount = item.poll.count
7685
return (
7786
<div className={styles.pollBox}>
78-
{item.poll.options.map(v =>
87+
{pollOptions.map(v =>
7988
showPollButton
8089
? <PollButton key={v.id} v={v} />
8190
: <PollResult

fragments/items.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ export const POLL_FIELDS = gql`
152152
option
153153
count
154154
}
155+
randPollOptions
155156
}
156157
}`
157158

fragments/paidAction.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,10 @@ export const UPSERT_POLL = gql`
192192
${PAID_ACTION}
193193
mutation upsertPoll($sub: String, $id: ID, $title: String!, $text: String,
194194
$options: [String!]!, $boost: Int, $forward: [ItemForwardInput], $pollExpiresAt: Date,
195-
${HASH_HMAC_INPUT_1}) {
195+
$randPollOptions: Boolean, ${HASH_HMAC_INPUT_1}) {
196196
upsertPoll(sub: $sub, id: $id, title: $title, text: $text,
197197
options: $options, boost: $boost, forward: $forward, pollExpiresAt: $pollExpiresAt,
198-
${HASH_HMAC_INPUT_2}) {
198+
randPollOptions: $randPollOptions, ${HASH_HMAC_INPUT_2}) {
199199
result {
200200
id
201201
deleteScheduledAt

lib/rand.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
export function randInRange (min, max) {
22
return Math.random() * (max - min) + min
33
}
4+
5+
export function shuffleArray (array) {
6+
return [...array].sort(() => Math.random() - 0.5)
7+
}

lib/validate.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ export function pollSchema ({ numExistingChoices = 0, ...args }) {
291291
test: arr => arr.length >= MIN_POLL_NUM_CHOICES - numExistingChoices
292292
}),
293293
pollExpiresAt: date().nullable().min(datePivot(new Date(), { days: 1 }), 'Expiration must be at least 1 day in the future'),
294+
randPollOptions: boolean(),
294295
...advPostSchemaMembers(args),
295296
...subSelectSchemaMembers(args)
296297
}).test({
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "Item" ADD COLUMN "randPollOptions" BOOLEAN NOT NULL DEFAULT false;

prisma/schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ model Item {
600600
PollBlindVote PollBlindVote[]
601601
ItemUserAgg ItemUserAgg[]
602602
AutoSocialPost AutoSocialPost[]
603+
randPollOptions Boolean @default(false)
603604
604605
@@index([uploadId])
605606
@@index([lastZapAt])

0 commit comments

Comments
 (0)