Skip to content

Commit

Permalink
Private flag on posts (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannesNakayama authored Jun 4, 2024
1 parent a80bf02 commit 568e2ad
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 25 deletions.
44 changes: 36 additions & 8 deletions app/components/ui/post-form.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import { useFetcher } from '@remix-run/react'
import { useState, type FormEvent } from 'react'
import { type ChangeEvent, useState, type FormEvent } from 'react'
import { Textarea } from '#app/components/ui/textarea.tsx'

export function PostForm({ className }: { className?: string }) {
export function PostForm({
showPrivateFlag = false,
className,
}: {
showPrivateFlag: boolean
className?: string
}) {
const [textAreaValue, setTextAreaValue] = useState<string>('')

const [isPrivate, setIsPrivate] = useState<number>(0)

const replyFetcher = useFetcher<{ newPostId: number }>()
const handleSubmit = function (event: FormEvent<HTMLFormElement>) {
replyFetcher.submit(event.currentTarget)
setTextAreaValue('')
}

function handleCheckboxChange(event: ChangeEvent<HTMLInputElement>) {
setIsPrivate(Number(event.target.checked))
}

return (
<replyFetcher.Form
id="create-post"
Expand All @@ -26,12 +38,28 @@ export function PostForm({ className }: { className?: string }) {
onChange={event => setTextAreaValue(event.target.value)}
className="mb-2 w-full"
/>
<button
disabled={replyFetcher.state !== 'idle'}
className="rounded bg-blue-500 px-4 py-2 text-base font-bold text-white hover:bg-blue-700"
>
{replyFetcher.state === 'idle' ? 'Post' : 'submitting...'}
</button>
<div className={'flex flex-row'}>
{showPrivateFlag && (
<div className="mr-2 mt-2">
<input type="hidden" name="isPrivate" value={isPrivate} />
<input
className={'mr-2'}
type="checkbox"
name="isPrivateCheckbox"
onChange={handleCheckboxChange}
/>
<label className={'text-gray-700'} htmlFor="isPrivate">
private
</label>
</div>
)}
<button
disabled={replyFetcher.state !== 'idle'}
className="rounded bg-blue-500 px-4 py-2 text-base font-bold text-white hover:bg-blue-700"
>
{replyFetcher.state === 'idle' ? 'Post' : 'submitting...'}
</button>
</div>
</div>
</replyFetcher.Form>
)
Expand Down
9 changes: 8 additions & 1 deletion app/components/ui/post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ export function PostDetails({
action="/reply"
onSubmit={handleReplySubmit}
>
<ReplyForm post={post} className="mt-2" />
<ReplyForm
post={post}
isPrivate={Boolean(post.isPrivate)}
className="mt-2"
/>
</Form>
)}
</div>
Expand Down Expand Up @@ -211,14 +215,17 @@ export function ParentPost({ parentPost }: { parentPost: Post }) {

function ReplyForm({
post,
isPrivate,
className,
}: {
post: ScoredPost
isPrivate: boolean
className: string
}) {
return (
<div className={'flex flex-col items-end ' + className}>
<input type="hidden" name="parentId" value={post.id} />
<input type="hidden" name="isPrivate" value={Number(isPrivate)} />

<Textarea
name="content"
Expand Down
1 change: 1 addition & 0 deletions app/db/kysely-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type Post = {
authorId: string
createdAt: Generated<number>
deletedAt: number | null
isPrivate: number
}
export type PostStats = {
postId: number
Expand Down
13 changes: 10 additions & 3 deletions app/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@ export async function createPost(
parentId: number | null, // TODO: use parentId?: number
content: string,
authorId: string,
withUpvote?: boolean,
options?: { isPrivate: boolean; withUpvote?: boolean },
): Promise<number> {
const persistedPost: Post = await trx
.insertInto('Post')
.values({ content, parentId, authorId })
.values({
content: content,
parentId: parentId,
authorId: authorId,
isPrivate: options ? Number(options.isPrivate) : 0,
})
.returningAll()
.executeTakeFirstOrThrow()

invariant(persistedPost, `Reply to ${parentId} not submitted successfully`)

if (withUpvote !== undefined ? withUpvote : true) {
if (options?.withUpvote !== undefined ? options.withUpvote : true) {
await vote(trx, authorId, persistedPost.id, null, Direction.Up)
}

Expand Down Expand Up @@ -158,6 +163,7 @@ export async function getTransitiveParents(
'content',
'createdAt',
'deletedAt',
'isPrivate',
])
.unionAll(db =>
db
Expand All @@ -170,6 +176,7 @@ export async function getTransitiveParents(
'P.content',
'P.createdAt',
'P.deletedAt',
'P.isPrivate',
]),
),
)
Expand Down
5 changes: 3 additions & 2 deletions app/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Read [how Jabble makes conversations better](https://github.com/social-protocols
</div>

{showNewDiscussionForm ? (
<PostForm className="mb-4" />
<PostForm showPrivateFlag={true} className="mb-4" />
) : (
loggedIn && (
<div className="mb-4 flex justify-end">{newDiscussionButton()}</div>
Expand Down Expand Up @@ -80,7 +80,8 @@ Read [how Jabble makes conversations better](https://github.com/social-protocols
}

function PostList({ feed }: { feed: rankingTs.ScoredPost[] }) {
return feed.map(post => {
const filteredFeed = feed.filter(post => !post.isPrivate)
return filteredFeed.map(post => {
return <TopLevelPost key={post.id} post={post} className="flex-1" />
})
}
Expand Down
11 changes: 8 additions & 3 deletions app/routes/reply.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { requireUserId } from '#app/utils/auth.server.ts'
const replySchema = zfd.formData({
parentId: z.coerce.number().optional(),
content: z.coerce.string(),
isPrivate: z.coerce.number(),
})

export const action = async (args: ActionFunctionArgs) => {
Expand All @@ -21,12 +22,16 @@ export const action = async (args: ActionFunctionArgs) => {

const content = parsedData.content
const parentId = parsedData.parentId || null
const isPrivate = Boolean(parsedData.isPrivate)

invariant(content, 'content !== undefined')

let postId = await db
.transaction()
.execute(async trx => createPost(trx, parentId, content, userId))
let postId = await db.transaction().execute(async trx =>
createPost(trx, parentId, content, userId, {
isPrivate: isPrivate,
withUpvote: true,
}),
)

return redirect(`/post/${postId}`)
}
9 changes: 6 additions & 3 deletions import-hn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,12 @@ async function importHNPostsFromFile(filename: string) {
}
}

const postId = await db
.transaction()
.execute(async trx => createPost(trx, parentId, markdown, ourUserId))
const postId = await db.transaction().execute(async trx =>
createPost(trx, parentId, markdown, ourUserId, {
isPrivate: false,
withUpvote: true,
}),
)

idMap.set(item.id, postId)
bar1.update(++i)
Expand Down
7 changes: 7 additions & 0 deletions migrations/2024-06-03-private-flag-on-posts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { type Kysely, sql } from 'kysely'

export async function up(db: Kysely<any>): Promise<void> {
await sql`
alter table post add column isPrivate integer not null default false
`.execute(db)
}
26 changes: 21 additions & 5 deletions other/import-society-library-debatemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ async function importQuestion(question: Question) {
let wording = removePrefix(question.question, '[question] ')

const postId = await db.transaction().execute(async trx => {
return createPost(trx, null, wording, userId, withUpvote)
return createPost(trx, null, wording, userId, {
isPrivate: true,
withUpvote: withUpvote,
})
})
console.log(`Inserted question. post ${postId}: ${wording}`)

Expand All @@ -87,7 +90,10 @@ async function importPosition(parentId: number, position: Position) {
let wording = removePrefix(position.position, '[position] ')

const postId = await db.transaction().execute(async trx => {
return createPost(trx, parentId, wording, userId, withUpvote)
return createPost(trx, parentId, wording, userId, {
isPrivate: true,
withUpvote: withUpvote,
})
})
console.log(`Inserted position. post ${postId}: ${wording}`)

Expand All @@ -106,7 +112,10 @@ async function importClaim(parentId: number, claim: Claim) {
let wording = removePrefix(claim.claim, '[for reasons like] ')

const postId = await db.transaction().execute(async trx => {
return createPost(trx, parentId, wording, userId, withUpvote)
return createPost(trx, parentId, wording, userId, {
isPrivate: true,
withUpvote: withUpvote,
})
})
console.log(`Inserted claim. post ${postId}: ${wording}`)

Expand All @@ -122,7 +131,10 @@ async function importExample(parentId: number, example: Example) {
let wording = removePrefix(example.original_example, '[original example] ')

const postId = await db.transaction().execute(async trx => {
return createPost(trx, parentId, wording, userId, withUpvote)
return createPost(trx, parentId, wording, userId, {
isPrivate: true,
withUpvote: withUpvote,
})
})
console.log(`Inserted example. post ${postId}: ${wording}`)

Expand All @@ -144,6 +156,7 @@ ${evidence.url}
${evidence.reasoning}
`,
userId,
{ isPrivate: true, withUpvote: withUpvote },
)
})

Expand All @@ -159,7 +172,10 @@ async function importCounterClaim(parentId: number, counterClaim: string) {
)

const postId = await db.transaction().execute(async trx => {
return createPost(trx, parentId, wording, userId, withUpvote)
return createPost(trx, parentId, wording, userId, {
isPrivate: true,
withUpvote: withUpvote,
})
})
console.log(`Inserted counter claim. post ${postId}: ${wording}`)
}
7 changes: 7 additions & 0 deletions seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export async function seed() {
null,
'So, pregnant people can’t cross state lines to get abortions but guys like Kyle Rittenhouse can cross state lines to murder people. Seems fair.',
alice,
{ isPrivate: false, withUpvote: true },
)
})

Expand All @@ -75,6 +76,7 @@ export async function seed() {
post1,
'Kyle Rittenhouse was acquitted of murder charges. Clear video evidence showed he acted in self defense.',
bob,
{ isPrivate: false, withUpvote: true },
)
})

Expand All @@ -93,6 +95,7 @@ export async function seed() {
post2,
'That trial was a sham. They were never going to convict.',
alice,
{ isPrivate: false, withUpvote: true },
)
})

Expand All @@ -103,6 +106,7 @@ export async function seed() {
null,
'Sudafed, Benadryl and most decongestants don’t work: FDA advisory panel https://trib.al/sJmOJBP',
alice,
{ isPrivate: false, withUpvote: true },
)
})

Expand All @@ -116,6 +120,7 @@ export async function seed() {
post4,
'This is misleading. Regular Benadryl is an antihistamine; it is not a decongestant. There is a Benadryl branded product that is impacted. https://www.nbcnews.com/news/amp/rcna104424',
bob,
{ isPrivate: false, withUpvote: true },
)
})

Expand All @@ -126,6 +131,7 @@ export async function seed() {
null,
"Right now, real wages for the average American worker is higher than it was before the pandemic, with lower wage workers seeing the largest gains. That's Bidenomics.",
alice,
{ isPrivate: false, withUpvote: true },
)
})

Expand All @@ -140,6 +146,7 @@ export async function seed() {
post6,
"The tweet's claim about real wages contains a factual error. On 3/15/20 when US COVID lockdowns began real wages adjusted for inflation (AFI) were $11.15. As of 7/16/23 real wages AFI are $11.05. Real wages AFI remain lower (not higher) than before the pandemic.",
bob,
{ isPrivate: false, withUpvote: true },
)
})

Expand Down

0 comments on commit 568e2ad

Please sign in to comment.