prefixed-queries
This commit is contained in:
parent
9d93ee0a6c
commit
dfbbb075e8
|
@ -25,7 +25,7 @@ type Props = {
|
||||||
export const AuthorBadge = (props: Props) => {
|
export const AuthorBadge = (props: Props) => {
|
||||||
const [isSubscribing, setIsSubscribing] = createSignal(false)
|
const [isSubscribing, setIsSubscribing] = createSignal(false)
|
||||||
const {
|
const {
|
||||||
session,
|
author,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
actions: { loadSubscriptions, requireAuthentication },
|
actions: { loadSubscriptions, requireAuthentication },
|
||||||
} = useSession()
|
} = useSession()
|
||||||
|
@ -96,7 +96,7 @@ export const AuthorBadge = (props: Props) => {
|
||||||
</Show>
|
</Show>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<Show when={props.author.slug !== session()?.user.slug && !props.nameOnly}>
|
<Show when={props.author.slug !== author()?.slug && !props.nameOnly}>
|
||||||
<div class={styles.actions}>
|
<div class={styles.actions}>
|
||||||
<Show
|
<Show
|
||||||
when={!props.minimizeSubscribeButton}
|
when={!props.minimizeSubscribeButton}
|
||||||
|
|
|
@ -32,7 +32,6 @@ type Props = {
|
||||||
export const AuthorCard = (props: Props) => {
|
export const AuthorCard = (props: Props) => {
|
||||||
const { t, lang } = useLocalize()
|
const { t, lang } = useLocalize()
|
||||||
const {
|
const {
|
||||||
session,
|
|
||||||
author,
|
author,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
isSessionLoaded,
|
isSessionLoaded,
|
||||||
|
|
0
src/components/Nav/AuthModal/ResetPasswordForm.tsx
Normal file
0
src/components/Nav/AuthModal/ResetPasswordForm.tsx
Normal file
|
@ -32,7 +32,7 @@ const MD_WIDTH_BREAKPOINT = 992
|
||||||
export const HeaderAuth = (props: Props) => {
|
export const HeaderAuth = (props: Props) => {
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const { page } = useRouter()
|
const { page } = useRouter()
|
||||||
const { author, session, isSessionLoaded, isAuthenticated } = useSession()
|
const { author, isAuthenticated, isSessionLoaded } = useSession()
|
||||||
const {
|
const {
|
||||||
unreadNotificationsCount,
|
unreadNotificationsCount,
|
||||||
actions: { showNotificationsPanel },
|
actions: { showNotificationsPanel },
|
||||||
|
@ -147,7 +147,7 @@ export const HeaderAuth = (props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
<Show when={!session()}>
|
<Show when={!author()}>
|
||||||
<div class={styles.userControlItem} onClick={handleBellIconClick}>
|
<div class={styles.userControlItem} onClick={handleBellIconClick}>
|
||||||
<div class={styles.button}>
|
<div class={styles.button}>
|
||||||
<Icon name="bell-white" counter={1} class={styles.icon} />
|
<Icon name="bell-white" counter={1} class={styles.icon} />
|
||||||
|
|
|
@ -13,7 +13,7 @@ type ProfilePopupProps = Omit<PopupProps, 'children'>
|
||||||
|
|
||||||
export const ProfilePopup = (props: ProfilePopupProps) => {
|
export const ProfilePopup = (props: ProfilePopupProps) => {
|
||||||
const {
|
const {
|
||||||
user,
|
author,
|
||||||
actions: { signOut },
|
actions: { signOut },
|
||||||
} = useSession()
|
} = useSession()
|
||||||
|
|
||||||
|
@ -23,18 +23,18 @@ export const ProfilePopup = (props: ProfilePopupProps) => {
|
||||||
<Popup {...props} horizontalAnchor="right" variant="bordered">
|
<Popup {...props} horizontalAnchor="right" variant="bordered">
|
||||||
<ul class="nodash">
|
<ul class="nodash">
|
||||||
<li>
|
<li>
|
||||||
<a href={getPagePath(router, 'author', { slug: user().slug })}>{t('Profile')}</a>
|
<a href={getPagePath(router, 'author', { slug: author().slug })}>{t('Profile')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href={getPagePath(router, 'drafts')}>{t('Drafts')}</a>
|
<a href={getPagePath(router, 'drafts')}>{t('Drafts')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href={`${getPagePath(router, 'author', { slug: user().slug })}?modal=following`}>
|
<a href={`${getPagePath(router, 'author', { slug: author().slug })}?modal=following`}>
|
||||||
{t('Subscriptions')}
|
{t('Subscriptions')}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href={`${getPagePath(router, 'authorComments', { slug: user().slug })}`}>{t('Comments')}</a>
|
<a href={`${getPagePath(router, 'authorComments', { slug: author().slug })}`}>{t('Comments')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#">{t('Bookmarks')}</a>
|
<a href="#">{t('Bookmarks')}</a>
|
||||||
|
|
|
@ -177,18 +177,18 @@ export const ProfileSettings = () => {
|
||||||
<h4>{t('Userpic')}</h4>
|
<h4>{t('Userpic')}</h4>
|
||||||
<div class="pretty-form__item">
|
<div class="pretty-form__item">
|
||||||
<div
|
<div
|
||||||
class={clsx(styles.userpic, { [styles.hasControls]: form.userpic })}
|
class={clsx(styles.userpic, { [styles.hasControls]: form.pic })}
|
||||||
onClick={!form.userpic && handleUploadAvatar}
|
onClick={!form.pic && handleUploadAvatar}
|
||||||
>
|
>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={isUserpicUpdating()}>
|
<Match when={isUserpicUpdating()}>
|
||||||
<Loading />
|
<Loading />
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={form.userpic}>
|
<Match when={form.pic}>
|
||||||
<div
|
<div
|
||||||
class={styles.userpicImage}
|
class={styles.userpicImage}
|
||||||
style={{
|
style={{
|
||||||
'background-image': `url(${getImageUrl(form.userpic, {
|
'background-image': `url(${getImageUrl(form.pic, {
|
||||||
width: 180,
|
width: 180,
|
||||||
height: 180,
|
height: 180,
|
||||||
})})`,
|
})})`,
|
||||||
|
@ -200,7 +200,7 @@ export const ProfileSettings = () => {
|
||||||
<button
|
<button
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
class={styles.control}
|
class={styles.control}
|
||||||
onClick={() => updateFormField('userpic', '')}
|
onClick={() => updateFormField('pic', '')}
|
||||||
>
|
>
|
||||||
<Icon name="close" />
|
<Icon name="close" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -219,7 +219,7 @@ export const ProfileSettings = () => {
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={!form.userpic}>
|
<Match when={!form.pic}>
|
||||||
<Icon name="user-image-gray" />
|
<Icon name="user-image-gray" />
|
||||||
{t('Here you can upload your photo')}
|
{t('Here you can upload your photo')}
|
||||||
</Match>
|
</Match>
|
||||||
|
|
|
@ -39,13 +39,14 @@ export const ConnectProvider = (props: { children: JSX.Element }) => {
|
||||||
}
|
}
|
||||||
const [retried, setRetried] = createSignal<number>(0)
|
const [retried, setRetried] = createSignal<number>(0)
|
||||||
const listen = () => {
|
const listen = () => {
|
||||||
if (isAuthenticated() && !connected() && retried() < 4) {
|
const token = getToken()
|
||||||
try {
|
console.log(`[context.connect] token: ${token}`)
|
||||||
|
if (token && !connected() && retried() < 4) {
|
||||||
fetchEventSource('https://connect.discours.io', {
|
fetchEventSource('https://connect.discours.io', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
Authorization: getToken(),
|
Authorization: token,
|
||||||
},
|
},
|
||||||
onmessage(event) {
|
onmessage(event) {
|
||||||
const m: SSEMessage = JSON.parse(event.data)
|
const m: SSEMessage = JSON.parse(event.data)
|
||||||
|
@ -60,17 +61,11 @@ export const ConnectProvider = (props: { children: JSX.Element }) => {
|
||||||
},
|
},
|
||||||
onerror(err) {
|
onerror(err) {
|
||||||
console.error('[context.connect] sse connection error', err)
|
console.error('[context.connect] sse connection error', err)
|
||||||
|
setRetried((r) => r + 1)
|
||||||
setConnected(false)
|
setConnected(false)
|
||||||
throw new Error(err) // NOTE: simple hack to close the connection
|
throw new Error(err) // NOTE: simple hack to close the connection
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} catch (err) {
|
|
||||||
if (retried() < 4) {
|
|
||||||
setRetried((r) => r + 1)
|
|
||||||
} else {
|
|
||||||
console.warn('Not trying to reconnect anymore; listen() should be called again.')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { notifierClient } from '../graphql/client/notifier'
|
||||||
import { Notification } from '../graphql/schema/notifier.gen'
|
import { Notification } from '../graphql/schema/notifier.gen'
|
||||||
|
|
||||||
import { SSEMessage, useConnect } from './connect'
|
import { SSEMessage, useConnect } from './connect'
|
||||||
|
import { useSession } from './session'
|
||||||
|
|
||||||
type NotificationsContextType = {
|
type NotificationsContextType = {
|
||||||
notificationEntities: Record<number, Notification>
|
notificationEntities: Record<number, Notification>
|
||||||
|
@ -38,12 +39,13 @@ export const NotificationsProvider = (props: { children: JSX.Element }) => {
|
||||||
const [unreadNotificationsCount, setUnreadNotificationsCount] = createSignal(0)
|
const [unreadNotificationsCount, setUnreadNotificationsCount] = createSignal(0)
|
||||||
const [totalNotificationsCount, setTotalNotificationsCount] = createSignal(0)
|
const [totalNotificationsCount, setTotalNotificationsCount] = createSignal(0)
|
||||||
const [notificationEntities, setNotificationEntities] = createStore<Record<number, Notification>>({})
|
const [notificationEntities, setNotificationEntities] = createStore<Record<number, Notification>>({})
|
||||||
|
const { isAuthenticated } = useSession()
|
||||||
const apiClient = createMemo(() => {
|
const apiClient = createMemo(() => {
|
||||||
if (!notifierClient.private) notifierClient.connect()
|
if (!notifierClient.private && isAuthenticated()) notifierClient.connect()
|
||||||
return notifierClient
|
return notifierClient
|
||||||
})
|
})
|
||||||
const { addHandler } = useConnect()
|
const { addHandler } = useConnect()
|
||||||
const loadNotifications = async (options: { limit: number; offset?: number }) => {
|
const loadNotifications = async (options: { limit?: number; offset?: number }) => {
|
||||||
const { notifications, unread, total } = await apiClient().getNotifications(options)
|
const { notifications, unread, total } = await apiClient().getNotifications(options)
|
||||||
const newNotificationEntities = notifications.reduce((acc, notification) => {
|
const newNotificationEntities = notifications.reduce((acc, notification) => {
|
||||||
acc[notification.id] = notification
|
acc[notification.id] = notification
|
||||||
|
|
|
@ -101,7 +101,7 @@ export const SessionProvider = (props: { children: JSX.Element }) => {
|
||||||
async () => {
|
async () => {
|
||||||
const u = session()?.user
|
const u = session()?.user
|
||||||
if (u) {
|
if (u) {
|
||||||
return (await apiClient.getAuthor({ user: u.id })) ?? null
|
return (await apiClient.getAuthorId({ user: u.id })) ?? null
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,6 +29,7 @@ import draftsLoad from '../query/core/articles-load-drafts'
|
||||||
import myFeed from '../query/core/articles-load-feed'
|
import myFeed from '../query/core/articles-load-feed'
|
||||||
import shoutsLoadSearch from '../query/core/articles-load-search'
|
import shoutsLoadSearch from '../query/core/articles-load-search'
|
||||||
import authorBy from '../query/core/author-by'
|
import authorBy from '../query/core/author-by'
|
||||||
|
import authorId from '../query/core/author-id'
|
||||||
import authorFollowers from '../query/core/author-followers'
|
import authorFollowers from '../query/core/author-followers'
|
||||||
import authorsAll from '../query/core/authors-all'
|
import authorsAll from '../query/core/authors-all'
|
||||||
import authorFollowed from '../query/core/authors-followed-by'
|
import authorFollowed from '../query/core/authors-followed-by'
|
||||||
|
@ -79,10 +80,14 @@ export const apiClient = {
|
||||||
}
|
}
|
||||||
return response.data.load_authors_all
|
return response.data.load_authors_all
|
||||||
},
|
},
|
||||||
getAuthor: async (params: { slug?: string; author_id?: number; user?: string }): Promise<Author> => {
|
getAuthor: async (params: { slug?: string; author_id?: number }): Promise<Author> => {
|
||||||
const response = await publicGraphQLClient.query(authorBy, params).toPromise()
|
const response = await publicGraphQLClient.query(authorBy, params).toPromise()
|
||||||
return response.data.get_author
|
return response.data.get_author
|
||||||
},
|
},
|
||||||
|
getAuthorId: async (params: { user: string }): Promise<Author> => {
|
||||||
|
const response = await publicGraphQLClient.query(authorId, params).toPromise()
|
||||||
|
return response.data.get_author_id
|
||||||
|
},
|
||||||
getAuthorFollowers: async ({ slug }: { slug: string }): Promise<Author[]> => {
|
getAuthorFollowers: async ({ slug }: { slug: string }): Promise<Author[]> => {
|
||||||
const response = await publicGraphQLClient.query(authorFollowers, { slug }).toPromise()
|
const response = await publicGraphQLClient.query(authorFollowers, { slug }).toPromise()
|
||||||
return response.data.get_author_followers
|
return response.data.get_author_followers
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { gql } from '@urql/core'
|
import { gql } from '@urql/core'
|
||||||
|
|
||||||
export default gql`
|
export default gql`
|
||||||
query GetAuthorBy($slug: String, $author_id: Int, $user: String) {
|
query GetAuthorBy($slug: String, $author_id: Int) {
|
||||||
get_author(slug: $slug, author_id: $author_id, user: $user) {
|
get_author(slug: $slug, author_id: $author_id) {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
name
|
name
|
||||||
|
|
17
src/graphql/query/core/author-id.ts
Normal file
17
src/graphql/query/core/author-id.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { gql } from '@urql/core'
|
||||||
|
|
||||||
|
export default gql`
|
||||||
|
query GetAuthorId($user: String!) {
|
||||||
|
get_author_id(user: $user) {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
name
|
||||||
|
bio
|
||||||
|
about
|
||||||
|
pic
|
||||||
|
links
|
||||||
|
created_at
|
||||||
|
last_seen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
9
src/graphql/query/core/query.json
Normal file
9
src/graphql/query/core/query.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"query": "query ValidateToken($params: ValidateJWTTokenInput!) { validate_jwt_token(params: $params) { is_valid claims } }",
|
||||||
|
"variables": {
|
||||||
|
"params": {
|
||||||
|
"token_type": "access_token",
|
||||||
|
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbGxvd2VkX3JvbGVzIjpbInJlYWRlciJdLCJhdWQiOiI5YzExMzM3Ny01ZWVhLTRjODktOThlMS02OTMwMjQ2MmZjMDgiLCJleHAiOjE3MDI1MDM3NDksImlhdCI6MTcwMjUwMTk0OSwiaXNzIjoiaHR0cHM6Ly9hdXRoLmRpc2NvdXJzLmlvIiwibG9naW5fbWV0aG9kIjoiYmFzaWNfYXV0aCIsIm5vbmNlIjoiNTNhZmE1NzMtMWZhMC00NDNhLTk4NzktNWE0ZDk3YTQ1OWEzIiwicm9sZXMiOlsicmVhZGVyIl0sInNjb3BlIjpbIm9wZW5pZCIsImVtYWlsIiwicHJvZmlsZSJdLCJzdWIiOiIyNDU3NTc5Yi0yNTk3LTQzNjMtOGU1MC00YWM5ZjY5YzgyMWQiLCJ0b2tlbl90eXBlIjoiYWNjZXNzX3Rva2VuIn0.ImAmAFXkwReYhLvLR1GG3g0mDllQaj7NVWw5q9D7EFUHtpjuNOanlVfzoaqqB6CXkc_uSRlrfiaLkbfCzhbXAWpi49vOI9P2fvLv-41Y0p8FJZnruZDi1c8psyPU5gpCLp3nqtBTTIR2IP-Uu_1oYo2Hl02xdOFjVHw19f-WEf73L6APBPppNeE21IJJy8aU5uXBHv12Y--kH5tEzn83BNBKPm5yWay-k4DVuBnAJt_ODENqm5NAaiG-q2eG3GnXWpjgpDXf0cxVXdtJbvFcPIv-pH7Dm6ae8m4xM7MmVmpzCE5f-Qc1lwcfX51Cr6IMXUjHx0N3n54sKk91CPa_ug"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
import { gql } from '@urql/core'
|
import { gql } from '@urql/core'
|
||||||
|
|
||||||
export default gql`
|
export default gql`
|
||||||
query LoadNotificationsQuery($params: NotificationsQueryParams!) {
|
query LoadNotificationsQuery($limit: Int, $offset: Int) {
|
||||||
load_notifications(params: $params) {
|
load_notifications(limit: $limit, offset: $offset) {
|
||||||
notifications {
|
notifications {
|
||||||
id
|
id
|
||||||
entity
|
entity
|
||||||
action
|
action
|
||||||
paylaod
|
payload
|
||||||
created_at
|
created_at
|
||||||
seen
|
seen
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user