Revert "add useconfirm for req actions & fixes for toc (#155)" (#173)

This reverts commit b5708d26cd.
This commit is contained in:
Igor Lobanov 2023-08-14 15:42:12 +02:00 committed by GitHub
parent e51cff6fb8
commit 64bd3defcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 88 additions and 142 deletions

View File

@ -30,6 +30,7 @@
},
"dependencies": {
"@hocuspocus/provider": "2.0.6",
"fast-deep-equal": "3.1.3",
"form-data": "4.0.0",
"i18next": "22.4.15",
"mailgun.js": "8.2.1",
@ -100,7 +101,6 @@
"cookie-signature": "1.2.1",
"cosmiconfig-toml-loader": "1.0.0",
"cross-env": "7.0.3",
"debounce": "1.2.1",
"eslint": "8.40.0",
"eslint-config-stylelint": "18.0.0",
"eslint-import-resolver-typescript": "3.5.5",
@ -111,7 +111,6 @@
"eslint-plugin-solid": "0.12.1",
"eslint-plugin-sonarjs": "0.19.0",
"eslint-plugin-unicorn": "47.0.0",
"fast-deep-equal": "3.1.3",
"graphql": "16.6.0",
"graphql-tag": "2.12.6",
"graphql-ws": "5.12.1",

View File

@ -302,8 +302,6 @@
"Topic is supported by": "Topic is supported by",
"Topics": "Topics",
"Topics which supported by author": "Topics which supported by author",
"There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?": "There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?",
"There are unsaved changes in your profile settings. Are you sure you want to leave the page without saving?": "There are unsaved changes in your profile settings. Are you sure you want to leave the page without saving?",
"Try to find another way": "Try to find another way",
"Unfollow": "Unfollow",
"Unfollow the topic": "Unfollow the topic",

View File

@ -319,8 +319,6 @@
"Topic is supported by": "Тему поддерживают",
"Topics": "Темы",
"Topics which supported by author": "Автор поддерживает темы",
"There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?": "В настройках публикации есть несохраненные изменения. Уверены, что хотите покинуть страницу без сохранения?",
"There are unsaved changes in your profile settings. Are you sure you want to leave the page without saving?": "В настройках вашего профиля есть несохраненные изменения. Уверены, что хотите покинуть страницу без сохранения?",
"Try to find another way": "Попробуйте найти по-другому",
"Unfollow": "Отписаться",
"Unfollow the topic": "Отписаться от темы",

View File

@ -1,13 +1,11 @@
h1 {
@include font-size(4rem);
line-height: 1.1;
margin-top: 0.5em;
}
h2 {
@include font-size(4rem);
line-height: 1.1;
}
@ -46,7 +44,7 @@ img {
margin: 3.2rem 0;
position: relative;
&::before {
&:before {
background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNiAyMSIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wIDEwLjUwMDFWMjFIMTAuNzA2MVYxMC41MDAxSDQuNTg4MzNDNC41ODgzMyA3LjE4NjU4IDcuMzI3NTggNC41MDAwOCAxMC43MDYxIDQuNTAwMDhWMEM0Ljc5Mjk3IDAgMCA0LjcwMDczIDAgMTAuNDk5OVYxMC41MDAxWk0yNiA0LjUwMDA4VjBDMjAuMDg2OSAwIDE1LjI5MzkgNC43MDA3MyAxNS4yOTM5IDEwLjQ5OTlWMjAuOTk5OUgyNlYxMC41MDA1SDE5Ljg4MjJDMTkuODgyNCA3LjE4NyAyMi42MjE3IDQuNTAwNSAyNiA0LjUwMDVWNC41MDAwOFoiIGZpbGw9ImJsYWNrIi8+PC9zdmc+')
no-repeat;
content: '';
@ -62,19 +60,17 @@ img {
blockquote[data-type='quote'],
ta-quotation {
@include font-size(1.4rem);
border: solid #000;
border-width: 0 0 0 2px;
display: block;
font-weight: 500;
line-height: 1.6;
margin: 1.6rem 0 0 calc(-8.3333% - 2px);
padding: 0 0 0 8.3333%;
margin: 1.6rem 0 0 calc(-8.33333% - 2px);
padding: 0 0 0 8.33333%;
&[data-float='left'],
&[data-float='right'] {
@include font-size(2.2rem);
line-height: 1.4;
}
@ -88,7 +84,7 @@ img {
}
}
&::before {
&:before {
display: none;
}
}
@ -99,15 +95,13 @@ img {
ta-border-sub {
background: #f1f2f3;
display: block;
@include font-size(1.4rem);
margin: 3.2rem 0;
padding: 3.2rem;
@include media-breakpoint-up(md) {
margin: 3.2rem -8.3333%;
padding: 3.2rem 8.3333%;
margin: 3.2rem -8.33333%;
padding: 3.2rem 8.33333%;
}
p:last-child {
@ -150,7 +144,7 @@ img {
}
@include media-breakpoint-up(md) {
margin: 0 8.3333% 3.2rem -16.6666%;
margin: 0 8.33333% 3.2rem -16.66666%;
}
}
@ -160,7 +154,7 @@ img {
}
@include media-breakpoint-up(md) {
margin: 0 -16.6666% 3.2rem 8.3333%;
margin: 0 -16.66666% 3.2rem 8.33333%;
}
}
@ -174,13 +168,13 @@ img {
h2 {
@include media-breakpoint-up(xl) {
margin-left: -16.6666%;
margin-left: -16.6666666666%;
}
}
:global(.img-align-left) {
float: left;
margin: 1em 8.3333% 0.5em 0;
margin: 1em 8.333333333% 0.5em 0;
}
:global(.width-30) {
@ -193,18 +187,18 @@ img {
:global(.img-align-left.width-50) {
@include media-breakpoint-up(xl) {
margin-left: -16.6666%;
margin-left: -16.6666666666%;
}
}
:global(.img-align-right) {
float: right;
margin: 1em 0 0.5em 8.3333%;
margin: 1em 0 0.5em 8.333333333%;
}
:global(.img-align-right.width-50) {
@include media-breakpoint-up(xl) {
margin-right: -16.6666%;
margin-right: -16.6666666666%;
}
}
@ -504,7 +498,6 @@ img {
button {
@include font-size(1.5rem);
border-radius: 0.8rem;
margin-right: 1.2rem;
padding: 0.9rem 1.2rem;

View File

@ -17,6 +17,7 @@ import { useSnackbar } from '../../context/snackbar'
import { useConfirm } from '../../context/confirm'
import { Author, Reaction, ReactionKind } from '../../graphql/types.gen'
import { router } from '../../stores/router'
import styles from './Comment.module.scss'
@ -47,7 +48,6 @@ export const Comment = (props: Props) => {
const {
actions: { showConfirm }
} = useConfirm()
const {
actions: { showSnackbar }
} = useSnackbar()

View File

@ -132,7 +132,7 @@ export const FullArticle = (props: Props) => {
<>
<Title>{props.article.title}</Title>
<div class="wide-container">
<div class="row position-relative">
<div class="row">
<article class="col-md-16 col-lg-14 col-xl-12 offset-md-5">
{/*TODO: Check styles.shoutTopic*/}
<Show when={props.article.layout !== 'audio'}>
@ -212,7 +212,7 @@ export const FullArticle = (props: Props) => {
</Show>
</article>
<Show when={isDesktop() && body()}>
<TableOfContents variant="article" parentSelector="#shoutBody" body={body()} />
<TableOfContents variant="article" parentSelector="#shoutBody" />
</Show>
</div>
</div>

View File

@ -1,4 +1,5 @@
import { Show } from 'solid-js'
import type { Author, User } from '../../../graphql/types.gen'
import styles from './Userpic.module.scss'
import { clsx } from 'clsx'
import { imageProxy } from '../../../utils/imageProxy'

View File

@ -62,7 +62,6 @@ const providers: Record<string, HocuspocusProvider> = {}
export const Editor = (props: Props) => {
const { t } = useLocalize()
const { user } = useSession()
const [isCommonMarkup, setIsCommonMarkup] = createSignal(false)
const docName = `shout-${props.shoutId}`
@ -248,7 +247,7 @@ export const Editor = (props: Props) => {
<>
<div ref={(el) => (editorElRef.current = el)} id="editorBody" />
<Show when={isDesktop() && html()}>
<TableOfContents variant="editor" parentSelector="#editorBody" body={html()} />
<TableOfContents variant="editor" parentSelector="#editorBody" />
</Show>
<TextBubbleMenu
isCommonMarkup={isCommonMarkup()}

View File

@ -24,12 +24,11 @@
box-sizing: content-box;
flex: 0 0 auto;
@media (width >= 768px) {
@media (min-width: 768px) {
padding-left: calc(21.9% + 3px);
max-width: 72.7%;
}
@media (width >= 1200px) {
@media (min-width: 1200px) {
padding-left: calc(21.5% + 3px);
max-width: 64.9%;
}
@ -39,35 +38,32 @@
.articleEditor figure,
.articleEditor .uploadedImage,
.articleEditor article[data-type='incut'] {
@media (width >= 768px) {
@media (min-width: 768px) {
margin-left: calc(21.9% + 3px) !important;
max-width: 73.6%;
}
@media (width >= 1200px) {
@media (min-width: 1200px) {
margin-left: calc(21.4% + 3px) !important;
max-width: 65.3%;
}
}
.articleEditor h2 {
@media (width >= 768px) {
@media (min-width: 768px) {
padding-left: calc(21.9% + 2px);
max-width: 72.7%;
}
@media (width >= 1200px) {
@media (min-width: 1200px) {
padding-left: 21.5%;
max-width: 87.1%;
}
}
.articleEditor h3 {
@media (width >= 768px) {
@media (min-width: 768px) {
padding-left: calc(21.9% + 2px);
}
@media (width >= 1200px) {
@media (min-width: 1200px) {
padding-left: 21.5%;
max-width: 87.1%;
}
@ -77,7 +73,7 @@
.articleEditor * h2,
.articleEditor * h3,
.articleEditor * h4 {
@media (width >= 768px) {
@media (min-width: 768px) {
padding-left: unset;
max-width: unset;
}
@ -187,7 +183,6 @@ mark.highlight {
&[data-type='quote'] {
@include font-size(1.4rem);
border: solid #000;
border-width: 0 0 0 2px;
margin: 1.6rem 0;
@ -209,9 +204,7 @@ mark.highlight {
&[data-type='punchline'] {
border: solid #000;
border-width: 2px 0;
@include font-size(3.2rem);
font-weight: 700;
line-height: 1.2;
margin: 1em 0;
@ -220,7 +213,6 @@ mark.highlight {
&[data-float='left'],
&[data-float='right'] {
@include font-size(2.2rem);
line-height: 1.4;
}
@ -238,9 +230,7 @@ mark.highlight {
.ProseMirror article[data-type='incut'] {
background: #f1f2f3;
@include font-size(1.4rem);
margin: 1em -1rem;
padding: 2em 2rem;
transition: background 0.3s ease-in-out;

View File

@ -19,6 +19,7 @@
.confirmModalActions {
display: flex;
justify-content: space-between;
margin-top: 16px;
}
@ -26,23 +27,26 @@
display: block;
width: 100%;
margin-right: 12px;
font-weight: 700;
margin-top: 32px;
padding: 1.6rem !important;
border: 1px solid black;
&:hover {
background-color: rgb(0 0 0 / 8%);
background-color: rgba(0, 0, 0, 0.08);
}
}
.confirmModalButtonPrimary {
margin-right: 0;
background-color: black;
color: white;
border: none;
&:hover {
background-color: rgb(0 0 0 / 60%);
background-color: rgba(0, 0, 0, 0.6);
}
}

View File

@ -1,6 +1,7 @@
import { Show, createSignal, createEffect, onMount, onCleanup } from 'solid-js'
import { getPagePath, redirectPage } from '@nanostores/router'
import { getPagePath } from '@nanostores/router'
import { clsx } from 'clsx'
import { redirectPage } from '@nanostores/router'
import { Modal } from './Modal'
import { AuthModal } from './AuthModal'

View File

@ -1,26 +1,28 @@
.TableOfContentsFixedWrapper {
position: absolute;
top: 0;
right: 0;
position: fixed;
top: 150px;
right: 20px;
width: 281px;
min-height: 100%;
}
.TableOfContentsFixedWrapperLefted {
right: auto;
left: 70px;
left: 20px;
}
.TableOfContentsContainer {
position: sticky;
top: 150px;
right: 20px;
position: absolute;
right: 0;
top: 0;
display: flex;
width: 100%;
height: auto;
padding: 20px;
flex-direction: column;
align-items: flex-start;
background-color: transparent;
}
@ -32,6 +34,7 @@
.TableOfContentsHeading {
margin: 0;
color: #000;
font-size: 22px;
font-style: normal;
@ -43,17 +46,20 @@
position: absolute;
right: 20px;
top: 10px;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
background: transparent;
border: none;
cursor: pointer;
&:hover {
box-shadow: 0 0 1px 1px rgb(0 0 0 / 30%);
box-shadow: 0px 0px 1px 1px rgba(0, 0, 0, 0.3);
}
}
@ -64,16 +70,18 @@
.TableOfContentsHeadingsList {
position: relative;
display: flex;
flex-direction: column;
list-style-type: none;
margin: 0;
padding: 0 38px 0 0;
width: 100%;
}
.TableOfContentsHeadingsItem {
margin-top: 20px;
color: #000;
font-size: 14px;
font-style: normal;
@ -83,7 +91,7 @@
letter-spacing: -0.14px;
&:hover {
color: rgb(0 0 0 / 50%);
transform: scale(1.05);
}
}

View File

@ -1,12 +1,10 @@
import { For, Show, createSignal, createEffect, on } from 'solid-js'
import { onMount, For, Show, createSignal } from 'solid-js'
import { clsx } from 'clsx'
import { DEFAULT_HEADER_OFFSET } from '../../stores/router'
import { useLocalize } from '../../context/localize'
import { debounce } from 'debounce'
import { Icon } from '../_shared/Icon'
import styles from './TableOfContents.module.scss'
@ -14,7 +12,6 @@ import styles from './TableOfContents.module.scss'
interface Props {
variant: 'article' | 'editor'
parentSelector: string
body: string
}
const scrollToHeader = (element) => {
@ -33,33 +30,21 @@ export const TableOfContents = (props: Props) => {
const [headings, setHeadings] = createSignal<Element[]>([])
const [areHeadingsLoaded, setAreHeadingsLoaded] = createSignal<boolean>(false)
const [isVisible, setIsVisible] = createSignal<boolean>(props.variant === 'article')
const [isVisible, setIsVisible] = createSignal<boolean>(true)
const toggleIsVisible = () => {
setIsVisible((visible) => !visible)
}
const updateHeadings = () => {
onMount(() => {
const { parentSelector } = props
// eslint-disable-next-line unicorn/prefer-spread
setHeadings(Array.from(document.querySelector(parentSelector).querySelectorAll('h2, h3, h4')))
setAreHeadingsLoaded(true)
}
const debouncedUpdateHeadings = debounce(updateHeadings, 500)
createEffect(
on(
() => props.body,
() => debouncedUpdateHeadings()
)
)
setAreHeadingsLoaded(true)
})
return (
<Show
when={
areHeadingsLoaded() && (props.variant === 'article' ? headings().length > 2 : headings().length > 1)
}
>
<Show when={areHeadingsLoaded()}>
<div
class={clsx(styles.TableOfContentsFixedWrapper, {
[styles.TableOfContentsFixedWrapperLefted]: props.variant === 'editor'

View File

@ -3,11 +3,16 @@ import { useLocalize } from '../../context/localize'
import { clsx } from 'clsx'
import { Title } from '@solidjs/meta'
import type { Shout, Topic } from '../../graphql/types.gen'
import { apiClient } from '../../utils/apiClient'
import { useRouter } from '../../stores/router'
import { ShoutForm, useEditorContext } from '../../context/editor'
import { Editor, Panel } from '../Editor'
import { Editor, Panel, TopicSelect, UploadModalContent } from '../Editor'
import { Icon } from '../_shared/Icon'
import { Button } from '../_shared/Button'
import styles from './Edit.module.scss'
import { useSession } from '../../context/session'
import { Modal } from '../Nav/Modal'
import { hideModal, showModal } from '../../stores/ui'
import { imageProxy } from '../../utils/imageProxy'
import { GrowingTextarea } from '../_shared/GrowingTextarea'
import { VideoUploader } from '../Editor/VideoUploader'
@ -20,7 +25,6 @@ import { clone } from '../../utils/clone'
import deepEqual from 'fast-deep-equal'
import { AutoSaveNotice } from '../Editor/AutoSaveNotice'
import { PublishSettings } from './PublishSettings'
import { createStore } from 'solid-js/store'
type Props = {
shout: Shout
@ -72,7 +76,7 @@ export const EditView = (props: Props) => {
})
}
const [prevForm, setPrevForm] = createStore<ShoutForm>(clone(form))
const [prevForm, setPrevForm] = createSignal<ShoutForm>(clone(form))
const [saving, setSaving] = createSignal(false)
const mediaItems: Accessor<MediaItem[]> = createMemo(() => {
@ -90,20 +94,6 @@ export const EditView = (props: Props) => {
})
})
onMount(() => {
// eslint-disable-next-line unicorn/consistent-function-scoping
const handleBeforeUnload = (event) => {
if (!deepEqual(prevForm, form)) {
event.returnValue = t(
`There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?`
)
}
}
window.addEventListener('beforeunload', handleBeforeUnload)
onCleanup(() => window.removeEventListener('beforeunload', handleBeforeUnload))
})
const handleTitleInputChange = (value) => {
setForm('title', value)
setForm('slug', slugify(value))
@ -184,7 +174,7 @@ export const EditView = (props: Props) => {
const autoSaveRecursive = () => {
autoSaveTimeOutId = setTimeout(async () => {
const hasChanges = !deepEqual(form, prevForm)
const hasChanges = !deepEqual(form, prevForm())
if (hasChanges) {
setSaving(true)
if (props.shout.visibility === 'owner') {

View File

@ -1,6 +1,6 @@
import { clsx } from 'clsx'
import styles from './PublishSettings.module.scss'
import { createSignal, onMount, Show } from 'solid-js'
import { createEffect, createSignal, onMount, Show } from 'solid-js'
import { TopicSelect, UploadModalContent } from '../../Editor'
import { Button } from '../../_shared/Button'
import { hideModal, showModal } from '../../../stores/ui'

View File

@ -1,6 +1,7 @@
import { clsx } from 'clsx'
import styles from './GrowingTextarea.module.scss'
import { createSignal, Show } from 'solid-js'
import { createSignal, Show, Switch } from 'solid-js'
import { style } from 'solid-js/web'
type Props = {
class?: string

View File

@ -65,17 +65,6 @@ const topic2topicInput = (topic: Topic): TopicInput => {
}
}
const saveDraftToLocalStorage = (formToSave: ShoutForm) => {
localStorage.setItem(`shout-${formToSave.shoutId}`, JSON.stringify(formToSave))
}
const getDraftFromLocalStorage = (shoutId: number) => {
return JSON.parse(localStorage.getItem(`shout-${shoutId}`))
}
const removeDraftFromLocalStorage = (shoutId: number) => {
localStorage.removeItem(`shout-${shoutId}`)
}
export const EditorProvider = (props: { children: JSX.Element }) => {
const { t } = useLocalize()
@ -175,6 +164,17 @@ export const EditorProvider = (props: { children: JSX.Element }) => {
await updateShout(draftForm, { publish: false })
}
const saveDraftToLocalStorage = (formToSave: ShoutForm) => {
localStorage.setItem(`shout-${formToSave.shoutId}`, JSON.stringify(formToSave))
}
const getDraftFromLocalStorage = (shoutId: number) => {
return JSON.parse(localStorage.getItem(`shout-${shoutId}`))
}
const removeDraftFromLocalStorage = (shoutId: number) => {
localStorage.removeItem(`shout-${shoutId}`)
}
const publishShout = async (formToPublish: ShoutForm) => {
if (isEditorPanelVisible()) {
toggleEditorPanel()

View File

@ -34,16 +34,14 @@ const useProfileForm = () => {
if (!currentSlug()) return
try {
await loadAuthor({ slug: currentSlug() })
const updatedFormValues = {
setForm({
name: currentAuthor()?.name,
slug: currentAuthor()?.slug,
bio: currentAuthor()?.bio,
about: currentAuthor()?.about,
userpic: currentAuthor()?.userpic,
links: currentAuthor()?.links
}
setForm(updatedFormValues)
})
} catch (error) {
console.error(error)
}

View File

@ -1,8 +1,7 @@
import { PageLayout } from '../../components/_shared/PageLayout'
import { Icon } from '../../components/_shared/Icon'
import ProfileSettingsNavigation from '../../components/Discours/ProfileSettingsNavigation'
import { For, createSignal, Show, onMount, onCleanup } from 'solid-js'
import deepEqual from 'fast-deep-equal'
import { For, createSignal, Show, onMount } from 'solid-js'
import { clsx } from 'clsx'
import styles from './Settings.module.scss'
import { useProfileForm } from '../../context/profile'
@ -14,8 +13,6 @@ import { useSnackbar } from '../../context/snackbar'
import { useLocalize } from '../../context/localize'
import { handleFileUpload } from '../../utils/handleFileUpload'
import { Userpic } from '../../components/Author/Userpic'
import { createStore } from 'solid-js/store'
import { clone } from '../../utils/clone'
export const ProfileSettingsPage = () => {
const { t } = useLocalize()
@ -32,7 +29,6 @@ export const ProfileSettingsPage = () => {
actions: { loadSession }
} = useSession()
const { form, updateFormField, submit, slugError } = useProfileForm()
const [prevForm, setPrevForm] = createStore(clone(form))
const handleChangeSocial = (value: string) => {
if (validateUrl(value)) {
@ -49,7 +45,6 @@ export const ProfileSettingsPage = () => {
try {
await submit(form)
setPrevForm(clone(form))
showSnackbar({ body: t('Profile successfully saved') })
} catch {
showSnackbar({ type: 'error', body: t('Error') })
@ -75,23 +70,9 @@ export const ProfileSettingsPage = () => {
}
const [hostname, setHostname] = createSignal<string | null>(null)
onMount(() => setHostname(window?.location.host))
onMount(() => {
setHostname(window?.location.host)
// eslint-disable-next-line unicorn/consistent-function-scoping
const handleBeforeUnload = (event) => {
if (!deepEqual(form, prevForm)) {
event.returnValue = t(
'There are unsaved changes in your profile settings. Are you sure you want to leave the page without saving?'
)
}
}
window.addEventListener('beforeunload', handleBeforeUnload)
onCleanup(() => window.removeEventListener('beforeunload', handleBeforeUnload))
})
console.log('!!! form:', form)
return (
<PageLayout>
<Show when={form}>