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

View File

@ -302,8 +302,6 @@
"Topic is supported by": "Topic is supported by", "Topic is supported by": "Topic is supported by",
"Topics": "Topics", "Topics": "Topics",
"Topics which supported by author": "Topics which supported by author", "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", "Try to find another way": "Try to find another way",
"Unfollow": "Unfollow", "Unfollow": "Unfollow",
"Unfollow the topic": "Unfollow the topic", "Unfollow the topic": "Unfollow the topic",

View File

@ -319,8 +319,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 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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,6 +19,7 @@
.confirmModalActions { .confirmModalActions {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-top: 16px; margin-top: 16px;
} }
@ -26,23 +27,26 @@
display: block; display: block;
width: 100%; width: 100%;
margin-right: 12px; margin-right: 12px;
font-weight: 700; font-weight: 700;
margin-top: 32px; margin-top: 32px;
padding: 1.6rem !important; padding: 1.6rem !important;
border: 1px solid black; border: 1px solid black;
&:hover { &:hover {
background-color: rgb(0 0 0 / 8%); background-color: rgba(0, 0, 0, 0.08);
} }
} }
.confirmModalButtonPrimary { .confirmModalButtonPrimary {
margin-right: 0; margin-right: 0;
background-color: black; background-color: black;
color: white; color: white;
border: none; border: none;
&:hover { &: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 { Show, createSignal, createEffect, onMount, onCleanup } from 'solid-js'
import { getPagePath, redirectPage } from '@nanostores/router' import { getPagePath } from '@nanostores/router'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { redirectPage } from '@nanostores/router'
import { Modal } from './Modal' import { Modal } from './Modal'
import { AuthModal } from './AuthModal' import { AuthModal } from './AuthModal'

View File

@ -1,26 +1,28 @@
.TableOfContentsFixedWrapper { .TableOfContentsFixedWrapper {
position: absolute; position: fixed;
top: 0; top: 150px;
right: 0; right: 20px;
width: 281px; width: 281px;
min-height: 100%;
} }
.TableOfContentsFixedWrapperLefted { .TableOfContentsFixedWrapperLefted {
right: auto; right: auto;
left: 70px; left: 20px;
} }
.TableOfContentsContainer { .TableOfContentsContainer {
position: sticky; position: absolute;
top: 150px; right: 0;
right: 20px; top: 0;
display: flex; display: flex;
width: 100%; width: 100%;
height: auto; height: auto;
padding: 20px; padding: 20px;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
background-color: transparent; background-color: transparent;
} }
@ -32,6 +34,7 @@
.TableOfContentsHeading { .TableOfContentsHeading {
margin: 0; margin: 0;
color: #000; color: #000;
font-size: 22px; font-size: 22px;
font-style: normal; font-style: normal;
@ -43,17 +46,20 @@
position: absolute; position: absolute;
right: 20px; right: 20px;
top: 10px; top: 10px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 40px; width: 40px;
height: 40px; height: 40px;
background: transparent; background: transparent;
border: none; border: none;
cursor: pointer; cursor: pointer;
&:hover { &: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 { .TableOfContentsHeadingsList {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
list-style-type: none; list-style-type: none;
margin: 0; margin: 0;
padding: 0 38px 0 0; padding: 0 38px 0 0;
width: 100%;
} }
.TableOfContentsHeadingsItem { .TableOfContentsHeadingsItem {
margin-top: 20px; margin-top: 20px;
color: #000; color: #000;
font-size: 14px; font-size: 14px;
font-style: normal; font-style: normal;
@ -83,7 +91,7 @@
letter-spacing: -0.14px; letter-spacing: -0.14px;
&:hover { &: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 { clsx } from 'clsx'
import { DEFAULT_HEADER_OFFSET } from '../../stores/router' import { DEFAULT_HEADER_OFFSET } from '../../stores/router'
import { useLocalize } from '../../context/localize' import { useLocalize } from '../../context/localize'
import { debounce } from 'debounce'
import { Icon } from '../_shared/Icon' import { Icon } from '../_shared/Icon'
import styles from './TableOfContents.module.scss' import styles from './TableOfContents.module.scss'
@ -14,7 +12,6 @@ import styles from './TableOfContents.module.scss'
interface Props { interface Props {
variant: 'article' | 'editor' variant: 'article' | 'editor'
parentSelector: string parentSelector: string
body: string
} }
const scrollToHeader = (element) => { const scrollToHeader = (element) => {
@ -33,33 +30,21 @@ export const TableOfContents = (props: Props) => {
const [headings, setHeadings] = createSignal<Element[]>([]) const [headings, setHeadings] = createSignal<Element[]>([])
const [areHeadingsLoaded, setAreHeadingsLoaded] = createSignal<boolean>(false) const [areHeadingsLoaded, setAreHeadingsLoaded] = createSignal<boolean>(false)
const [isVisible, setIsVisible] = createSignal<boolean>(props.variant === 'article') const [isVisible, setIsVisible] = createSignal<boolean>(true)
const toggleIsVisible = () => { const toggleIsVisible = () => {
setIsVisible((visible) => !visible) setIsVisible((visible) => !visible)
} }
const updateHeadings = () => { onMount(() => {
const { parentSelector } = props const { parentSelector } = props
// eslint-disable-next-line unicorn/prefer-spread // eslint-disable-next-line unicorn/prefer-spread
setHeadings(Array.from(document.querySelector(parentSelector).querySelectorAll('h2, h3, h4'))) setHeadings(Array.from(document.querySelector(parentSelector).querySelectorAll('h2, h3, h4')))
setAreHeadingsLoaded(true)
}
const debouncedUpdateHeadings = debounce(updateHeadings, 500) setAreHeadingsLoaded(true)
createEffect( })
on(
() => props.body,
() => debouncedUpdateHeadings()
)
)
return ( return (
<Show <Show when={areHeadingsLoaded()}>
when={
areHeadingsLoaded() && (props.variant === 'article' ? headings().length > 2 : headings().length > 1)
}
>
<div <div
class={clsx(styles.TableOfContentsFixedWrapper, { class={clsx(styles.TableOfContentsFixedWrapper, {
[styles.TableOfContentsFixedWrapperLefted]: props.variant === 'editor' [styles.TableOfContentsFixedWrapperLefted]: props.variant === 'editor'

View File

@ -3,11 +3,16 @@ import { useLocalize } from '../../context/localize'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { Title } from '@solidjs/meta' import { Title } from '@solidjs/meta'
import type { Shout, Topic } from '../../graphql/types.gen' import type { Shout, Topic } from '../../graphql/types.gen'
import { apiClient } from '../../utils/apiClient'
import { useRouter } from '../../stores/router' import { useRouter } from '../../stores/router'
import { ShoutForm, useEditorContext } from '../../context/editor' import { ShoutForm, useEditorContext } from '../../context/editor'
import { Editor, Panel } from '../Editor' import { Editor, Panel, TopicSelect, UploadModalContent } from '../Editor'
import { Icon } from '../_shared/Icon' import { Icon } from '../_shared/Icon'
import { Button } from '../_shared/Button'
import styles from './Edit.module.scss' 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 { imageProxy } from '../../utils/imageProxy'
import { GrowingTextarea } from '../_shared/GrowingTextarea' import { GrowingTextarea } from '../_shared/GrowingTextarea'
import { VideoUploader } from '../Editor/VideoUploader' import { VideoUploader } from '../Editor/VideoUploader'
@ -20,7 +25,6 @@ import { clone } from '../../utils/clone'
import deepEqual from 'fast-deep-equal' import deepEqual from 'fast-deep-equal'
import { AutoSaveNotice } from '../Editor/AutoSaveNotice' import { AutoSaveNotice } from '../Editor/AutoSaveNotice'
import { PublishSettings } from './PublishSettings' import { PublishSettings } from './PublishSettings'
import { createStore } from 'solid-js/store'
type Props = { type Props = {
shout: Shout 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 [saving, setSaving] = createSignal(false)
const mediaItems: Accessor<MediaItem[]> = createMemo(() => { 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) => { const handleTitleInputChange = (value) => {
setForm('title', value) setForm('title', value)
setForm('slug', slugify(value)) setForm('slug', slugify(value))
@ -184,7 +174,7 @@ export const EditView = (props: Props) => {
const autoSaveRecursive = () => { const autoSaveRecursive = () => {
autoSaveTimeOutId = setTimeout(async () => { autoSaveTimeOutId = setTimeout(async () => {
const hasChanges = !deepEqual(form, prevForm) const hasChanges = !deepEqual(form, prevForm())
if (hasChanges) { if (hasChanges) {
setSaving(true) setSaving(true)
if (props.shout.visibility === 'owner') { if (props.shout.visibility === 'owner') {

View File

@ -1,6 +1,6 @@
import { clsx } from 'clsx' import { clsx } from 'clsx'
import styles from './PublishSettings.module.scss' 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 { TopicSelect, UploadModalContent } from '../../Editor'
import { Button } from '../../_shared/Button' import { Button } from '../../_shared/Button'
import { hideModal, showModal } from '../../../stores/ui' import { hideModal, showModal } from '../../../stores/ui'

View File

@ -1,6 +1,7 @@
import { clsx } from 'clsx' import { clsx } from 'clsx'
import styles from './GrowingTextarea.module.scss' 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 = { type Props = {
class?: string 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 }) => { export const EditorProvider = (props: { children: JSX.Element }) => {
const { t } = useLocalize() const { t } = useLocalize()
@ -175,6 +164,17 @@ export const EditorProvider = (props: { children: JSX.Element }) => {
await updateShout(draftForm, { publish: false }) 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) => { const publishShout = async (formToPublish: ShoutForm) => {
if (isEditorPanelVisible()) { if (isEditorPanelVisible()) {
toggleEditorPanel() toggleEditorPanel()

View File

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

View File

@ -1,8 +1,7 @@
import { PageLayout } from '../../components/_shared/PageLayout' import { PageLayout } from '../../components/_shared/PageLayout'
import { Icon } from '../../components/_shared/Icon' import { Icon } from '../../components/_shared/Icon'
import ProfileSettingsNavigation from '../../components/Discours/ProfileSettingsNavigation' import ProfileSettingsNavigation from '../../components/Discours/ProfileSettingsNavigation'
import { For, createSignal, Show, onMount, onCleanup } from 'solid-js' import { For, createSignal, Show, onMount } from 'solid-js'
import deepEqual from 'fast-deep-equal'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import styles from './Settings.module.scss' import styles from './Settings.module.scss'
import { useProfileForm } from '../../context/profile' import { useProfileForm } from '../../context/profile'
@ -14,8 +13,6 @@ import { useSnackbar } from '../../context/snackbar'
import { useLocalize } from '../../context/localize' import { useLocalize } from '../../context/localize'
import { handleFileUpload } from '../../utils/handleFileUpload' import { handleFileUpload } from '../../utils/handleFileUpload'
import { Userpic } from '../../components/Author/Userpic' import { Userpic } from '../../components/Author/Userpic'
import { createStore } from 'solid-js/store'
import { clone } from '../../utils/clone'
export const ProfileSettingsPage = () => { export const ProfileSettingsPage = () => {
const { t } = useLocalize() const { t } = useLocalize()
@ -32,7 +29,6 @@ export const ProfileSettingsPage = () => {
actions: { loadSession } actions: { loadSession }
} = useSession() } = useSession()
const { form, updateFormField, submit, slugError } = useProfileForm() const { form, updateFormField, submit, slugError } = useProfileForm()
const [prevForm, setPrevForm] = createStore(clone(form))
const handleChangeSocial = (value: string) => { const handleChangeSocial = (value: string) => {
if (validateUrl(value)) { if (validateUrl(value)) {
@ -49,7 +45,6 @@ export const ProfileSettingsPage = () => {
try { try {
await submit(form) await submit(form)
setPrevForm(clone(form))
showSnackbar({ body: t('Profile successfully saved') }) showSnackbar({ body: t('Profile successfully saved') })
} catch { } catch {
showSnackbar({ type: 'error', body: t('Error') }) showSnackbar({ type: 'error', body: t('Error') })
@ -75,23 +70,9 @@ export const ProfileSettingsPage = () => {
} }
const [hostname, setHostname] = createSignal<string | null>(null) const [hostname, setHostname] = createSignal<string | null>(null)
onMount(() => setHostname(window?.location.host))
onMount(() => { console.log('!!! form:', form)
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))
})
return ( return (
<PageLayout> <PageLayout>
<Show when={form}> <Show when={form}>