main topic select, save topics WiP
This commit is contained in:
parent
a73918b8f6
commit
01f33413eb
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -35,7 +35,7 @@
|
||||||
"@solid-primitives/storage": "1.3.9",
|
"@solid-primitives/storage": "1.3.9",
|
||||||
"@solid-primitives/upload": "0.0.110",
|
"@solid-primitives/upload": "0.0.110",
|
||||||
"@solidjs/meta": "0.28.2",
|
"@solidjs/meta": "0.28.2",
|
||||||
"@thisbeyond/solid-select": "0.13.0",
|
"@thisbeyond/solid-select": "0.14.0",
|
||||||
"@tiptap/core": "2.0.3",
|
"@tiptap/core": "2.0.3",
|
||||||
"@tiptap/extension-blockquote": "2.0.3",
|
"@tiptap/extension-blockquote": "2.0.3",
|
||||||
"@tiptap/extension-bold": "2.0.3",
|
"@tiptap/extension-bold": "2.0.3",
|
||||||
|
@ -5745,9 +5745,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@thisbeyond/solid-select": {
|
"node_modules/@thisbeyond/solid-select": {
|
||||||
"version": "0.13.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.14.0.tgz",
|
||||||
"integrity": "sha512-eION+Xf8TGLs1NZrvRo1NRKOl4plYMbY7UswHhh5bEUY8oMltjrBhUWF0hzaFViEc1zZpkCQyafaD89iofG6Tg==",
|
"integrity": "sha512-ecq4U3Vnc/nJbU84ARuPg2scNuYt994ljF5AmBlzuZW87x43mWiGJ5hEWufIJJMpDT6CcnCIx/xbrdDkaDEHQw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"solid-js": "^1.5"
|
"solid-js": "^1.5"
|
||||||
|
@ -24828,9 +24828,9 @@
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"@thisbeyond/solid-select": {
|
"@thisbeyond/solid-select": {
|
||||||
"version": "0.13.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.14.0.tgz",
|
||||||
"integrity": "sha512-eION+Xf8TGLs1NZrvRo1NRKOl4plYMbY7UswHhh5bEUY8oMltjrBhUWF0hzaFViEc1zZpkCQyafaD89iofG6Tg==",
|
"integrity": "sha512-ecq4U3Vnc/nJbU84ARuPg2scNuYt994ljF5AmBlzuZW87x43mWiGJ5hEWufIJJMpDT6CcnCIx/xbrdDkaDEHQw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
"@solid-primitives/storage": "1.3.9",
|
"@solid-primitives/storage": "1.3.9",
|
||||||
"@solid-primitives/upload": "0.0.110",
|
"@solid-primitives/upload": "0.0.110",
|
||||||
"@solidjs/meta": "0.28.2",
|
"@solidjs/meta": "0.28.2",
|
||||||
"@thisbeyond/solid-select": "0.13.0",
|
"@thisbeyond/solid-select": "0.14.0",
|
||||||
"@tiptap/core": "2.0.3",
|
"@tiptap/core": "2.0.3",
|
||||||
"@tiptap/extension-blockquote": "2.0.3",
|
"@tiptap/extension-blockquote": "2.0.3",
|
||||||
"@tiptap/extension-bold": "2.0.3",
|
"@tiptap/extension-bold": "2.0.3",
|
||||||
|
|
13
src/components/Editor/TopicSelect/TopicSelect.module.scss
Normal file
13
src/components/Editor/TopicSelect/TopicSelect.module.scss
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
.selectedItem {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.mainTopic {
|
||||||
|
cursor: default;
|
||||||
|
background: #000;
|
||||||
|
color: #ccc;
|
||||||
|
|
||||||
|
+ :global(.solid-select-multi-value-remove) {
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,32 +3,73 @@ import { createOptions, Select } from '@thisbeyond/solid-select'
|
||||||
import { useLocalize } from '../../../context/localize'
|
import { useLocalize } from '../../../context/localize'
|
||||||
import '@thisbeyond/solid-select/style.css'
|
import '@thisbeyond/solid-select/style.css'
|
||||||
import './TopicSelect.scss'
|
import './TopicSelect.scss'
|
||||||
|
import styles from './TopicSelect.module.scss'
|
||||||
|
import { clsx } from 'clsx'
|
||||||
|
import { createSignal } from 'solid-js'
|
||||||
|
import { slugify } from '../../../utils/slugify'
|
||||||
|
|
||||||
type TopicSelectProps = {
|
type TopicSelectProps = {
|
||||||
topics: Topic[]
|
topics: Topic[]
|
||||||
selectedTopics: Topic[]
|
selectedTopics: Topic[]
|
||||||
onChange: (selectedTopics: Topic[]) => void
|
onChange: (selectedTopics: Topic[]) => void
|
||||||
|
mainTopic?: Topic
|
||||||
|
onMainTopicChange: (mainTopic: Topic) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TopicSelect = (props: TopicSelectProps) => {
|
export const TopicSelect = (props: TopicSelectProps) => {
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
|
|
||||||
|
const [isDisabled, setIsDisabled] = createSignal(false)
|
||||||
|
|
||||||
|
const createValue = (title): Topic => {
|
||||||
|
const minId = Math.min(...props.selectedTopics.map((topic) => topic.id))
|
||||||
|
const id = minId < 0 ? minId - 1 : -2
|
||||||
|
return { id, title, slug: slugify(title) }
|
||||||
|
}
|
||||||
|
|
||||||
const selectProps = createOptions(props.topics, {
|
const selectProps = createOptions(props.topics, {
|
||||||
key: 'title',
|
key: 'title',
|
||||||
disable: (topic) => {
|
disable: (topic) => {
|
||||||
// console.log({ selectedTopics: clone(props.selectedTopics) })
|
|
||||||
return props.selectedTopics.some((selectedTopic) => selectedTopic.slug === topic.slug)
|
return props.selectedTopics.some((selectedTopic) => selectedTopic.slug === topic.slug)
|
||||||
}
|
},
|
||||||
|
createable: createValue
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleChange = (selectedTopics: Topic[]) => {
|
const handleChange = (selectedTopics: Topic[]) => {
|
||||||
props.onChange(selectedTopics)
|
props.onChange(selectedTopics)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSelectedItemClick = (topic: Topic) => {
|
||||||
|
setIsDisabled(true)
|
||||||
|
props.onMainTopicChange(topic)
|
||||||
|
setIsDisabled(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const format = (item, type) => {
|
||||||
|
if (type === 'option') {
|
||||||
|
return item.label
|
||||||
|
}
|
||||||
|
|
||||||
|
const isMainTopic = item.id === props.mainTopic.id
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class={clsx(styles.selectedItem, {
|
||||||
|
[styles.mainTopic]: isMainTopic
|
||||||
|
})}
|
||||||
|
onClick={() => handleSelectedItemClick(item)}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
multiple={true}
|
multiple={true}
|
||||||
|
disabled={isDisabled()}
|
||||||
{...selectProps}
|
{...selectProps}
|
||||||
|
format={format}
|
||||||
placeholder={t('Topics')}
|
placeholder={t('Topics')}
|
||||||
class="TopicSelect"
|
class="TopicSelect"
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
|
|
@ -217,3 +217,7 @@
|
||||||
color: #f00;
|
color: #f00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topicSelectContainer {
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,11 @@ const scrollTop = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EMPTY_TOPIC: Topic = {
|
||||||
|
id: -1,
|
||||||
|
slug: ''
|
||||||
|
}
|
||||||
|
|
||||||
export const EditView = (props: EditViewProps) => {
|
export const EditView = (props: EditViewProps) => {
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const { user } = useSession()
|
const { user } = useSession()
|
||||||
|
@ -39,13 +44,15 @@ export const EditView = (props: EditViewProps) => {
|
||||||
actions: { setForm, setFormErrors }
|
actions: { setForm, setFormErrors }
|
||||||
} = useEditorContext()
|
} = useEditorContext()
|
||||||
|
|
||||||
|
const shoutTopics = props.shout.topics || []
|
||||||
|
|
||||||
setForm({
|
setForm({
|
||||||
shoutId: props.shout.id,
|
shoutId: props.shout.id,
|
||||||
slug: props.shout.slug,
|
slug: props.shout.slug,
|
||||||
title: props.shout.title,
|
title: props.shout.title,
|
||||||
subtitle: props.shout.subtitle,
|
subtitle: props.shout.subtitle,
|
||||||
selectedTopics: props.shout.topics || [],
|
selectedTopics: shoutTopics,
|
||||||
mainTopic: props.shout.mainTopic,
|
mainTopic: shoutTopics.find((topic) => topic.slug === props.shout.mainTopic) || EMPTY_TOPIC,
|
||||||
body: props.shout.body,
|
body: props.shout.body,
|
||||||
coverImageUrl: props.shout.cover
|
coverImageUrl: props.shout.cover
|
||||||
})
|
})
|
||||||
|
@ -86,6 +93,24 @@ export const EditView = (props: EditViewProps) => {
|
||||||
setForm('coverImageUrl', imgUrl)
|
setForm('coverImageUrl', imgUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleTopicSelectChange = (newSelectedTopics) => {
|
||||||
|
console.log({ newSelectedTopics })
|
||||||
|
if (newSelectedTopics.length === 0) {
|
||||||
|
setForm('mainTopic', EMPTY_TOPIC)
|
||||||
|
} else if (
|
||||||
|
form.selectedTopics.length === 0 ||
|
||||||
|
newSelectedTopics.every((topic) => topic.id !== form.mainTopic.id)
|
||||||
|
) {
|
||||||
|
setForm('mainTopic', newSelectedTopics[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newSelectedTopics.length > 0) {
|
||||||
|
setFormErrors('selectedTopics', '')
|
||||||
|
}
|
||||||
|
|
||||||
|
setForm('selectedTopics', newSelectedTopics)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
|
@ -184,16 +209,20 @@ export const EditView = (props: EditViewProps) => {
|
||||||
{/* его на страницах интересных ему тем. Темы можно менять местами, первая тема*/}
|
{/* его на страницах интересных ему тем. Темы можно менять местами, первая тема*/}
|
||||||
{/* становится заглавной*/}
|
{/* становится заглавной*/}
|
||||||
{/*</p>*/}
|
{/*</p>*/}
|
||||||
<div class="pretty-form__item">
|
<div class={clsx('pretty-form__item', styles.topicSelectContainer)}>
|
||||||
<Show when={topics()}>
|
<Show when={topics()}>
|
||||||
<TopicSelect
|
<TopicSelect
|
||||||
topics={topics()}
|
topics={topics()}
|
||||||
onChange={(newSelectedTopics) => setForm('selectedTopics', newSelectedTopics)}
|
onChange={handleTopicSelectChange}
|
||||||
selectedTopics={form.selectedTopics}
|
selectedTopics={form.selectedTopics}
|
||||||
|
onMainTopicChange={(mainTopic) => setForm('mainTopic', mainTopic)}
|
||||||
|
mainTopic={form.mainTopic}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
{/*<input type="text" name="topics" id="topics" placeholder="Темы" class="nolabel" />*/}
|
|
||||||
</div>
|
</div>
|
||||||
|
<Show when={formErrors.selectedTopics}>
|
||||||
|
<div class={styles.validationError}>{formErrors.selectedTopics}</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
{/*<h4>Соавторы</h4>*/}
|
{/*<h4>Соавторы</h4>*/}
|
||||||
{/*<p class="description">У каждого соавтора можно добавить роль</p>*/}
|
{/*<p class="description">У каждого соавтора можно добавить роль</p>*/}
|
||||||
|
|
|
@ -5,9 +5,9 @@ import { Topic } from '../graphql/types.gen'
|
||||||
import { apiClient } from '../utils/apiClient'
|
import { apiClient } from '../utils/apiClient'
|
||||||
import { useLocalize } from './localize'
|
import { useLocalize } from './localize'
|
||||||
import { useSnackbar } from './snackbar'
|
import { useSnackbar } from './snackbar'
|
||||||
import { translit } from '../utils/ru2en'
|
|
||||||
import { openPage } from '@nanostores/router'
|
import { openPage } from '@nanostores/router'
|
||||||
import { router, useRouter } from '../stores/router'
|
import { router, useRouter } from '../stores/router'
|
||||||
|
import { slugify } from '../utils/slugify'
|
||||||
|
|
||||||
type WordCounter = {
|
type WordCounter = {
|
||||||
characters: number
|
characters: number
|
||||||
|
@ -20,7 +20,7 @@ type ShoutForm = {
|
||||||
title: string
|
title: string
|
||||||
subtitle: string
|
subtitle: string
|
||||||
selectedTopics: Topic[]
|
selectedTopics: Topic[]
|
||||||
mainTopic: string
|
mainTopic?: Topic
|
||||||
body: string
|
body: string
|
||||||
coverImageUrl: string
|
coverImageUrl: string
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ type EditorContextType = {
|
||||||
isEditorPanelVisible: Accessor<boolean>
|
isEditorPanelVisible: Accessor<boolean>
|
||||||
wordCounter: Accessor<WordCounter>
|
wordCounter: Accessor<WordCounter>
|
||||||
form: ShoutForm
|
form: ShoutForm
|
||||||
formErrors: Partial<ShoutForm>
|
formErrors: Record<keyof ShoutForm, string>
|
||||||
actions: {
|
actions: {
|
||||||
saveShout: () => Promise<void>
|
saveShout: () => Promise<void>
|
||||||
publishShout: () => Promise<void>
|
publishShout: () => Promise<void>
|
||||||
|
@ -38,7 +38,7 @@ type EditorContextType = {
|
||||||
toggleEditorPanel: () => void
|
toggleEditorPanel: () => void
|
||||||
countWords: (value: WordCounter) => void
|
countWords: (value: WordCounter) => void
|
||||||
setForm: SetStoreFunction<ShoutForm>
|
setForm: SetStoreFunction<ShoutForm>
|
||||||
setFormErrors: SetStoreFunction<Partial<ShoutForm>>
|
setFormErrors: SetStoreFunction<Record<keyof ShoutForm, string>>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => {
|
||||||
const [isEditorPanelVisible, setIsEditorPanelVisible] = createSignal<boolean>(false)
|
const [isEditorPanelVisible, setIsEditorPanelVisible] = createSignal<boolean>(false)
|
||||||
|
|
||||||
const [form, setForm] = createStore<ShoutForm>(null)
|
const [form, setForm] = createStore<ShoutForm>(null)
|
||||||
const [formErrors, setFormErrors] = createStore<Partial<ShoutForm>>(null)
|
const [formErrors, setFormErrors] = createStore<Record<keyof ShoutForm, string>>(null)
|
||||||
|
|
||||||
const [wordCounter, setWordCounter] = createSignal<WordCounter>({
|
const [wordCounter, setWordCounter] = createSignal<WordCounter>({
|
||||||
characters: 0,
|
characters: 0,
|
||||||
|
@ -79,31 +79,48 @@ export const EditorProvider = (props: { children: JSX.Element }) => {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveShout = async () => {
|
const validateSettings = () => {
|
||||||
if (isEditorPanelVisible()) {
|
if (form.selectedTopics.length === 0) {
|
||||||
toggleEditorPanel()
|
setFormErrors('selectedTopics', t('Required'))
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validate()) {
|
return true
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const updateShout = async ({ publish }: { publish: boolean }) => {
|
||||||
const shout = await apiClient.updateArticle({
|
return apiClient.updateArticle({
|
||||||
shoutId: form.shoutId,
|
shoutId: form.shoutId,
|
||||||
shoutInput: {
|
shoutInput: {
|
||||||
body: form.body,
|
body: form.body,
|
||||||
topics: form.selectedTopics.map((topic) => topic.slug),
|
topics: form.selectedTopics,
|
||||||
// authors?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
|
// authors?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
|
||||||
// community?: InputMaybe<Scalars['Int']>
|
// community?: InputMaybe<Scalars['Int']>
|
||||||
mainTopic: form.selectedTopics[0]?.slug || 'society',
|
mainTopic: form.mainTopic,
|
||||||
slug: form.slug,
|
slug: form.slug,
|
||||||
subtitle: form.subtitle,
|
subtitle: form.subtitle,
|
||||||
title: form.title,
|
title: form.title,
|
||||||
cover: form.coverImageUrl
|
cover: form.coverImageUrl
|
||||||
},
|
},
|
||||||
publish: false
|
publish
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveShout = async () => {
|
||||||
|
if (isEditorPanelVisible()) {
|
||||||
|
toggleEditorPanel()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page().route === 'edit' && !validate()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page().route === 'editSettings' && !validateSettings()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const shout = await updateShout({ publish: false })
|
||||||
|
|
||||||
if (shout.visibility === 'owner') {
|
if (shout.visibility === 'owner') {
|
||||||
openPage(router, 'drafts')
|
openPage(router, 'drafts')
|
||||||
|
@ -120,32 +137,20 @@ export const EditorProvider = (props: { children: JSX.Element }) => {
|
||||||
if (isEditorPanelVisible()) {
|
if (isEditorPanelVisible()) {
|
||||||
toggleEditorPanel()
|
toggleEditorPanel()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validate()) {
|
if (!validate()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page().route === 'edit') {
|
if (page().route === 'edit') {
|
||||||
const slug = translit(form.title.toLowerCase()).replaceAll(' ', '-')
|
const slug = slugify(form.title)
|
||||||
setForm('slug', slug)
|
setForm('slug', slug)
|
||||||
openPage(router, 'editSettings', { shoutId: form.shoutId.toString() })
|
openPage(router, 'editSettings', { shoutId: form.shoutId.toString() })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await apiClient.updateArticle({
|
await updateShout({ publish: true })
|
||||||
shoutId: form.shoutId,
|
|
||||||
shoutInput: {
|
|
||||||
body: form.body,
|
|
||||||
topics: form.selectedTopics.map((topic) => topic.slug),
|
|
||||||
// authors?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
|
|
||||||
// community?: InputMaybe<Scalars['Int']>
|
|
||||||
mainTopic: form.selectedTopics[0]?.slug || 'society',
|
|
||||||
slug: form.slug,
|
|
||||||
subtitle: form.subtitle,
|
|
||||||
title: form.title,
|
|
||||||
cover: form.coverImageUrl
|
|
||||||
},
|
|
||||||
publish: true
|
|
||||||
})
|
|
||||||
openPage(router, 'feed')
|
openPage(router, 'feed')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[publishShout]', error)
|
console.error('[publishShout]', error)
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { gql } from '@urql/core'
|
||||||
export default gql`
|
export default gql`
|
||||||
query TopicsAllQuery {
|
query TopicsAllQuery {
|
||||||
topicsAll {
|
topicsAll {
|
||||||
|
id
|
||||||
title
|
title
|
||||||
body
|
body
|
||||||
slug
|
slug
|
||||||
|
|
|
@ -582,11 +582,11 @@ export type ShoutInput = {
|
||||||
body?: InputMaybe<Scalars['String']>
|
body?: InputMaybe<Scalars['String']>
|
||||||
community?: InputMaybe<Scalars['Int']>
|
community?: InputMaybe<Scalars['Int']>
|
||||||
cover?: InputMaybe<Scalars['String']>
|
cover?: InputMaybe<Scalars['String']>
|
||||||
mainTopic?: InputMaybe<Scalars['String']>
|
mainTopic?: InputMaybe<TopicInput>
|
||||||
slug?: InputMaybe<Scalars['String']>
|
slug?: InputMaybe<Scalars['String']>
|
||||||
subtitle?: InputMaybe<Scalars['String']>
|
subtitle?: InputMaybe<Scalars['String']>
|
||||||
title?: InputMaybe<Scalars['String']>
|
title?: InputMaybe<Scalars['String']>
|
||||||
topics?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
|
topics?: InputMaybe<Array<InputMaybe<TopicInput>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShoutsFilterBy = {
|
export type ShoutsFilterBy = {
|
||||||
|
@ -628,7 +628,6 @@ export type Token = {
|
||||||
|
|
||||||
export type Topic = {
|
export type Topic = {
|
||||||
body?: Maybe<Scalars['String']>
|
body?: Maybe<Scalars['String']>
|
||||||
community: Community
|
|
||||||
id: Scalars['Int']
|
id: Scalars['Int']
|
||||||
oid?: Maybe<Scalars['String']>
|
oid?: Maybe<Scalars['String']>
|
||||||
pic?: Maybe<Scalars['String']>
|
pic?: Maybe<Scalars['String']>
|
||||||
|
@ -639,7 +638,7 @@ export type Topic = {
|
||||||
|
|
||||||
export type TopicInput = {
|
export type TopicInput = {
|
||||||
body?: InputMaybe<Scalars['String']>
|
body?: InputMaybe<Scalars['String']>
|
||||||
community: Scalars['String']
|
id?: InputMaybe<Scalars['Int']>
|
||||||
pic?: InputMaybe<Scalars['String']>
|
pic?: InputMaybe<Scalars['String']>
|
||||||
slug: Scalars['String']
|
slug: Scalars['String']
|
||||||
title?: InputMaybe<Scalars['String']>
|
title?: InputMaybe<Scalars['String']>
|
||||||
|
|
|
@ -25,7 +25,16 @@ export const EditPage = () => {
|
||||||
return (
|
return (
|
||||||
<PageLayout>
|
<PageLayout>
|
||||||
<Show when={isSessionLoaded()}>
|
<Show when={isSessionLoaded()}>
|
||||||
<Show when={isAuthenticated()} fallback="Давайте авторизуемся">
|
<Show
|
||||||
|
when={isAuthenticated()}
|
||||||
|
fallback={
|
||||||
|
<div class="wide-container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-19 col-lg-18 col-xl-16 offset-md-5">Давайте авторизуемся</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Show when={shout()}>
|
<Show when={shout()}>
|
||||||
<Suspense fallback={<Loading />}>
|
<Suspense fallback={<Loading />}>
|
||||||
<EditView shout={shout()} />
|
<EditView shout={shout()} />
|
||||||
|
|
7
src/utils/slugify.ts
Normal file
7
src/utils/slugify.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { translit } from './ru2en'
|
||||||
|
|
||||||
|
export const slugify = (text) => {
|
||||||
|
return translit(text.toLowerCase())
|
||||||
|
.replaceAll(/[^\da-z]/g, '')
|
||||||
|
.replaceAll(' ', '-')
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user