parent
9b18587c9e
commit
6bce7d576c
|
@ -167,6 +167,8 @@
|
||||||
"More": "More",
|
"More": "More",
|
||||||
"Most commented": "Commented",
|
"Most commented": "Commented",
|
||||||
"Most read": "Readable",
|
"Most read": "Readable",
|
||||||
|
"Move down": "Move down",
|
||||||
|
"Move up": "Move up",
|
||||||
"My feed": "My feed",
|
"My feed": "My feed",
|
||||||
"My subscriptions": "Subscriptions",
|
"My subscriptions": "Subscriptions",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
|
|
|
@ -177,6 +177,8 @@
|
||||||
"More": "Ещё",
|
"More": "Ещё",
|
||||||
"Most commented": "Комментируемое",
|
"Most commented": "Комментируемое",
|
||||||
"Most read": "Читаемое",
|
"Most read": "Читаемое",
|
||||||
|
"Move down": "Переместить вниз",
|
||||||
|
"Move up": "Переместить вверх",
|
||||||
"My feed": "Моя лента",
|
"My feed": "Моя лента",
|
||||||
"My subscriptions": "Подписки",
|
"My subscriptions": "Подписки",
|
||||||
"Name": "Имя",
|
"Name": "Имя",
|
||||||
|
|
|
@ -309,8 +309,25 @@ $vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thum
|
||||||
.actions {
|
.actions {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
|
||||||
|
.action {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
|
||||||
|
&:not([disabled]):hover {
|
||||||
|
border-color: var(--background-color-invert);
|
||||||
|
background: var(--background-color-invert);
|
||||||
|
img {
|
||||||
|
filter: var(--icon-filter-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.moveIconDown {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.descriptionBlock {
|
.descriptionBlock {
|
||||||
|
|
|
@ -11,6 +11,7 @@ type Props = {
|
||||||
body?: string
|
body?: string
|
||||||
editorMode?: boolean
|
editorMode?: boolean
|
||||||
onMediaItemFieldChange?: (index: number, field: keyof MediaItem, value: string) => void
|
onMediaItemFieldChange?: (index: number, field: keyof MediaItem, value: string) => void
|
||||||
|
onChangeMediaIndex?: (direction: 'up' | 'down', index) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFormattedTime = (point) => new Date(point * 1000).toISOString().slice(14, -5)
|
const getFormattedTime = (point) => new Date(point * 1000).toISOString().slice(14, -5)
|
||||||
|
@ -159,6 +160,7 @@ export const AudioPlayer = (props: Props) => {
|
||||||
<PlayerPlaylist
|
<PlayerPlaylist
|
||||||
editorMode={props.editorMode}
|
editorMode={props.editorMode}
|
||||||
onPlayMedia={handlePlayMedia}
|
onPlayMedia={handlePlayMedia}
|
||||||
|
onChangeMediaIndex={(direction, index) => props.onChangeMediaIndex(direction, index)}
|
||||||
isPlaying={isPlaying()}
|
isPlaying={isPlaying()}
|
||||||
media={props.media}
|
media={props.media}
|
||||||
currentTrackIndex={currentTrackIndex()}
|
currentTrackIndex={currentTrackIndex()}
|
||||||
|
|
|
@ -18,6 +18,7 @@ type Props = {
|
||||||
body?: string
|
body?: string
|
||||||
editorMode?: boolean
|
editorMode?: boolean
|
||||||
onMediaItemFieldChange?: (index: number, field: keyof MediaItem, value: string) => void
|
onMediaItemFieldChange?: (index: number, field: keyof MediaItem, value: string) => void
|
||||||
|
onChangeMediaIndex?: (direction: 'up' | 'down', index) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PlayerPlaylist = (props: Props) => {
|
export const PlayerPlaylist = (props: Props) => {
|
||||||
|
@ -72,6 +73,34 @@ export const PlayerPlaylist = (props: Props) => {
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
<div class={styles.actions}>
|
<div class={styles.actions}>
|
||||||
|
<Show when={props.editorMode}>
|
||||||
|
<Popover content={t('Move up')}>
|
||||||
|
{(triggerRef: (el) => void) => (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
ref={triggerRef}
|
||||||
|
class={styles.action}
|
||||||
|
disabled={index() === 0}
|
||||||
|
onClick={() => props.onChangeMediaIndex('up', index())}
|
||||||
|
>
|
||||||
|
<Icon name="up-button" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</Popover>
|
||||||
|
<Popover content={t('Move down')}>
|
||||||
|
{(triggerRef: (el) => void) => (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
ref={triggerRef}
|
||||||
|
class={styles.action}
|
||||||
|
disabled={index() === props.media.length - 1}
|
||||||
|
onClick={() => props.onChangeMediaIndex('down', index())}
|
||||||
|
>
|
||||||
|
<Icon name="up-button" class={styles.moveIconDown} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</Popover>
|
||||||
|
</Show>
|
||||||
<Show when={(mi.lyrics || mi.body) && !props.editorMode}>
|
<Show when={(mi.lyrics || mi.body) && !props.editorMode}>
|
||||||
<Popover content={t('Show lyrics')}>
|
<Popover content={t('Show lyrics')}>
|
||||||
{(triggerRef: (el) => void) => (
|
{(triggerRef: (el) => void) => (
|
||||||
|
|
|
@ -190,12 +190,6 @@ export const FullArticle = (props: ArticleProps) => {
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
<Show when={media().length > 0 && props.article.layout === 'audio'}>
|
|
||||||
<div class="media-items">
|
|
||||||
<AudioPlayer media={media()} articleSlug={props.article.slug} body={body()} />
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
<Show when={body()}>
|
<Show when={body()}>
|
||||||
<div class={styles.shoutBody}>
|
<div class={styles.shoutBody}>
|
||||||
<Show when={!body().startsWith('<')} fallback={<div innerHTML={body()} />}>
|
<Show when={!body().startsWith('<')} fallback={<div innerHTML={body()} />}>
|
||||||
|
|
|
@ -2,8 +2,8 @@ import { clsx } from 'clsx'
|
||||||
import styles from './AudioUploader.module.scss'
|
import styles from './AudioUploader.module.scss'
|
||||||
import { DropArea } from '../../_shared/DropArea'
|
import { DropArea } from '../../_shared/DropArea'
|
||||||
import { useLocalize } from '../../../context/localize'
|
import { useLocalize } from '../../../context/localize'
|
||||||
import { createEffect, createSignal, on, Show } from 'solid-js'
|
import { Show } from 'solid-js'
|
||||||
import { MediaItem, UploadedFile } from '../../../pages/types'
|
import { MediaItem } from '../../../pages/types'
|
||||||
import { composeMediaItems } from '../../../utils/composeMediaItems'
|
import { composeMediaItems } from '../../../utils/composeMediaItems'
|
||||||
import { AudioPlayer } from '../../Article/AudioPlayer'
|
import { AudioPlayer } from '../../Article/AudioPlayer'
|
||||||
import { Buffer } from 'buffer'
|
import { Buffer } from 'buffer'
|
||||||
|
@ -20,6 +20,7 @@ type Props = {
|
||||||
}
|
}
|
||||||
onAudioChange: (index: number, value: MediaItem) => void
|
onAudioChange: (index: number, value: MediaItem) => void
|
||||||
onAudioAdd: (value: MediaItem[]) => void
|
onAudioAdd: (value: MediaItem[]) => void
|
||||||
|
onAudioSorted: (value: MediaItem[]) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AudioUploader = (props: Props) => {
|
export const AudioUploader = (props: Props) => {
|
||||||
|
@ -29,6 +30,18 @@ export const AudioUploader = (props: Props) => {
|
||||||
props.onAudioChange(index, { ...props.audio[index], [field]: value })
|
props.onAudioChange(index, { ...props.audio[index], [field]: value })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleChangeIndex = (direction: 'up' | 'down', index: number) => {
|
||||||
|
const media = [...props.audio]
|
||||||
|
if (direction === 'up' && index > 0) {
|
||||||
|
const copy = media.splice(index, 1)[0]
|
||||||
|
media.splice(index - 1, 0, copy)
|
||||||
|
} else if (direction === 'down' && index < media.length - 1) {
|
||||||
|
const copy = media.splice(index, 1)[0]
|
||||||
|
media.splice(index + 1, 0, copy)
|
||||||
|
}
|
||||||
|
props.onAudioSorted(media)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={clsx(styles.AudioUploader, props.class)}>
|
<div class={clsx(styles.AudioUploader, props.class)}>
|
||||||
<Show when={props.audio.length > 0}>
|
<Show when={props.audio.length > 0}>
|
||||||
|
@ -36,6 +49,7 @@ export const AudioUploader = (props: Props) => {
|
||||||
editorMode={true}
|
editorMode={true}
|
||||||
media={props.audio}
|
media={props.audio}
|
||||||
onMediaItemFieldChange={handleMediaItemFieldChange}
|
onMediaItemFieldChange={handleMediaItemFieldChange}
|
||||||
|
onChangeMediaIndex={handleChangeIndex}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
<DropArea
|
<DropArea
|
||||||
|
|
|
@ -96,6 +96,13 @@
|
||||||
.additionalInput {
|
.additionalInput {
|
||||||
@include font-size(1.4rem);
|
@include font-size(1.4rem);
|
||||||
|
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
&::-webkit-outer-spin-button,
|
||||||
|
&::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 14px 0 0;
|
margin: 14px 0 0;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Accessor, createEffect, createMemo, createSignal, For, onCleanup, onMount, Show } from 'solid-js'
|
import { Accessor, createMemo, createSignal, For, onCleanup, onMount, Show } from 'solid-js'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { Title } from '@solidjs/meta'
|
import { Title } from '@solidjs/meta'
|
||||||
|
@ -132,7 +132,7 @@ export const EditView = (props: Props) => {
|
||||||
const newMedia = [...mediaItems(), ...data]
|
const newMedia = [...mediaItems(), ...data]
|
||||||
setForm('media', JSON.stringify(newMedia))
|
setForm('media', JSON.stringify(newMedia))
|
||||||
}
|
}
|
||||||
const handleSortedImages = (data) => {
|
const handleSortedMedia = (data) => {
|
||||||
setForm('media', JSON.stringify(data))
|
setForm('media', JSON.stringify(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,6 +244,10 @@ export const EditView = (props: Props) => {
|
||||||
onChange={(event) => handleBaseFieldsChange('artist', event.target.value)}
|
onChange={(event) => handleBaseFieldsChange('artist', event.target.value)}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
|
type="number"
|
||||||
|
min="1900"
|
||||||
|
max={new Date().getFullYear()}
|
||||||
|
step="1"
|
||||||
class={styles.additionalInput}
|
class={styles.additionalInput}
|
||||||
placeholder={t('Release date...')}
|
placeholder={t('Release date...')}
|
||||||
value={mediaItems()[0]?.date || ''}
|
value={mediaItems()[0]?.date || ''}
|
||||||
|
@ -305,7 +309,7 @@ export const EditView = (props: Props) => {
|
||||||
onImageChange={handleMediaChange}
|
onImageChange={handleMediaChange}
|
||||||
onImageDelete={(index) => handleImageDelete(index)}
|
onImageDelete={(index) => handleImageDelete(index)}
|
||||||
onImagesAdd={(value) => handleAddMedia(value)}
|
onImagesAdd={(value) => handleAddMedia(value)}
|
||||||
onImagesSorted={(value) => handleSortedImages(value)}
|
onImagesSorted={(value) => handleSortedMedia(value)}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
|
@ -341,6 +345,7 @@ export const EditView = (props: Props) => {
|
||||||
baseFields={baseAudioFields()}
|
baseFields={baseAudioFields()}
|
||||||
onAudioAdd={(value) => handleAddMedia(value)}
|
onAudioAdd={(value) => handleAddMedia(value)}
|
||||||
onAudioChange={handleMediaChange}
|
onAudioChange={handleMediaChange}
|
||||||
|
onAudioSorted={(value) => handleSortedMedia(value)}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
|
@ -387,7 +392,7 @@ export const EditView = (props: Props) => {
|
||||||
{/* />*/}
|
{/* />*/}
|
||||||
{/*</div>*/}
|
{/*</div>*/}
|
||||||
|
|
||||||
<h4>Темы</h4>
|
<h4>{t('Topics')}</h4>
|
||||||
{/*<p class="description">*/}
|
{/*<p class="description">*/}
|
||||||
{/* Добавьте несколько тем, чтобы читатель знал, о чем ваш материал, и мог найти*/}
|
{/* Добавьте несколько тем, чтобы читатель знал, о чем ваш материал, и мог найти*/}
|
||||||
{/* его на страницах интересных ему тем. Темы можно менять местами, первая тема*/}
|
{/* его на страницах интересных ему тем. Темы можно менять местами, первая тема*/}
|
||||||
|
|
|
@ -295,7 +295,7 @@ export const SolidSwiper = (props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class={clsx(styles.action, {
|
class={clsx(styles.action, {
|
||||||
[styles.hidden]: index() + 1 === Number(props.images.length)
|
[styles.hidden]: index() === props.images.length - 1
|
||||||
})}
|
})}
|
||||||
onClick={() => handleChangeIndex('right', index())}
|
onClick={() => handleChangeIndex('right', index())}
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user