Merge branch 'dev' into hotfix/editor-permission

This commit is contained in:
Untone 2024-05-06 17:23:24 +03:00
commit 82e2abf8e3
22 changed files with 491 additions and 394 deletions

640
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,7 @@
"@nanostores/solid": "0.4.2", "@nanostores/solid": "0.4.2",
"@playwright/test": "1.41.2", "@playwright/test": "1.41.2",
"@popperjs/core": "2.11.8", "@popperjs/core": "2.11.8",
"@sentry/browser": "7.99.0", "@sentry/browser": "^7.113.0",
"@solid-primitives/media": "2.2.3", "@solid-primitives/media": "2.2.3",
"@solid-primitives/memo": "1.2.4", "@solid-primitives/memo": "1.2.4",
"@solid-primitives/pagination": "0.2.10", "@solid-primitives/pagination": "0.2.10",

View File

@ -532,7 +532,7 @@
"resend confirmation link": "отправить ссылку ещё раз", "resend confirmation link": "отправить ссылку ещё раз",
"shout": "пост", "shout": "пост",
"shout not found": "публикация не найдена", "shout not found": "публикация не найдена",
"shoutsWithCount": "{count} {count, plural, one {пост} few {поста} other {постов}}", "shoutsWithCount": "{count} {count, plural, one {публикация} few {публикации} other {публикаций}}",
"sign in": "войти", "sign in": "войти",
"sign up or sign in": "зарегистрироваться или войти", "sign up or sign in": "зарегистрироваться или войти",
"sign up": "зарегистрироваться", "sign up": "зарегистрироваться",

View File

@ -60,11 +60,13 @@
.bio { .bio {
@include font-size(1.2rem); @include font-size(1.2rem);
color: var(--black-400);
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: 1rem;
color: var(--black-400);
font-weight: 500; font-weight: 500;
gap: 1rem;
max-width: 100%;
word-break: break-word;
} }
.actions { .actions {

View File

@ -27,6 +27,7 @@ type Props = {
inviteView?: boolean inviteView?: boolean
onInvite?: (id: number) => void onInvite?: (id: number) => void
selected?: boolean selected?: boolean
subscriptionsMode?: boolean
} }
export const AuthorBadge = (props: Props) => { export const AuthorBadge = (props: Props) => {
const { mediaMatches } = useMediaQuery() const { mediaMatches } = useMediaQuery()
@ -45,7 +46,6 @@ export const AuthorBadge = (props: Props) => {
setIsMobileView(!mediaMatches.sm) setIsMobileView(!mediaMatches.sm)
}) })
// const { setFollowing } = useFollowing()
const { changeSearchParams } = useRouter() const { changeSearchParams } = useRouter()
const { t, formatDate, lang } = useLocalize() const { t, formatDate, lang } = useLocalize()
@ -114,7 +114,7 @@ export const AuthorBadge = (props: Props) => {
<div class={clsx('text-truncate', styles.bio)} innerHTML={props.author.bio} /> <div class={clsx('text-truncate', styles.bio)} innerHTML={props.author.bio} />
</Match> </Match>
</Switch> </Switch>
<Show when={props.author?.stat}> <Show when={props.author?.stat && !props.subscriptionsMode}>
<div class={styles.bio}> <div class={styles.bio}>
<Show when={props.author?.stat.shouts > 0}> <Show when={props.author?.stat.shouts > 0}>
<div>{t('PublicationsWithCount', { count: props.author.stat?.shouts ?? 0 })}</div> <div>{t('PublicationsWithCount', { count: props.author.stat?.shouts ?? 0 })}</div>

View File

@ -312,9 +312,9 @@ export const AuthorCard = (props: Props) => {
<For each={authorSubs()}> <For each={authorSubs()}>
{(subscription) => {(subscription) =>
isAuthor(subscription) ? ( isAuthor(subscription) ? (
<AuthorBadge author={subscription} /> <AuthorBadge author={subscription} subscriptionsMode={true} />
) : ( ) : (
<TopicBadge topic={subscription} /> <TopicBadge topic={subscription} subscriptionsMode={true} />
) )
} }
</For> </For>

View File

@ -151,7 +151,7 @@ export const Editor = (props: Props) => {
} }
showSnackbar({ body: t('Uploading image') }) showSnackbar({ body: t('Uploading image') })
const result = await handleImageUpload(uplFile) const result = await handleImageUpload(uplFile, session()?.access_token)
editor() editor()
.chain() .chain()

View File

@ -28,6 +28,7 @@ const embedData = (data) => {
const result: { src: string; width?: string; height?: string } = { src: '' } const result: { src: string; width?: string; height?: string } = { src: '' }
// biome-ignore lint/style/useForOf: <explanation>
for (let i = 0; i < attributes.length; i++) { for (let i = 0; i < attributes.length; i++) {
const attribute = attributes.item(i) const attribute = attributes.item(i)
if (attribute) { if (attribute) {

View File

@ -12,6 +12,7 @@ import { Icon } from '../../_shared/Icon'
import { Loading } from '../../_shared/Loading' import { Loading } from '../../_shared/Loading'
import { InlineForm } from '../InlineForm' import { InlineForm } from '../InlineForm'
import { useSession } from '../../../context/session'
import styles from './UploadModalContent.module.scss' import styles from './UploadModalContent.module.scss'
type Props = { type Props = {
@ -24,12 +25,12 @@ export const UploadModalContent = (props: Props) => {
const [uploadError, setUploadError] = createSignal<string | undefined>() const [uploadError, setUploadError] = createSignal<string | undefined>()
const [dragActive, setDragActive] = createSignal(false) const [dragActive, setDragActive] = createSignal(false)
const [dragError, setDragError] = createSignal<string | undefined>() const [dragError, setDragError] = createSignal<string | undefined>()
const { session } = useSession()
const { selectFiles } = createFileUploader({ multiple: false, accept: 'image/*' }) const { selectFiles } = createFileUploader({ multiple: false, accept: 'image/*' })
const runUpload = async (file: UploadFile) => { const runUpload = async (file: UploadFile) => {
try { try {
setIsUploading(true) setIsUploading(true)
const result = await handleImageUpload(file) const result = await handleImageUpload(file, session()?.access_token)
props.onClose(result) props.onClose(result)
setIsUploading(false) setIsUploading(false)
} catch (error) { } catch (error) {

View File

@ -298,10 +298,6 @@
box-sizing: content-box; box-sizing: content-box;
display: inline-flex; display: inline-flex;
@include media-breakpoint-up(sm) {
padding-left: divide($container-padding-x, 2);
}
@include media-breakpoint-up(lg) { @include media-breakpoint-up(lg) {
display: none; display: none;
} }
@ -425,7 +421,7 @@
width: 100%; width: 100%;
@include media-breakpoint-up(xl) { @include media-breakpoint-up(xl) {
right: 9rem; right: 1.4rem;
} }
.control { .control {
@ -457,6 +453,14 @@
} }
} }
.articleControlsAuthorized {
right: 3.6rem;
@include media-breakpoint-up(xl) {
right: 9rem;
}
}
.userControl { .userControl {
align-items: center; align-items: center;
display: flex; display: flex;
@ -484,7 +488,8 @@
} }
.editorControl { .editorControl {
border-radius: 1.2em; border-radius: 2em;
font-size: 1.4rem !important;
&:hover { &:hover {
background: var(--background-color-invert); background: var(--background-color-invert);
@ -518,6 +523,7 @@
height: 2.8rem; height: 2.8rem;
justify-content: center; justify-content: center;
margin: 0 0.4rem; margin: 0 0.4rem;
order: 2;
position: relative; position: relative;
transition: margin-left 0.3s; transition: margin-left 0.3s;
width: 2.8rem; width: 2.8rem;
@ -528,7 +534,7 @@
width: 3.2rem; width: 3.2rem;
} }
@include media-breakpoint-down(sm) { @include media-breakpoint-down(xl) {
margin-left: 0.4rem !important; margin-left: 0.4rem !important;
} }
@ -579,6 +585,10 @@
.userControlItemSearch { .userControlItemSearch {
margin: 0 1rem 0 2.2rem; margin: 0 1rem 0 2.2rem;
@include media-breakpoint-down(xl) {
order: 1;
}
} }
.userControlItemUserpic { .userControlItemUserpic {
@ -591,13 +601,6 @@
} }
} }
.userControlItemInbox,
.userControlItemSearch {
@include media-breakpoint-down(sm) {
display: none;
}
}
.userControlItemVerbose { .userControlItemVerbose {
align-items: stretch; align-items: stretch;
display: flex; display: flex;
@ -677,7 +680,9 @@
} }
&:hover { &:hover {
background-color: var(--link-hover-background); @include media-breakpoint-up(xl) {
background-color: var(--link-hover-background);
}
&, &,
.textLabel { .textLabel {
@ -703,6 +708,18 @@
} }
} }
.userControlItemCreate {
.icon {
height: 2.8rem;
width: 2.8rem;
@include media-breakpoint-up(md) {
height: 3.2rem;
width: 3.2rem;
}
}
}
.subnavigation { .subnavigation {
background: #000; background: #000;
color: #fff; color: #fff;

View File

@ -59,6 +59,7 @@ export const Header = (props: Props) => {
const [isTopicsVisible, setIsTopicsVisible] = createSignal(false) const [isTopicsVisible, setIsTopicsVisible] = createSignal(false)
const [isZineVisible, setIsZineVisible] = createSignal(false) const [isZineVisible, setIsZineVisible] = createSignal(false)
const [isFeedVisible, setIsFeedVisible] = createSignal(false) const [isFeedVisible, setIsFeedVisible] = createSignal(false)
const { isAuthenticated } = useSession()
const toggleFixed = () => setFixed(!fixed()) const toggleFixed = () => setFixed(!fixed())
@ -68,7 +69,9 @@ export const Header = (props: Props) => {
let windowScrollTop = 0 let windowScrollTop = 0
createEffect(() => { createEffect(() => {
setRandomTopics(getRandomTopicsFromArray(topics())) if (topics()?.length) {
setRandomTopics(getRandomTopicsFromArray(topics()))
}
}) })
createEffect(() => { createEffect(() => {
@ -330,7 +333,11 @@ export const Header = (props: Props) => {
</div> </div>
<HeaderAuth setIsProfilePopupVisible={setIsProfilePopupVisible} /> <HeaderAuth setIsProfilePopupVisible={setIsProfilePopupVisible} />
<Show when={props.title}> <Show when={props.title}>
<div class={clsx(styles.articleControls, 'col-auto')}> <div
class={clsx(styles.articleControls, 'col-auto', {
[styles.articleControlsAuthorized]: isAuthenticated(),
})}
>
<SharePopup <SharePopup
title={props.title} title={props.title}
imageUrl={props.cover} imageUrl={props.cover}

View File

@ -113,8 +113,8 @@ export const HeaderAuth = (props: Props) => {
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}> <div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
<a href={getPagePath(router, 'create')}> <a href={getPagePath(router, 'create')}>
<span class={styles.textLabel}>{t('Create post')}</span> <span class={styles.textLabel}>{t('Create post')}</span>
<Icon name="pencil" class={styles.icon} /> <Icon name="pencil-outline" class={styles.icon} />
<Icon name="pencil" class={clsx(styles.icon, styles.iconHover)} /> <Icon name="pencil-outline-hover" class={clsx(styles.icon, styles.iconHover)} />
</a> </a>
</div> </div>
</Show> </Show>
@ -221,8 +221,8 @@ export const HeaderAuth = (props: Props) => {
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}> <div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
<a href={getPagePath(router, 'create')}> <a href={getPagePath(router, 'create')}>
<span class={styles.textLabel}>{t('Create post')}</span> <span class={styles.textLabel}>{t('Create post')}</span>
<Icon name="pencil" class={styles.icon} /> <Icon name="pencil-outline" class={styles.icon} />
<Icon name="pencil" class={clsx(styles.icon, styles.iconHover)} /> <Icon name="pencil-outline-hover" class={clsx(styles.icon, styles.iconHover)} />
</a> </a>
</div> </div>
</Show> </Show>
@ -235,7 +235,7 @@ export const HeaderAuth = (props: Props) => {
<a href="?m=auth&mode=login"> <a href="?m=auth&mode=login">
<span class={styles.textLabel}>{t('Enter')}</span> <span class={styles.textLabel}>{t('Enter')}</span>
<Icon name="key" class={styles.icon} /> <Icon name="key" class={styles.icon} />
{/*<Icon name="user-default" class={clsx(styles.icon, styles.iconHover)} />*/} <Icon name="key" class={clsx(styles.icon, styles.iconHover)} />
</a> </a>
</div> </div>
</Show> </Show>

View File

@ -57,7 +57,7 @@ export const ProfileSettings = () => {
const [nameError, setNameError] = createSignal<string>() const [nameError, setNameError] = createSignal<string>()
const { form, submit, updateFormField, setForm } = useProfileForm() const { form, submit, updateFormField, setForm } = useProfileForm()
const { showSnackbar } = useSnackbar() const { showSnackbar } = useSnackbar()
const { loadAuthor } = useSession() const { loadAuthor, session } = useSession()
const { showConfirm } = useConfirm() const { showConfirm } = useConfirm()
createEffect(() => { createEffect(() => {
@ -140,7 +140,7 @@ export const ProfileSettings = () => {
setUploadError(false) setUploadError(false)
setIsUserpicUpdating(true) setIsUserpicUpdating(true)
const result = await handleImageUpload(uploadFile) const result = await handleImageUpload(uploadFile, session()?.access_token)
updateFormField('pic', result.url) updateFormField('pic', result.url)
setUserpicFile(null) setUserpicFile(null)

View File

@ -1,12 +1,11 @@
.TopicBadge { .TopicBadge {
margin-bottom: 2rem; margin-bottom: 4.8rem;
gap: 1rem; gap: 1rem;
.content { .content {
align-items: flex-start; align-items: flex-start;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin-bottom: .8rem;
} }
.basicInfo { .basicInfo {
@ -48,11 +47,62 @@
@include font-size(1.4rem); @include font-size(1.4rem);
border: none; border: none;
display: flex;
flex-direction: column; // display: flex;
// flex-direction: column;
&:hover { &:hover {
background: unset; background: unset;
color: inherit;
.title {
background: var(--background-color-invert);
color: var(--default-color-invert);
}
}
.title {
@include font-size(2.2rem);
font-weight: bold;
}
.description {
@include font-size(1.6rem);
line-height: 1.4;
margin: 0.8rem 0;
-webkit-line-clamp: 2;
}
}
.actions {
display: flex;
flex-direction: row;
gap: 1rem;
margin-bottom: -1rem;
}
.subscribeButton {
border-radius: 0.8rem !important;
margin-right: 0 !important;
width: 9em;
}
}
.TopicBadgeSubscriptionsMode {
margin-bottom: 2rem;
.content {
margin-bottom: 0.8rem;
}
.info {
&:hover {
.title {
background-color: var(--blue-500);
color: var(--white-500);
}
} }
.title { .title {
@ -66,7 +116,11 @@
.description { .description {
color: var(--black-400); color: var(--black-400);
@include font-size(1.2rem);
font-weight: 500; font-weight: 500;
margin: 0;
} }
} }
@ -88,7 +142,6 @@
color: var(--secondary-color); color: var(--secondary-color);
display: flex; display: flex;
margin: 0 0 1em;
@include media-breakpoint-down(md) { @include media-breakpoint-down(md) {
flex-wrap: wrap; flex-wrap: wrap;
@ -101,6 +154,7 @@
.statsItem { .statsItem {
@include font-size(1.4rem); @include font-size(1.4rem);
font-weight: 500;
margin-right: 1.6rem; margin-right: 1.6rem;
white-space: nowrap; white-space: nowrap;

View File

@ -15,6 +15,7 @@ type Props = {
topic: Topic topic: Topic
minimizeSubscribeButton?: boolean minimizeSubscribeButton?: boolean
showStat?: boolean showStat?: boolean
subscriptionsMode?: boolean
} }
export const TopicBadge = (props: Props) => { export const TopicBadge = (props: Props) => {
@ -47,23 +48,27 @@ export const TopicBadge = (props: Props) => {
lang() === 'en' ? capitalize(props.topic.slug.replaceAll('-', ' ')) : props.topic.title lang() === 'en' ? capitalize(props.topic.slug.replaceAll('-', ' ')) : props.topic.title
return ( return (
<div class={styles.TopicBadge}> <div class={clsx(styles.TopicBadge, { [styles.TopicBadgeSubscriptionsMode]: props.subscriptionsMode })}>
<div class={styles.content}> <div class={styles.content}>
<div class={styles.basicInfo}> <div class={styles.basicInfo}>
<a <Show when={props.subscriptionsMode}>
href={`/topic/${props.topic.slug}`} <a
class={clsx(styles.picture, { href={`/topic/${props.topic.slug}`}
[styles.withImage]: props.topic.pic, class={clsx(styles.picture, {
[styles.smallSize]: isMobileView(), [styles.withImage]: props.topic.pic,
})} [styles.smallSize]: isMobileView(),
style={ })}
props.topic.pic && { style={
'background-image': `url('${getImageUrl(props.topic.pic, { width: 40, height: 40 })}')`, props.topic.pic && {
'background-image': `url('${getImageUrl(props.topic.pic, { width: 40, height: 40 })}')`,
}
} }
} />
/> </Show>
<a href={`/topic/${props.topic.slug}`} class={styles.info}> <a href={`/topic/${props.topic.slug}`} class={styles.info}>
<span class={styles.title}>{title()}</span> <span class={styles.title}>{title()}</span>
<Show <Show
when={props.topic.body} when={props.topic.body}
fallback={ fallback={
@ -86,18 +91,23 @@ export const TopicBadge = (props: Props) => {
/> />
</div> </div>
</div> </div>
<div class={styles.stats}>
<span class={styles.statsItem}>{t('shoutsWithCount', { count: props.topic?.stat?.shouts })}</span> <Show when={!props.subscriptionsMode}>
<span class={styles.statsItem}>{t('authorsWithCount', { count: props.topic?.stat?.authors })}</span> <div class={styles.stats}>
<span class={styles.statsItem}> <span class={styles.statsItem}>{t('shoutsWithCount', { count: props.topic?.stat?.shouts })}</span>
{t('FollowersWithCount', { count: props.topic?.stat?.followers })}
</span>
<Show when={props.topic?.stat?.comments}>
<span class={styles.statsItem}> <span class={styles.statsItem}>
{t('CommentsWithCount', { count: props.topic?.stat?.comments ?? 0 })} {t('authorsWithCount', { count: props.topic?.stat?.authors })}
</span> </span>
</Show> <span class={styles.statsItem}>
</div> {t('FollowersWithCount', { count: props.topic?.stat?.followers })}
</span>
<Show when={props.topic?.stat?.comments}>
<span class={styles.statsItem}>
{t('CommentsWithCount', { count: props.topic?.stat?.comments ?? 0 })}
</span>
</Show>
</div>
</Show>
</div> </div>
) )
} }

View File

@ -42,7 +42,8 @@ export const AllAuthors = (props: Props) => {
const filteredAuthors = createMemo(() => { const filteredAuthors = createMemo(() => {
const query = searchQuery().toLowerCase() const query = searchQuery().toLowerCase()
return sortedAuthors().filter((author) => { return sortedAuthors().filter((author) => {
return author.name.toLowerCase().includes(query) // Предполагаем, что у автора есть свойство name // Предполагаем, что у автора есть свойство name
return author.name.toLowerCase().includes(query)
}) })
}) })

View File

@ -80,7 +80,7 @@ export const AllTopics = (props: Props) => {
const AllTopicsHead = () => ( const AllTopicsHead = () => (
<div class="row"> <div class="row">
<div class="col-lg-20 col-xl-18"> <div class="col-lg-18 col-xl-15">
<h1>{t('Topics')}</h1> <h1>{t('Topics')}</h1>
<p>{t('Subscribe what you like to tune your personal feed')}</p> <p>{t('Subscribe what you like to tune your personal feed')}</p>
@ -129,7 +129,7 @@ export const AllTopics = (props: Props) => {
<Show when={filteredResults().length > 0}> <Show when={filteredResults().length > 0}>
<Show when={searchParams().by === 'title'}> <Show when={searchParams().by === 'title'}>
<div class="col-lg-20 col-xl-18"> <div class="col-lg-18 col-xl-15">
<ul class={clsx('nodash', styles.alphabet)}> <ul class={clsx('nodash', styles.alphabet)}>
<For each={ALPHABET}> <For each={ALPHABET}>
{(letter, index) => ( {(letter, index) => (
@ -180,7 +180,7 @@ export const AllTopics = (props: Props) => {
<Show when={searchParams().by && searchParams().by !== 'title'}> <Show when={searchParams().by && searchParams().by !== 'title'}>
<div class="row"> <div class="row">
<div class="col-lg-20 col-xl-18 py-4"> <div class="col-lg-18 col-xl-15 py-4">
<For each={filteredResults().slice(0, limit())}> <For each={filteredResults().slice(0, limit())}>
{(topic) => ( {(topic) => (
<> <>

View File

@ -141,7 +141,7 @@
float: none; float: none;
padding-bottom: 0.6rem; padding-bottom: 0.6rem;
padding-top: 0.6rem; padding-top: 0.6rem;
width: 10em; width: 9em;
.icon { .icon {
img { img {

View File

@ -5,6 +5,7 @@ import { clsx } from 'clsx'
import { JSX, Show, createSignal } from 'solid-js' import { JSX, Show, createSignal } from 'solid-js'
import { useLocalize } from '../../../context/localize' import { useLocalize } from '../../../context/localize'
import { useSession } from '../../../context/session'
import { UploadedFile } from '../../../pages/types' import { UploadedFile } from '../../../pages/types'
import { handleFileUpload } from '../../../utils/handleFileUpload' import { handleFileUpload } from '../../../utils/handleFileUpload'
import { handleImageUpload } from '../../../utils/handleImageUpload' import { handleImageUpload } from '../../../utils/handleImageUpload'
@ -27,6 +28,7 @@ export const DropArea = (props: Props) => {
const [dragActive, setDragActive] = createSignal(false) const [dragActive, setDragActive] = createSignal(false)
const [dropAreaError, setDropAreaError] = createSignal<string>() const [dropAreaError, setDropAreaError] = createSignal<string>()
const [loading, setLoading] = createSignal(false) const [loading, setLoading] = createSignal(false)
const { session } = useSession()
const runUpload = async (files) => { const runUpload = async (files) => {
try { try {
@ -35,7 +37,7 @@ export const DropArea = (props: Props) => {
const results: UploadedFile[] = [] const results: UploadedFile[] = []
for (const file of files) { for (const file of files) {
const handler = props.fileType === 'image' ? handleImageUpload : handleFileUpload const handler = props.fileType === 'image' ? handleImageUpload : handleFileUpload
const result = await handler(file) const result = await handler(file, session()?.access_token)
results.push(result) results.push(result)
} }
props.onUpload(results) props.onUpload(results)

View File

@ -19,6 +19,7 @@ import { Popover } from '../Popover'
import { SwiperRef } from './swiper' import { SwiperRef } from './swiper'
import { useSession } from '../../../context/session'
import styles from './Swiper.module.scss' import styles from './Swiper.module.scss'
const SimplifiedEditor = lazy(() => import('../../Editor/SimplifiedEditor')) const SimplifiedEditor = lazy(() => import('../../Editor/SimplifiedEditor'))
@ -36,7 +37,7 @@ export const EditorSwiper = (props: Props) => {
const [loading, setLoading] = createSignal(false) const [loading, setLoading] = createSignal(false)
const [slideIndex, setSlideIndex] = createSignal(0) const [slideIndex, setSlideIndex] = createSignal(0)
const [slideBody, setSlideBody] = createSignal<string>() const [slideBody, setSlideBody] = createSignal<string>()
const { session } = useSession()
const mainSwipeRef: { current: SwiperRef } = { current: null } const mainSwipeRef: { current: SwiperRef } = { current: null }
const thumbSwipeRef: { current: SwiperRef } = { current: null } const thumbSwipeRef: { current: SwiperRef } = { current: null }
@ -100,7 +101,7 @@ export const EditorSwiper = (props: Props) => {
setLoading(true) setLoading(true)
const results: UploadedFile[] = [] const results: UploadedFile[] = []
for (const file of selectedFiles) { for (const file of selectedFiles) {
const result = await handleImageUpload(file) const result = await handleImageUpload(file, session()?.access_token)
results.push(result) results.push(result)
} }
props.onImagesAdd(composeMediaItems(results)) props.onImagesAdd(composeMediaItems(results))

View File

@ -5,12 +5,15 @@ import { UploadedFile } from '../pages/types'
const apiBaseUrl = 'https://core.discours.io' const apiBaseUrl = 'https://core.discours.io'
const apiUrl = `${apiBaseUrl}/upload` const apiUrl = `${apiBaseUrl}/upload`
export const handleFileUpload = async (uploadFile: UploadFile): Promise<UploadedFile> => { export const handleFileUpload = async (uploadFile: UploadFile, token: string): Promise<UploadedFile> => {
const formData = new FormData() const formData = new FormData()
formData.append('file', uploadFile.file, uploadFile.name) formData.append('file', uploadFile.file, uploadFile.name)
const response = await fetch(apiUrl, { const response = await fetch(apiUrl, {
method: 'POST', method: 'POST',
body: formData, body: formData,
headers: {
Authorization: token,
},
}) })
return response.json() return response.json()
} }

View File

@ -4,12 +4,14 @@ import { UploadedFile } from '../pages/types'
import { thumborUrl } from './config' import { thumborUrl } from './config'
export const handleImageUpload = async (uploadFile: UploadFile): Promise<UploadedFile> => { export const handleImageUpload = async (uploadFile: UploadFile, token: string): Promise<UploadedFile> => {
const formData = new FormData() const formData = new FormData()
formData.append('media', uploadFile.file, uploadFile.name) formData.append('media', uploadFile.file, uploadFile.name)
const headers = token ? { Authorization: token } : {}
const response = await fetch(`${thumborUrl}/image`, { const response = await fetch(`${thumborUrl}/image`, {
method: 'POST', method: 'POST',
body: formData, body: formData,
headers,
}) })
const location = response.headers.get('Location') const location = response.headers.get('Location')