Merge pull request #40 from Discours/popup
common Popup component & SharePopup
This commit is contained in:
commit
897afd6d06
|
@ -1,6 +1,3 @@
|
||||||
{
|
{
|
||||||
"*.{js,ts,tsx,json,scss,css,html}": "prettier --write",
|
"*.{js,ts,tsx,json,scss,css,html}": "prettier --write"
|
||||||
"package.json": "sort-package-json",
|
|
||||||
"*.{scss,css}": "stylelint",
|
|
||||||
"*.{ts,tsx,js}": "eslint --fix"
|
|
||||||
}
|
}
|
||||||
|
|
6
.lintstagedrc.bak
Normal file
6
.lintstagedrc.bak
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"*.{js,ts,tsx,json,scss,css,html}": "prettier --write",
|
||||||
|
"package.json": "sort-package-json",
|
||||||
|
"*.{scss,css}": "stylelint",
|
||||||
|
"*.{ts,tsx,js}": "eslint --fix"
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
"lint:code:fix": "eslint . --fix",
|
"lint:code:fix": "eslint . --fix",
|
||||||
"lint:styles": "stylelint **/*.{scss,css}",
|
"lint:styles": "stylelint **/*.{scss,css}",
|
||||||
"lint:styles:fix": "stylelint **/*.{scss,css} --fix",
|
"lint:styles:fix": "stylelint **/*.{scss,css} --fix",
|
||||||
"pre-commit": "",
|
"pre-commit": "lint-staged",
|
||||||
"pre-push": "",
|
"pre-push": "",
|
||||||
"pre-commit-old": "lint-staged",
|
"pre-commit-old": "lint-staged",
|
||||||
"pre-push-old": "npm run typecheck",
|
"pre-push-old": "npm run typecheck",
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { showModal } from '../../stores/ui'
|
||||||
import { useAuthStore } from '../../stores/auth'
|
import { useAuthStore } from '../../stores/auth'
|
||||||
import { incrementView } from '../../stores/zine/articles'
|
import { incrementView } from '../../stores/zine/articles'
|
||||||
import MD from './MD'
|
import MD from './MD'
|
||||||
|
import { SharePopup } from './SharePopup'
|
||||||
|
|
||||||
const MAX_COMMENT_LEVEL = 6
|
const MAX_COMMENT_LEVEL = 6
|
||||||
|
|
||||||
|
@ -126,9 +127,13 @@ export const FullArticle = (props: ArticleProps) => {
|
||||||
{/* </a>*/}
|
{/* </a>*/}
|
||||||
{/*</div>*/}
|
{/*</div>*/}
|
||||||
<div class="shout-stats__item">
|
<div class="shout-stats__item">
|
||||||
<a href="#share" onClick={() => showModal('share')}>
|
<SharePopup
|
||||||
<Icon name="share" />
|
trigger={
|
||||||
</a>
|
<a href="#" onClick={(event) => event.preventDefault()}>
|
||||||
|
<Icon name="share" />
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/*FIXME*/}
|
{/*FIXME*/}
|
||||||
{/*<Show when={canEdit()}>*/}
|
{/*<Show when={canEdit()}>*/}
|
||||||
|
|
45
src/components/Article/SharePopup.tsx
Normal file
45
src/components/Article/SharePopup.tsx
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import { Icon } from '../Nav/Icon'
|
||||||
|
import styles from '../Nav/Popup.module.scss'
|
||||||
|
import { t } from '../../utils/intl'
|
||||||
|
import { Popup, PopupProps } from '../Nav/Popup'
|
||||||
|
|
||||||
|
type SharePopupProps = Omit<PopupProps, 'children'>
|
||||||
|
|
||||||
|
export const SharePopup = (props: SharePopupProps) => {
|
||||||
|
return (
|
||||||
|
<Popup {...props}>
|
||||||
|
<ul class="nodash">
|
||||||
|
<li>
|
||||||
|
<a href="#">
|
||||||
|
<Icon name="vk-white" class={styles.icon} />
|
||||||
|
VK
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#">
|
||||||
|
<Icon name="facebook-white" class={styles.icon} />
|
||||||
|
Facebook
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#">
|
||||||
|
<Icon name="twitter-white" class={styles.icon} />
|
||||||
|
Twitter
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#">
|
||||||
|
<Icon name="telegram-white" class={styles.icon} />
|
||||||
|
Telegram
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#">
|
||||||
|
<Icon name="link-white" class={styles.icon} />
|
||||||
|
{t('Copy link')}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</Popup>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import styles from './Banner.module.scss'
|
import styles from './Banner.module.scss'
|
||||||
import { t } from '../../utils/intl'
|
import { t } from '../../utils/intl'
|
||||||
import { showModal } from '../../stores/ui'
|
import { showModal } from '../../stores/ui'
|
||||||
import {clsx} from "clsx";
|
import { clsx } from 'clsx'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Icon } from '../Nav/Icon'
|
||||||
import Subscribe from './Subscribe'
|
import Subscribe from './Subscribe'
|
||||||
import { t } from '../../utils/intl'
|
import { t } from '../../utils/intl'
|
||||||
import { locale } from '../../stores/ui'
|
import { locale } from '../../stores/ui'
|
||||||
import {clsx} from "clsx";
|
import { clsx } from 'clsx'
|
||||||
|
|
||||||
export const Footer = () => {
|
export const Footer = () => {
|
||||||
const locale_title = createMemo(() => (locale() === 'ru' ? 'English' : 'Русский'))
|
const locale_title = createMemo(() => (locale() === 'ru' ? 'English' : 'Русский'))
|
||||||
|
|
|
@ -7,7 +7,7 @@ export default (props: { article: Shout }) => (
|
||||||
<div class="floor floor--one-article">
|
<div class="floor floor--one-article">
|
||||||
<div class="wide-container row">
|
<div class="wide-container row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<ArticleCard article={props.article} settings={{isSingle: true}} />
|
<ArticleCard article={props.article} settings={{ isSingle: true }} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -35,18 +35,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.popupShare {
|
|
||||||
opacity: 1;
|
|
||||||
transition: opacity 0.3s;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
.headerScrolledTop & {
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s, z-index 0s 0.3s;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerFixed {
|
.headerFixed {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -348,18 +336,15 @@
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.icon {
|
.control {
|
||||||
|
cursor: pointer;
|
||||||
margin-left: 1.6rem;
|
margin-left: 1.6rem;
|
||||||
opacity: 0.6;
|
border: 0;
|
||||||
transition: opacity 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
.icon {
|
||||||
vertical-align: middle;
|
opacity: 0.6;
|
||||||
}
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
a {
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: none;
|
background: none;
|
||||||
|
@ -370,4 +355,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,17 @@ import Private from './Private'
|
||||||
import Notifications from './Notifications'
|
import Notifications from './Notifications'
|
||||||
import { Icon } from './Icon'
|
import { Icon } from './Icon'
|
||||||
import { Modal } from './Modal'
|
import { Modal } from './Modal'
|
||||||
import { Popup } from './Popup'
|
|
||||||
import AuthModal from './AuthModal'
|
import AuthModal from './AuthModal'
|
||||||
import { t } from '../../utils/intl'
|
import { t } from '../../utils/intl'
|
||||||
import {useModalStore, showModal, useWarningsStore, toggleModal} from '../../stores/ui'
|
import { useModalStore, showModal, useWarningsStore } from '../../stores/ui'
|
||||||
import { useAuthStore } from '../../stores/auth'
|
import { useAuthStore } from '../../stores/auth'
|
||||||
import { handleClientRouteLinkClick, router, Routes, useRouter } from '../../stores/router'
|
import { handleClientRouteLinkClick, router, Routes, useRouter } from '../../stores/router'
|
||||||
import styles from './Header.module.scss'
|
import styles from './Header.module.scss'
|
||||||
import stylesPopup from './Popup.module.scss'
|
|
||||||
import privateStyles from './Private.module.scss'
|
import privateStyles from './Private.module.scss'
|
||||||
import { getPagePath } from '@nanostores/router'
|
import { getPagePath } from '@nanostores/router'
|
||||||
import { getLogger } from '../../utils/logger'
|
import { getLogger } from '../../utils/logger'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
|
import { SharePopup } from '../Article/SharePopup'
|
||||||
|
|
||||||
const log = getLogger('header')
|
const log = getLogger('header')
|
||||||
|
|
||||||
|
@ -39,6 +38,7 @@ export const Header = (props: Props) => {
|
||||||
const [getIsScrolled, setIsScrolled] = createSignal(false)
|
const [getIsScrolled, setIsScrolled] = createSignal(false)
|
||||||
const [fixed, setFixed] = createSignal(false)
|
const [fixed, setFixed] = createSignal(false)
|
||||||
const [visibleWarnings, setVisibleWarnings] = createSignal(false)
|
const [visibleWarnings, setVisibleWarnings] = createSignal(false)
|
||||||
|
const [isSharePopupVisible, setIsSharePopupVisible] = createSignal(false)
|
||||||
// stores
|
// stores
|
||||||
const { getWarnings } = useWarningsStore()
|
const { getWarnings } = useWarningsStore()
|
||||||
const { session } = useAuthStore()
|
const { session } = useAuthStore()
|
||||||
|
@ -48,14 +48,11 @@ export const Header = (props: Props) => {
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
const toggleWarnings = () => setVisibleWarnings(!visibleWarnings())
|
const toggleWarnings = () => setVisibleWarnings(!visibleWarnings())
|
||||||
const toggleFixed = () => setFixed(!fixed())
|
const toggleFixed = () => setFixed((oldFixed) => !oldFixed)
|
||||||
// effects
|
// effects
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const isFixed = fixed() || (getModal() && getModal() !== 'share');
|
document.body.classList.toggle('fixed', fixed() || getModal() !== null)
|
||||||
|
})
|
||||||
document.body.classList.toggle('fixed', isFixed);
|
|
||||||
document.body.classList.toggle(styles.fixed, isFixed && !getModal());
|
|
||||||
}, [fixed(), getModal()])
|
|
||||||
|
|
||||||
// derived
|
// derived
|
||||||
const authorized = createMemo(() => session()?.user?.slug)
|
const authorized = createMemo(() => session()?.user?.slug)
|
||||||
|
@ -90,7 +87,7 @@ export const Header = (props: Props) => {
|
||||||
classList={{
|
classList={{
|
||||||
[styles.headerFixed]: props.isHeaderFixed,
|
[styles.headerFixed]: props.isHeaderFixed,
|
||||||
[styles.headerScrolledTop]: !getIsScrollingBottom() && getIsScrolled(),
|
[styles.headerScrolledTop]: !getIsScrollingBottom() && getIsScrolled(),
|
||||||
[styles.headerScrolledBottom]: getIsScrollingBottom() && getIsScrolled(),
|
[styles.headerScrolledBottom]: (getIsScrollingBottom() && getIsScrolled()) || isSharePopupVisible(),
|
||||||
[styles.headerWithTitle]: Boolean(props.title)
|
[styles.headerWithTitle]: Boolean(props.title)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -99,41 +96,6 @@ export const Header = (props: Props) => {
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<div class={clsx(styles.mainHeaderInner, 'wide-container')}>
|
<div class={clsx(styles.mainHeaderInner, 'wide-container')}>
|
||||||
<Popup name="share" class={clsx(styles.popupShare, stylesPopup.popupShare)}>
|
|
||||||
<ul class="nodash">
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<Icon name="vk-white" class={stylesPopup.icon}/>
|
|
||||||
VK
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<Icon name="facebook-white" class={stylesPopup.icon}/>
|
|
||||||
Facebook
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<Icon name="twitter-white" class={stylesPopup.icon}/>
|
|
||||||
Twitter
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<Icon name="telegram-white" class={stylesPopup.icon}/>
|
|
||||||
Telegram
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<Icon name="link-white" class={stylesPopup.icon}/>
|
|
||||||
{t('Copy link')}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</Popup>
|
|
||||||
|
|
||||||
<nav class={clsx(styles.headerInner, 'row')} classList={{ fixed: fixed() }}>
|
<nav class={clsx(styles.headerInner, 'row')} classList={{ fixed: fixed() }}>
|
||||||
<div class={clsx(styles.mainLogo, 'col-auto')}>
|
<div class={clsx(styles.mainLogo, 'col-auto')}>
|
||||||
<a href={getPagePath(router, 'home')} onClick={handleClientRouteLinkClick}>
|
<a href={getPagePath(router, 'home')} onClick={handleClientRouteLinkClick}>
|
||||||
|
@ -197,14 +159,23 @@ export const Header = (props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
<Show when={props.title}>
|
<Show when={props.title}>
|
||||||
<div class={styles.articleControls}>
|
<div class={styles.articleControls}>
|
||||||
<button onClick={() => {toggleModal('share')}}>
|
<SharePopup
|
||||||
<Icon name="share-outline" class={styles.icon}/>
|
onVisibilityChange={(isVisible) => {
|
||||||
</button>
|
console.log({ isVisible })
|
||||||
<a href="#comments">
|
setIsSharePopupVisible(isVisible)
|
||||||
|
}}
|
||||||
|
containerCssClass={styles.control}
|
||||||
|
trigger={<Icon name="share-outline" class={styles.icon} />}
|
||||||
|
/>
|
||||||
|
<a href="#comments" class={styles.control}>
|
||||||
<Icon name="comments-outline" class={styles.icon} />
|
<Icon name="comments-outline" class={styles.icon} />
|
||||||
</a>
|
</a>
|
||||||
<Icon name="pencil-outline" class={styles.icon} />
|
<a href="#" class={styles.control} onClick={(event) => event.preventDefault()}>
|
||||||
<Icon name="bookmark" class={styles.icon} />
|
<Icon name="pencil-outline" class={styles.icon} />
|
||||||
|
</a>
|
||||||
|
<a href="#" class={styles.control} onClick={(event) => event.preventDefault()}>
|
||||||
|
<Icon name="bookmark" class={styles.icon} />
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
|
.container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.popup {
|
.popup {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 2px solid #000;
|
border: 2px solid #000;
|
||||||
|
top: calc(100% + 8px);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
@include font-size(1.6rem);
|
@include font-size(1.6rem);
|
||||||
|
|
||||||
|
@ -24,6 +31,7 @@
|
||||||
|
|
||||||
a {
|
a {
|
||||||
border: none;
|
border: none;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
|
@ -40,7 +48,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.popupShare {
|
// TODO: animation
|
||||||
right: 1em;
|
// .popup {
|
||||||
top: 4.5rem;
|
// opacity: 1;
|
||||||
}
|
// transition: opacity 0.3s;
|
||||||
|
// z-index: 1;
|
||||||
|
// &.visible {
|
||||||
|
// opacity: 0;
|
||||||
|
// transition: opacity 0.3s, z-index 0s 0.3s;
|
||||||
|
// z-index: -1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
@ -1,33 +1,50 @@
|
||||||
import { createEffect, createSignal, onMount, Show } from 'solid-js'
|
import { createEffect, createSignal, JSX, onCleanup, onMount, Show } from 'solid-js'
|
||||||
import style from './Popup.module.scss'
|
import styles from './Popup.module.scss'
|
||||||
import { hideModal, useModalStore } from '../../stores/ui'
|
import { clsx } from 'clsx'
|
||||||
import {clsx} from 'clsx';
|
|
||||||
|
|
||||||
interface PopupProps {
|
export type PopupProps = {
|
||||||
name: string
|
containerCssClass?: string
|
||||||
children: any
|
trigger: JSX.Element
|
||||||
class?: string
|
children: JSX.Element
|
||||||
|
onVisibilityChange?: (isVisible) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Popup = (props: PopupProps) => {
|
export const Popup = (props: PopupProps) => {
|
||||||
const { getModal } = useModalStore()
|
const [isVisible, setIsVisible] = createSignal(false)
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
if (props.onVisibilityChange) {
|
||||||
|
props.onVisibilityChange(isVisible())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let container: HTMLDivElement | undefined
|
||||||
|
|
||||||
|
const handleClickOutside = (event: MouseEvent & { target: Element }) => {
|
||||||
|
if (!isVisible()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.target === container || container?.contains(event.target)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
window.addEventListener('keydown', (e: KeyboardEvent) => {
|
document.addEventListener('click', handleClickOutside, { capture: true })
|
||||||
if (e.key === 'Escape') hideModal()
|
onCleanup(() => document.removeEventListener('click', handleClickOutside, { capture: true }))
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const [visible, setVisible] = createSignal(false)
|
|
||||||
createEffect(() => {
|
|
||||||
setVisible(getModal() === props.name)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const toggle = () => setIsVisible((oldVisible) => !oldVisible)
|
||||||
|
// class={clsx(styles.popupShare, stylesPopup.popupShare)}
|
||||||
return (
|
return (
|
||||||
<Show when={visible()}>
|
<span class={clsx(styles.container, props.containerCssClass)} ref={container}>
|
||||||
<div class={clsx(style.popup, props.class)}>
|
<span onClick={toggle}>{props.trigger}</span>
|
||||||
{props.children}
|
<Show when={isVisible()}>
|
||||||
</div>
|
<div class={clsx(styles.popup)}>{props.children}</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,28 +54,29 @@ export const ManifestPage = () => {
|
||||||
|
|
||||||
<div class="col-lg-10 offset-md-1">
|
<div class="col-lg-10 offset-md-1">
|
||||||
<p>
|
<p>
|
||||||
Дискурс — независимый художественно-аналитический журнал с горизонтальной редакцией,
|
Дискурс — независимый художественно-аналитический журнал с горизонтальной
|
||||||
основанный на принципах свободы слова, прямой демократии и совместного редактирования.
|
редакцией, основанный на принципах свободы слова, прямой демократии и совместного
|
||||||
Дискурс создаётся открытым медиасообществом ученых, журналистов, музыкантов, писателей,
|
редактирования. Дискурс создаётся открытым медиасообществом ученых, журналистов, музыкантов,
|
||||||
предпринимателей, философов, инженеров, художников и специалистов со всего мира,
|
писателей, предпринимателей, философов, инженеров, художников и специалистов
|
||||||
объединившихся, чтобы вместе делать общий журнал и объяснять с разных точек
|
со всего мира, объединившихся, чтобы вместе делать общий журнал и объяснять
|
||||||
зрения мозаичную картину современности.
|
с разных точек зрения мозаичную картину современности.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Мы пишем о культуре, науке и обществе, рассказываем о новых идеях и современном искусстве,
|
Мы пишем о культуре, науке и обществе, рассказываем о новых идеях
|
||||||
публикуем статьи, исследования, репортажи, интервью людей, чью прямую речь стоит услышать,
|
и современном искусстве, публикуем статьи, исследования, репортажи, интервью людей, чью
|
||||||
и работы художников из разных стран — от фильмов и музыки
|
прямую речь стоит услышать, и работы художников из разных стран —
|
||||||
до живописи и фотографии. Помогая друг другу делать публикации качественнее
|
от фильмов и музыки до живописи и фотографии. Помогая друг другу делать
|
||||||
и общим голосованием выбирая лучшие материалы для журнала, мы создаём новую
|
публикации качественнее и общим голосованием выбирая лучшие материалы для журнала,
|
||||||
горизонтальную журналистику, чтобы честно рассказывать о важном и интересном.
|
мы создаём новую горизонтальную журналистику, чтобы честно рассказывать о важном
|
||||||
|
и интересном.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Редакция Дискурса открыта для всех: у нас нет цензуры, запретных тем и идеологических рамок.
|
Редакция Дискурса открыта для всех: у нас нет цензуры, запретных тем
|
||||||
Каждый может <a href="/create">прислать материал</a> в журнал
|
и идеологических рамок. Каждый может <a href="/create">прислать материал</a>{' '}
|
||||||
и <a href="/about/guide">присоединиться к редакции</a>. Предоставляя трибуну
|
в журнал и <a href="/about/guide">присоединиться к редакции</a>. Предоставляя
|
||||||
для независимой журналистики и художественных проектов, мы помогаем людям
|
трибуну для независимой журналистики и художественных проектов, мы помогаем людям
|
||||||
рассказывать свои истории так, чтобы они были услышаны. Мы убеждены: чем больше
|
рассказывать свои истории так, чтобы они были услышаны. Мы убеждены: чем больше голосов
|
||||||
голосов будет звучать на Дискурсе, тем громче в полифонии мнений будет слышна истина.
|
будет звучать на Дискурсе, тем громче в полифонии мнений будет слышна истина.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -91,23 +92,26 @@ export const ManifestPage = () => {
|
||||||
</p>
|
</p>
|
||||||
<h3 id="contribute">Предлагать материалы</h3>
|
<h3 id="contribute">Предлагать материалы</h3>
|
||||||
<p>
|
<p>
|
||||||
<a href="/create">Создавайте</a> свои статьи и художественные работы — лучшие из них будут
|
<a href="/create">Создавайте</a> свои статьи и художественные работы —
|
||||||
опубликованы в журнале. Дискурс — некоммерческое издание, авторы публикуются
|
лучшие из них будут опубликованы в журнале. Дискурс — некоммерческое
|
||||||
в журнале на общественных началах, получая при этом <a href="/create?collab=true">поддержку</a> редакции,
|
издание, авторы публикуются в журнале на общественных началах, получая при этом{' '}
|
||||||
право голоса, множество других возможностей и читателей по всему миру.
|
<a href="/create?collab=true">поддержку</a> редакции, право голоса, множество других
|
||||||
|
возможностей и читателей по всему миру.
|
||||||
</p>
|
</p>
|
||||||
<h3 id="donate">Поддерживать проект</h3>
|
<h3 id="donate">Поддерживать проект</h3>
|
||||||
<p>Дискурс существует на пожертвования читателей. Если вам нравится журнал, пожалуйста,</p>
|
|
||||||
<p>
|
<p>
|
||||||
<a href="/about/help">поддержите</a> нашу работу. Ваши пожертвования пойдут на выпуск новых
|
Дискурс существует на пожертвования читателей. Если вам нравится журнал, пожалуйста,
|
||||||
материалов, оплату серверов, труда программистов, дизайнеров и редакторов.
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="/about/help">поддержите</a> нашу работу. Ваши пожертвования пойдут на выпуск
|
||||||
|
новых материалов, оплату серверов, труда программистов, дизайнеров и редакторов.
|
||||||
</p>
|
</p>
|
||||||
<h3 id="cooperation">Сотрудничать с журналом</h3>
|
<h3 id="cooperation">Сотрудничать с журналом</h3>
|
||||||
<p>
|
<p>
|
||||||
Мы всегда открыты для сотрудничества и рады единомышленникам. Если вы хотите помогать
|
Мы всегда открыты для сотрудничества и рады единомышленникам. Если вы хотите помогать
|
||||||
журналу с редактурой, корректурой, иллюстрациями, переводами, версткой, подкастами,
|
журналу с редактурой, корректурой, иллюстрациями, переводами, версткой, подкастами,
|
||||||
мероприятиями, фандрайзингом или как-то ещё — скорее пишите нам
|
мероприятиями, фандрайзингом или как-то ещё — скорее пишите нам на
|
||||||
на <a href="mailto:welcome@discours.io">welcome@discours.io</a>.
|
<a href="mailto:welcome@discours.io">welcome@discours.io</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Если вы представляете некоммерческую организацию и хотите сделать с нами
|
Если вы представляете некоммерческую организацию и хотите сделать с нами
|
||||||
|
@ -116,25 +120,26 @@ export const ManifestPage = () => {
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Если вы разработчик и хотите помогать с развитием сайта Дискурса,{' '}
|
Если вы разработчик и хотите помогать с развитием сайта Дискурса,{' '}
|
||||||
<a href="mailto:services@discours.io">присоединяйтесь к IT-команде самиздата</a>. Открытый
|
<a href="mailto:services@discours.io">присоединяйтесь к IT-команде самиздата</a>.
|
||||||
код платформы для независимой журналистики, а также всех наших спецпроектов
|
Открытый код платформы для независимой журналистики, а также всех наших спецпроектов
|
||||||
и медиаинструментов находится <a href="https://github.com/Discours">в свободном доступе на GitHub</a>.
|
и медиаинструментов находится{' '}
|
||||||
|
<a href="https://github.com/Discours">в свободном доступе на GitHub</a>.
|
||||||
</p>
|
</p>
|
||||||
<h3 id="follow">Как еще можно помочь</h3>
|
<h3 id="follow">Как еще можно помочь</h3>
|
||||||
<p>
|
<p>
|
||||||
Советуйте Дискурс друзьям и знакомым. Обсуждайте и распространяйте наши
|
Советуйте Дискурс друзьям и знакомым. Обсуждайте и распространяйте наши
|
||||||
публикации — все материалы открытой редакции можно читать и перепечатывать
|
публикации — все материалы открытой редакции можно читать и перепечатывать
|
||||||
бесплатно. Подпишитесь на самиздат{' '}
|
бесплатно. Подпишитесь на самиздат <a href="https://vk.com/discoursio">ВКонтакте</a>,
|
||||||
<a href="https://vk.com/discoursio">ВКонтакте</a>,
|
|
||||||
в <a href="https://facebook.com/discoursio">Фейсбуке</a>
|
в <a href="https://facebook.com/discoursio">Фейсбуке</a>
|
||||||
и в <a href="https://t.me/discoursio">Телеграме</a>, а также
|
и в <a href="https://t.me/discoursio">Телеграме</a>, а также на
|
||||||
на <Opener name="subscribe">рассылку лучших материалов</Opener>,
|
<Opener name="subscribe">рассылку лучших материалов</Opener>, чтобы не пропустить
|
||||||
чтобы не пропустить ничего интересного.
|
ничего интересного.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="https://forms.gle/9UnHBAz9Q3tjH5dAA">Рассказывайте о впечатлениях</a>
|
<a href="https://forms.gle/9UnHBAz9Q3tjH5dAA">Рассказывайте о впечатлениях</a>
|
||||||
от материалов открытой редакции, <Opener name="feedback">делитесь идеями</Opener>,
|
от материалов открытой редакции, <Opener name="feedback">делитесь идеями</Opener>,
|
||||||
интересными темами, о которых хотели бы узнать больше, и историями, которые нужно рассказать.
|
интересными темами, о которых хотели бы узнать больше, и историями, которые нужно
|
||||||
|
рассказать.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -145,9 +150,9 @@ export const ManifestPage = () => {
|
||||||
<div class="col-lg-10 offset-md-1">
|
<div class="col-lg-10 offset-md-1">
|
||||||
Если вы хотите предложить материал, сотрудничать, рассказать о проблеме, которую нужно
|
Если вы хотите предложить материал, сотрудничать, рассказать о проблеме, которую нужно
|
||||||
осветить, сообщить об ошибке или баге, что-то обсудить, уточнить или посоветовать,
|
осветить, сообщить об ошибке или баге, что-то обсудить, уточнить или посоветовать,
|
||||||
пожалуйста, <Opener name="feedback">напишите нам здесь</Opener> или
|
пожалуйста, <Opener name="feedback">напишите нам здесь</Opener> или на почту{' '}
|
||||||
на почту <a href="mailto:welcome@discours.io">welcome@discours.io</a>. Мы обязательно
|
<a href="mailto:welcome@discours.io">welcome@discours.io</a>. Мы обязательно ответим
|
||||||
ответим и постараемся реализовать все хорошие задумки.
|
и постараемся реализовать все хорошие задумки.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { createSignal } from 'solid-js'
|
||||||
|
|
||||||
//export const locale = persistentAtom<string>('locale', 'ru')
|
//export const locale = persistentAtom<string>('locale', 'ru')
|
||||||
export const [locale, setLocale] = createSignal('ru')
|
export const [locale, setLocale] = createSignal('ru')
|
||||||
export type ModalType = 'auth' | 'subscribe' | 'feedback' | 'share' | 'thank' | 'donate' | null
|
export type ModalType = 'auth' | 'subscribe' | 'feedback' | 'thank' | 'donate' | null
|
||||||
type WarnKind = 'error' | 'warn' | 'info'
|
type WarnKind = 'error' | 'warn' | 'info'
|
||||||
|
|
||||||
export interface Warning {
|
export interface Warning {
|
||||||
|
@ -20,7 +20,6 @@ const warnings = atom<Warning[]>([])
|
||||||
|
|
||||||
export const showModal = (modalType: ModalType) => modal.set(modalType)
|
export const showModal = (modalType: ModalType) => modal.set(modalType)
|
||||||
export const hideModal = () => modal.set(null)
|
export const hideModal = () => modal.set(null)
|
||||||
export const toggleModal = (modalType) => modal.get() ? hideModal() : showModal(modalType)
|
|
||||||
|
|
||||||
export const clearWarns = () => warnings.set([])
|
export const clearWarns = () => warnings.set([])
|
||||||
export const warn = (warning: Warning) => warnings.set([...warnings.get(), warning])
|
export const warn = (warning: Warning) => warnings.set([...warnings.get(), warning])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user