Add new visitor welcome banner (#418)
* add new visitor welcome banner * show dismissible banner on first-time login * add mutation to hide welcome banner * Update components/banners.js Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com> * fix error handling * simplifications and other review suggestions * cleanup * restore selective display logic * remove unnecessary query arguments * cleanup a bit more * don't show welcome banner to existing stackers --------- Co-authored-by: rleed <rleed1@pm.me> Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com> Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com> Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
This commit is contained in:
parent
e2548e718d
commit
2ba969ebab
|
@ -578,6 +578,14 @@ export default {
|
|||
await models.userSubscription.create({ data })
|
||||
}
|
||||
return { id }
|
||||
},
|
||||
hideWelcomeBanner: async (parent, data, { me, models }) => {
|
||||
if (!me) {
|
||||
throw new GraphQLError('you must be logged in', { extensions: { code: 'UNAUTHENTICATED' } })
|
||||
}
|
||||
|
||||
await models.user.update({ where: { id: me.id }, data: { hideWelcomeBanner: true } })
|
||||
return true
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ export default gql`
|
|||
unlinkAuth(authType: String!): AuthMethods!
|
||||
linkUnverifiedEmail(email: String!): Boolean
|
||||
subscribeUser(id: ID): User
|
||||
hideWelcomeBanner: Boolean
|
||||
}
|
||||
|
||||
type AuthMethods {
|
||||
|
@ -81,6 +82,7 @@ export default gql`
|
|||
hideFromTopUsers: Boolean!
|
||||
hideCowboyHat: Boolean!
|
||||
hideBookmarks: Boolean!
|
||||
hideWelcomeBanner: Boolean!
|
||||
clickToLoadImg: Boolean!
|
||||
wildWestMode: Boolean!
|
||||
greeterMode: Boolean!
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import Alert from 'react-bootstrap/Alert'
|
||||
import styles from './banners.module.css'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useMe } from '../components/me'
|
||||
import { useMutation } from '@apollo/client'
|
||||
import { WELCOME_BANNER_MUTATION } from '../fragments/users'
|
||||
import { useToast } from '../components/toast'
|
||||
|
||||
export default function WelcomeBanner () {
|
||||
const me = useMe()
|
||||
const toaster = useToast()
|
||||
const [hidden, setHidden] = useState(true)
|
||||
const handleClose = async () => {
|
||||
window.localStorage.setItem('hideWelcomeBanner', true)
|
||||
setHidden(true)
|
||||
if (me) {
|
||||
try {
|
||||
await hideWelcomeBanner()
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
toaster.danger('mutation failed')
|
||||
}
|
||||
}
|
||||
}
|
||||
const [hideWelcomeBanner] = useMutation(WELCOME_BANNER_MUTATION, {
|
||||
update (cache) {
|
||||
cache.modify({
|
||||
id: `User:${me.id}`,
|
||||
fields: {
|
||||
hideWelcomeBanner () {
|
||||
return true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
useEffect(() => {
|
||||
setHidden(me?.hideWelcomeBanner || (!me && window.localStorage.getItem('hideWelcomeBanner')))
|
||||
}, [me?.hideWelcomeBanner])
|
||||
|
||||
if (hidden) return
|
||||
|
||||
return (
|
||||
<Alert className={styles.banner} key='info' variant='info' onClose={handleClose} dismissible>
|
||||
<Alert.Heading>
|
||||
👋 Welcome to Stacker News!
|
||||
</Alert.Heading>
|
||||
<p>
|
||||
To get started, check out our{' '}
|
||||
<Alert.Link href='/faq'>FAQs</Alert.Link> or{' '}
|
||||
<Alert.Link href='/guide'>content guidelines</Alert.Link>, or go ahead and{' '}
|
||||
{
|
||||
me
|
||||
? (
|
||||
<Alert.Link href='/post'>make a post</Alert.Link>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<Alert.Link href='/signup'>signup</Alert.Link> or create an{' '}
|
||||
<Alert.Link href='/post'>anonymous post</Alert.Link>
|
||||
</>
|
||||
)
|
||||
}.
|
||||
</p>
|
||||
</Alert>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
.banner {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.banner p:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
|
@ -33,6 +33,7 @@ export const ME = gql`
|
|||
wildWestMode
|
||||
greeterMode
|
||||
lastCheckedJobs
|
||||
hideWelcomeBanner
|
||||
}
|
||||
}`
|
||||
|
||||
|
@ -108,6 +109,13 @@ gql`
|
|||
}
|
||||
`
|
||||
|
||||
export const WELCOME_BANNER_MUTATION =
|
||||
gql`
|
||||
mutation hideWelcomeBanner {
|
||||
hideWelcomeBanner
|
||||
}
|
||||
`
|
||||
|
||||
export const USER_SEARCH =
|
||||
gql`
|
||||
query searchUsers($q: String!, $limit: Int, $similarity: Float) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import Items from '../../components/items'
|
|||
import Layout from '../../components/layout'
|
||||
import { SUB_ITEMS } from '../../fragments/subs'
|
||||
import Snl from '../../components/snl'
|
||||
import WelcomeBanner from '../../components/banners'
|
||||
|
||||
export const getServerSideProps = getGetServerSideProps({
|
||||
query: SUB_ITEMS,
|
||||
|
@ -17,6 +18,7 @@ export default function Sub ({ ssrData }) {
|
|||
return (
|
||||
<Layout sub={variables.sub}>
|
||||
<Snl />
|
||||
<WelcomeBanner />
|
||||
<Items ssrData={ssrData} variables={variables} />
|
||||
</Layout>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "users" ADD COLUMN "hideWelcomeBanner" BOOLEAN NOT NULL DEFAULT true, ALTER COLUMN "hideWelcomeBanner" SET DEFAULT false;
|
|
@ -87,6 +87,7 @@ model User {
|
|||
hideBookmarks Boolean @default(false)
|
||||
followers UserSubscription[] @relation("follower")
|
||||
followees UserSubscription[] @relation("followee")
|
||||
hideWelcomeBanner Boolean @default(false)
|
||||
|
||||
@@index([createdAt], map: "users.created_at_index")
|
||||
@@index([inviteId], map: "users.inviteId_index")
|
||||
|
|
Loading…
Reference in New Issue