auth-minor-fixes
This commit is contained in:
parent
b53aa85337
commit
9a42086f08
35
biome.json
35
biome.json
|
@ -1,21 +1,8 @@
|
|||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.7.2/schema.json",
|
||||
"files": {
|
||||
"include": [
|
||||
"*.tsx",
|
||||
"*.ts",
|
||||
"*.js",
|
||||
"*.json"
|
||||
],
|
||||
"ignore": [
|
||||
"./dist",
|
||||
"./node_modules",
|
||||
".husky",
|
||||
"docs",
|
||||
"gen",
|
||||
"*.gen.ts",
|
||||
"*.d.ts"
|
||||
]
|
||||
"include": ["*.tsx", "*.ts", "*.js", "*.json"],
|
||||
"ignore": ["./dist", "./node_modules", ".husky", "docs", "gen", "*.gen.ts", "*.d.ts"]
|
||||
},
|
||||
"vcs": {
|
||||
"defaultBranch": "dev",
|
||||
|
@ -23,19 +10,13 @@
|
|||
},
|
||||
"organizeImports": {
|
||||
"enabled": true,
|
||||
"ignore": [
|
||||
"./api",
|
||||
"./gen"
|
||||
]
|
||||
"ignore": ["./api", "./gen"]
|
||||
},
|
||||
"formatter": {
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 108,
|
||||
"ignore": [
|
||||
"./src/graphql/schema",
|
||||
"./gen"
|
||||
]
|
||||
"ignore": ["./src/graphql/schema", "./gen"]
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
|
@ -48,13 +29,7 @@
|
|||
}
|
||||
},
|
||||
"linter": {
|
||||
"ignore": [
|
||||
"*.scss",
|
||||
"*.md",
|
||||
".DS_Store",
|
||||
"*.svg",
|
||||
"*.d.ts"
|
||||
],
|
||||
"ignore": ["*.scss", "*.md", ".DS_Store", "*.svg", "*.d.ts"],
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"all": true,
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
"fast-deep-equal": "3.1.3",
|
||||
"ga-gtag": "1.2.0",
|
||||
"graphql": "16.8.1",
|
||||
"graphql-tag": "2.12.6",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"i18next": "22.4.15",
|
||||
"i18next-http-backend": "2.2.0",
|
||||
"i18next-icu": "2.3.0",
|
||||
|
@ -137,5 +137,7 @@
|
|||
"y-prosemirror": "1.2.5",
|
||||
"yjs": "13.6.15"
|
||||
},
|
||||
"trustedDependencies": ["@biomejs/biome"]
|
||||
}
|
||||
"trustedDependencies": [
|
||||
"@biomejs/biome"
|
||||
]
|
||||
}
|
|
@ -541,4 +541,4 @@
|
|||
"You've reached a non-existed page": "You've reached a non-existed page",
|
||||
"Your email": "Your email",
|
||||
"Your name will appear on your profile page and as your signature in publications, comments and responses.": "Your name will appear on your profile page and as your signature in publications, comments and responses"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -568,4 +568,4 @@
|
|||
"You've successfully logged out": "Вы успешно вышли из аккаунта",
|
||||
"Your email": "Ваш email",
|
||||
"Your name will appear on your profile page and as your signature in publications, comments and responses.": "Ваше имя появится на странице вашего профиля и как ваша подпись в публикациях, комментариях и откликах"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,8 +197,10 @@ export const AuthorCard = (props: Props) => {
|
|||
<Show when={props.followers && props.followers.length > 0}>
|
||||
<a href="?m=followers" class={styles.followers}>
|
||||
<For each={props.followers.slice(0, 3)}>
|
||||
{(f) => (
|
||||
<Userpic size={'XS'} name={f.name} userpic={f.pic} class={styles.followersItem} />
|
||||
{(f: Author) => (
|
||||
<Show when={f?.name}>
|
||||
<Userpic size={'XS'} name={f?.name || ''} userpic={f?.pic || ''} class={styles.followersItem} />
|
||||
</Show>
|
||||
)}
|
||||
</For>
|
||||
<div class={styles.followsCounter}>
|
||||
|
|
|
@ -15,20 +15,24 @@ import styles from './DraftsView.module.scss'
|
|||
export const DraftsView = () => {
|
||||
const { author, loadSession } = useSession()
|
||||
const [drafts, setDrafts] = createSignal<Shout[]>([])
|
||||
const [loading, setLoading] = createSignal(false)
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
() => author(),
|
||||
async (a) => {
|
||||
if (a) {
|
||||
setLoading(true)
|
||||
const { shouts: loadedDrafts, error } = await apiClient.getDrafts()
|
||||
if (error) {
|
||||
console.warn(error)
|
||||
await loadSession()
|
||||
}
|
||||
setDrafts(loadedDrafts || [])
|
||||
setLoading(false)
|
||||
}
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -50,7 +54,7 @@ export const DraftsView = () => {
|
|||
|
||||
return (
|
||||
<div class={clsx(styles.DraftsView)}>
|
||||
<Show when={author()?.id} fallback={<Loading />}>
|
||||
<Show when={!loading() && author()?.id} fallback={<Loading />}>
|
||||
<div class="wide-container">
|
||||
<div class="row">
|
||||
<div class="col-md-19 col-lg-18 col-xl-16 offset-md-5">
|
||||
|
|
|
@ -28,6 +28,7 @@ import { EditorSwiper } from '../../_shared/SolidSwiper'
|
|||
import { PublishSettings } from '../PublishSettings'
|
||||
|
||||
import styles from './EditView.module.scss'
|
||||
import { Loading } from '../../_shared/Loading'
|
||||
|
||||
const SimplifiedEditor = lazy(() => import('../../Editor/SimplifiedEditor'))
|
||||
const GrowingTextarea = lazy(() => import('../../_shared/GrowingTextarea/GrowingTextarea'))
|
||||
|
@ -403,7 +404,7 @@ export const EditView = (props: Props) => {
|
|||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
<Show when={page().route === 'edit'}>
|
||||
<Show when={page().route === 'edit' && form?.shoutId} fallback={<Loading />}>
|
||||
<Editor
|
||||
shoutId={form.shoutId}
|
||||
initialContent={form.body}
|
||||
|
|
|
@ -40,7 +40,18 @@ const EMPTY_TOPIC: Topic = {
|
|||
id: -1,
|
||||
slug: '',
|
||||
}
|
||||
const emptyConfig = {
|
||||
|
||||
interface FormConfig {
|
||||
coverImageUrl?: string
|
||||
mainTopic?: Topic
|
||||
slug?: string
|
||||
title?: string
|
||||
subtitle?: string
|
||||
description?: string
|
||||
selectedTopics?: Topic[]
|
||||
}
|
||||
|
||||
const emptyConfig: FormConfig = {
|
||||
coverImageUrl: '',
|
||||
mainTopic: EMPTY_TOPIC,
|
||||
slug: '',
|
||||
|
@ -78,7 +89,7 @@ export const PublishSettings = (props: Props) => {
|
|||
}
|
||||
})
|
||||
|
||||
const [settingsForm, setSettingsForm] = createStore(emptyConfig)
|
||||
const [settingsForm, setSettingsForm] = createStore<FormConfig>(emptyConfig)
|
||||
|
||||
onMount(() => {
|
||||
setSettingsForm(initialData())
|
||||
|
@ -96,12 +107,12 @@ export const PublishSettings = (props: Props) => {
|
|||
setSettingsForm('coverImageUrl', '')
|
||||
}
|
||||
|
||||
const handleTopicSelectChange = (newSelectedTopics) => {
|
||||
const handleTopicSelectChange = (newSelectedTopics: Topic[]) => {
|
||||
if (
|
||||
props.form.selectedTopics.length === 0 ||
|
||||
newSelectedTopics.every((topic) => topic.id !== props.form.mainTopic?.id)
|
||||
newSelectedTopics.every((topic: Topic) => topic.id !== props.form.mainTopic?.id)
|
||||
) {
|
||||
setSettingsForm((prev) => {
|
||||
setSettingsForm((prev: Topic) => {
|
||||
return {
|
||||
...prev,
|
||||
mainTopic: newSelectedTopics[0],
|
||||
|
@ -193,7 +204,8 @@ export const PublishSettings = (props: Props) => {
|
|||
fieldName={t('Header')}
|
||||
placeholder={t('Come up with a title for your story')}
|
||||
initialValue={settingsForm.title}
|
||||
value={(value) => setSettingsForm('title', value)}
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
value={(value: any) => setSettingsForm('title', value)}
|
||||
allowEnterKey={false}
|
||||
maxLength={100}
|
||||
/>
|
||||
|
@ -203,7 +215,8 @@ export const PublishSettings = (props: Props) => {
|
|||
fieldName={t('Subheader')}
|
||||
placeholder={t('Come up with a subtitle for your story')}
|
||||
initialValue={settingsForm.subtitle || ''}
|
||||
value={(value) => setSettingsForm('subtitle', value)}
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
value={(value: any) => setSettingsForm('subtitle', value)}
|
||||
allowEnterKey={false}
|
||||
maxLength={100}
|
||||
/>
|
||||
|
@ -214,7 +227,8 @@ export const PublishSettings = (props: Props) => {
|
|||
placeholder={t('Write a short introduction')}
|
||||
label={t('Description')}
|
||||
initialContent={composeDescription()}
|
||||
onChange={(value) => setForm('description', value)}
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
onChange={(value: any) => setForm('description', value)}
|
||||
maxLength={DESCRIPTION_MAX_LENGTH}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -42,7 +42,7 @@ export const ConnectProvider = (props: { children: JSX.Element }) => {
|
|||
createEffect(
|
||||
on(
|
||||
() => session()?.access_token,
|
||||
async ([tkn]) => {
|
||||
async (tkn) => {
|
||||
if (!sseUrl) return
|
||||
if (!tkn) return
|
||||
if (!connected() && retried() <= RECONNECT_TIMES) {
|
||||
|
@ -67,7 +67,7 @@ export const ConnectProvider = (props: { children: JSX.Element }) => {
|
|||
return Promise.resolve()
|
||||
}
|
||||
return Promise.reject(
|
||||
`SSE: cannot connect to real-time updates, status: ${response.status}`,
|
||||
`SSE: cannot connect to real-time updates: ${response.status}`,
|
||||
)
|
||||
},
|
||||
onclose() {
|
||||
|
@ -75,7 +75,7 @@ export const ConnectProvider = (props: { children: JSX.Element }) => {
|
|||
setConnected(false)
|
||||
if (retried() < RECONNECT_TIMES) {
|
||||
setRetried((r) => r + 1)
|
||||
}
|
||||
} else throw Error('closed by server')
|
||||
},
|
||||
onerror(err) {
|
||||
console.error('[context.connect] SSE connection error:', err)
|
||||
|
|
|
@ -34,13 +34,14 @@ import { useRouter } from '../stores/router'
|
|||
import { showModal } from '../stores/ui'
|
||||
import { addAuthors } from '../stores/zine/authors'
|
||||
|
||||
import { authApiUrl } from '../utils/config'
|
||||
import { useLocalize } from './localize'
|
||||
import { useSnackbar } from './snackbar'
|
||||
|
||||
const defaultConfig: ConfigType = {
|
||||
authorizerURL: 'https://auth.discours.io',
|
||||
authorizerURL: authApiUrl.replace('/graphql', ''),
|
||||
redirectURL: 'https://testing.discours.io',
|
||||
clientID: 'b9038a34-ca59-41ae-a105-c7fbea603e24', // FIXME: use env?
|
||||
clientID: '',
|
||||
}
|
||||
|
||||
export type SessionContextType = {
|
||||
|
@ -73,9 +74,32 @@ export type SessionContextType = {
|
|||
resendVerifyEmail: (params: ResendVerifyEmailInput) => Promise<GenericResponse>
|
||||
}
|
||||
|
||||
// biome-ignore lint/suspicious/noEmptyBlockStatements: <explanation>
|
||||
const noop = () => {}
|
||||
|
||||
const noop = () => null
|
||||
const metaRes = {
|
||||
data: {
|
||||
meta: {
|
||||
version: 'latest',
|
||||
// client_id: 'b9038a34-ca59-41ae-a105-c7fbea603e24',
|
||||
is_google_login_enabled: true,
|
||||
is_facebook_login_enabled: true,
|
||||
is_github_login_enabled: true,
|
||||
is_linkedin_login_enabled: false,
|
||||
is_apple_login_enabled: false,
|
||||
is_twitter_login_enabled: true,
|
||||
is_microsoft_login_enabled: false,
|
||||
is_twitch_login_enabled: false,
|
||||
is_roblox_login_enabled: false,
|
||||
is_email_verification_enabled: true,
|
||||
is_basic_authentication_enabled: true,
|
||||
is_magic_link_login_enabled: true,
|
||||
is_sign_up_enabled: true,
|
||||
is_strong_password_enabled: false,
|
||||
is_multi_factor_auth_enabled: true,
|
||||
is_mobile_basic_authentication_enabled: true,
|
||||
is_phone_verification_enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
const SessionContext = createContext<SessionContextType>()
|
||||
|
||||
export function useSession() {
|
||||
|
@ -212,44 +236,41 @@ export const SessionProvider = (props: {
|
|||
})
|
||||
|
||||
// when session is loaded
|
||||
createEffect(() => {
|
||||
if (session()) {
|
||||
const token = session()?.access_token
|
||||
if (token) {
|
||||
if (!inboxClient.private) {
|
||||
apiClient.connect(token)
|
||||
inboxClient.connect(token)
|
||||
}
|
||||
|
||||
try {
|
||||
const appdata = session()?.user.app_data
|
||||
if (appdata) {
|
||||
const { profile } = appdata
|
||||
if (profile?.id) {
|
||||
setAuthor(profile)
|
||||
addAuthors([profile])
|
||||
} else {
|
||||
setTimeout(loadAuthor, 15)
|
||||
createEffect(
|
||||
on(
|
||||
session,
|
||||
(s: AuthToken) => {
|
||||
if (s) {
|
||||
const token = s?.access_token
|
||||
if (token) {
|
||||
if (!inboxClient.private) {
|
||||
apiClient.connect(token)
|
||||
inboxClient.connect(token)
|
||||
}
|
||||
|
||||
try {
|
||||
const appdata = session()?.user.app_data
|
||||
if (appdata) {
|
||||
const { profile } = appdata
|
||||
if (profile?.id) {
|
||||
setAuthor(profile)
|
||||
addAuthors([profile])
|
||||
} else {
|
||||
setTimeout(loadAuthor, 15)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
setIsSessionLoaded(true)
|
||||
} else {
|
||||
reset()
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
setIsSessionLoaded(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// when author is loaded
|
||||
createEffect(() => {
|
||||
if (author()) {
|
||||
addAuthors([author()])
|
||||
} else {
|
||||
reset()
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
const reset = () => {
|
||||
setIsSessionLoaded(true)
|
||||
setSession(null)
|
||||
|
@ -257,20 +278,13 @@ export const SessionProvider = (props: {
|
|||
}
|
||||
|
||||
// initial effect
|
||||
onMount(async () => {
|
||||
const metaRes = await authorizer().getMetaData()
|
||||
onMount(() => {
|
||||
setConfig({
|
||||
...defaultConfig,
|
||||
...metaRes,
|
||||
redirectURL: window.location.origin,
|
||||
})
|
||||
let s: AuthToken
|
||||
try {
|
||||
s = await loadSession()
|
||||
} catch (error) {
|
||||
console.warn('[context.session] load session failed', error)
|
||||
}
|
||||
if (!s) reset()
|
||||
loadSession()
|
||||
})
|
||||
|
||||
// callback state updater
|
||||
|
@ -318,6 +332,7 @@ export const SessionProvider = (props: {
|
|||
console.debug(authResult)
|
||||
reset()
|
||||
showSnackbar({ body: t("You've successfully logged out") })
|
||||
console.debug(session())
|
||||
}
|
||||
|
||||
const changePassword = async (password: string, token: string) => {
|
||||
|
|
|
@ -17,7 +17,7 @@ import styles from '../styles/Create.module.scss'
|
|||
|
||||
const handleCreate = async (layout: LayoutType) => {
|
||||
const shout = await apiClient.createArticle({ article: { layout: layout } })
|
||||
redirectPage(router, 'edit', {
|
||||
shout?.id && redirectPage(router, 'edit', {
|
||||
shoutId: shout?.id.toString(),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import { useLocalize } from '../context/localize'
|
|||
import { useSession } from '../context/session'
|
||||
import { apiClient } from '../graphql/client/core'
|
||||
import { Shout } from '../graphql/schema/core.gen'
|
||||
import { router, useRouter } from '../stores/router'
|
||||
import { router } from '../stores/router'
|
||||
|
||||
import { redirectPage } from '@nanostores/router'
|
||||
import { useSnackbar } from '../context/snackbar'
|
||||
|
@ -33,7 +33,6 @@ const getContentTypeTitle = (layout: LayoutType) => {
|
|||
export const EditPage = () => {
|
||||
const { t } = useLocalize()
|
||||
const { session } = useSession()
|
||||
const { page } = useRouter()
|
||||
const snackbar = useSnackbar()
|
||||
|
||||
const fail = async (error: string) => {
|
||||
|
@ -48,15 +47,17 @@ export const EditPage = () => {
|
|||
|
||||
createEffect(
|
||||
on(
|
||||
() => page(),
|
||||
() => window?.location.pathname,
|
||||
(p) => {
|
||||
if (p?.path) {
|
||||
console.debug(p?.path)
|
||||
const shoutId = p?.path.split('/').pop()
|
||||
const shoutIdFromUrl = Number.parseInt(shoutId ?? '0', 10)
|
||||
console.debug(`editing shout ${shoutIdFromUrl}`)
|
||||
if (shoutIdFromUrl) {
|
||||
setShoutId(shoutIdFromUrl)
|
||||
if (p) {
|
||||
console.debug(p)
|
||||
const shoutId = p.split('/').pop()
|
||||
if (shoutId) {
|
||||
const shoutIdFromUrl = Number.parseInt(shoutId ?? '0', 10)
|
||||
console.debug(`editing shout ${shoutIdFromUrl}`)
|
||||
if (shoutIdFromUrl) {
|
||||
setShoutId(shoutIdFromUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@ export const isDev = import.meta.env.MODE === 'development'
|
|||
export const cdnUrl = 'https://cdn.discours.io'
|
||||
export const thumborUrl = import.meta.env.PUBLIC_THUMBOR_URL || 'https://images.discours.io'
|
||||
export const errorsReportingDsn = import.meta.env.PUBLIC_GLITCHTIP_DSN || import.meta.env.PUBLIC_SENTRY_DSN || ''
|
||||
export const coreApiUrl = 'https://coretest.discours.io'
|
||||
export const chatApiUrl = 'https://inboxtest.discours.io'
|
||||
export const authApiUrl = 'https://authtest.discours.io/graphql'
|
||||
export const sseUrl = 'https://presencetest.discours.io'
|
||||
export const coreApiUrl = import.meta.env.PUBLIC_API_BASE || 'https://coretest.discours.io'
|
||||
export const chatApiUrl = import.meta.env.PUBLIC_CHAT_API || 'https://inboxtest.discours.io'
|
||||
export const authApiUrl = import.meta.env.PUBLIC_AUTH_API || 'https://authtest.discours.io/graphql'
|
||||
export const sseUrl = import.meta.env.PUBLIC_REALTIME_EVENTS || 'https://presencetest.discours.io'
|
||||
|
|
Loading…
Reference in New Issue
Block a user