fix(front): Users can expand and collapse rendered descriptions (in user-owned Channel detail page)

Flupsi 2025-08-14 21:46:47 +02:00 zatwierdzone przez Arne Bollinger
rodzic be15f1d5ec
commit 06d0859896
3 zmienionych plików z 111 dodań i 100 usunięć

Wyświetl plik

@ -11,6 +11,8 @@ import clip from 'text-clipper'
import Layout from '~/components/ui/Layout.vue'
import Button from '~/components/ui/Button.vue'
import Alert from '~/components/ui/Alert.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Section from '~/components/ui/Section.vue'
interface Events {
(e: 'updated', data: unknown): void
@ -92,102 +94,105 @@ const submit = async () => {
</script>
<template>
<Layout
v-if="content && !isUpdating"
flex
gap-4
<Section
:action="isTruncated ? {
text:
showMore
? t('components.common.RenderedDescription.button.less')
: t('components.common.RenderedDescription.button.more'),
onClick:() => { showMore = !showMore },
style:'color: var(--fw-primary)',
id: 'expandOrCollapseButton'
} : undefined"
>
<!-- Render the truncated or full description -->
<sanitized-html
:html="html"
:class="['description', isTruncated ? 'truncated' : '']"
/>
<label
v-if="content && !isUpdating"
for="expandOrCollapseButton"
>
<!-- Render the truncated or full description -->
<sanitized-html
:html="html"
:class="['description', isTruncated ? 'truncated' : '']"
/>
</label>
<span v-else-if="!isUpdating">
{{ t('components.common.RenderedDescription.empty.noDescription') }}
</span>
<!-- Display the `show more` / `show less` button -->
<!-- [DISABLED] Display an edit form -->
<!-- TODO: Check if we want to revive in-situ editing here -->
<template v-if="isTruncated">
<a
v-if="showMore === false && props.moreLink !== false"
class="more"
style="align-self: flex-end; color: var(--fw-primary);"
href=""
@click.stop.prevent="showMore = true"
<form
v-if="isUpdating"
@submit.prevent="submit()"
>
<Alert
v-if="errors.length > 0"
red
title="{{ t('components.common.RenderedDescription.header.failure') }}"
role="alert"
>
{{ t('components.common.RenderedDescription.button.more') }}
</a>
<a
v-else-if="props.moreLink !== false"
class="more"
style="align-self: center; color: var(--fw-primary);"
href=""
@click.stop.prevent="showMore = false"
<ul class="list">
<li
v-for="(error, key) in errors"
:key="key"
>
{{ error }}
</li>
</ul>
</Alert>
<content-form
v-model="text"
:autofocus="true"
/>
<Button
class="left floated"
solid
secondary
@click.prevent="isUpdating = false"
>
{{ t('components.common.RenderedDescription.button.less') }}
</a>
</template>
</Layout>
<span v-else-if="!isUpdating">
{{ t('components.common.RenderedDescription.empty.noDescription') }}
</span>
<!-- [DISABLED] Display an edit form -->
<!-- TODO: Check if we want to revive in-situ editing here -->
<form
v-if="isUpdating"
@submit.prevent="submit()"
>
<Alert
v-if="errors.length > 0"
red
title="{{ t('components.common.RenderedDescription.header.failure') }}"
role="alert"
>
<ul class="list">
<li
v-for="(error, key) in errors"
:key="key"
>
{{ error }}
</li>
</ul>
</Alert>
<content-form
v-model="text"
:autofocus="true"
/>
<Button
class="left floated"
solid
secondary
@click.prevent="isUpdating = false"
>
{{ t('components.common.RenderedDescription.button.cancel') }}
</Button>
<Button
:class="['ui', {'loading': isLoading}, 'right', 'floated', 'button']"
type="submit"
:disabled="isLoading"
solid
primary
>
{{ t('components.common.RenderedDescription.button.update') }}
</Button>
</form>
{{ t('components.common.RenderedDescription.button.cancel') }}
</Button>
<Button
:class="['ui', {'loading': isLoading}, 'right', 'floated', 'button']"
type="submit"
:disabled="isLoading"
solid
primary
>
{{ t('components.common.RenderedDescription.button.update') }}
</Button>
</form>
</Section>
</template>
<style lang="scss" scoped>
.description {
:has(>.description) {
position: relative;
align-items: first baseline;
}
.description {
display: flex; flex-direction: column;
}
.description.truncated {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
white-space: normal;
&.truncated {
-webkit-line-clamp: 1; /* Number of lines to show */
line-clamp: 1;
max-height: 72px;
flex-shrink: 1;
}
}
/* .description {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
white-space: normal;
&.truncated {
-webkit-line-clamp: 1;
line-clamp: 1;
max-height: 72px;
flex-shrink: 1;
}
} */
</style>

Wyświetl plik

@ -12,7 +12,7 @@ import Heading from '~/components/ui/Heading.vue'
const props = defineProps<{
columnsPerItem?: 1 | 2 | 3 | 4
alignLeft?: boolean
action?: { text: string } & (ComponentProps<typeof Link> | ComponentProps<typeof Button>)
action?: { text: string, id?: string } & (ComponentProps<typeof Link> | ComponentProps<typeof Button>)
icon?: string
} & {
[H in `h${ '1' | '2' | '3' | '4' | '5' | '6' }`]? : string

Wyświetl plik

@ -20,6 +20,7 @@ import HumanDuration from '~/components/common/HumanDuration.vue'
import PlayButton from '~/components/audio/PlayButton.vue'
import TagsList from '~/components/tags/List.vue'
import RadioButton from '~/components/radios/Button.vue'
import RenderedDescription from '~/components/common/RenderedDescription.vue'
import Loader from '~/components/ui/Loader.vue'
import Layout from '~/components/ui/Layout.vue'
@ -161,6 +162,12 @@ const tabs = ref([
to: { name: 'channels.detail.episodes', params: { id: props.id } }
}
])
const renderedDescription = computed(() => {
const description = object.value?.artist?.description
return description && ({ text: description.text || undefined, html: description.html })
}
)
</script>
<template>
@ -262,11 +269,10 @@ const tabs = ref([
/>
</Layout>
</Layout>
<rendered-description
:content="object.artist?.description"
<RenderedDescription
:content="renderedDescription"
:update-url="`channels/${object.uuid}/`"
:can-update="false"
@updated="object = $event"
/>
<Layout
flex
@ -411,14 +417,14 @@ const tabs = ref([
: t('views.channels.DetailBase.header.artistChannel')
"
>
<Spacer />
<channel-form
ref="editForm"
:object="object"
@loading="edit.loading = $event"
@submittable="edit.submittable = $event"
@updated="fetchData"
/>
<Spacer />
<channel-form
ref="editForm"
:object="object"
@loading="edit.loading = $event"
@submittable="edit.submittable = $event"
@updated="fetchData"
/>
<template #actions>
<Spacer grow />
<Button
@ -427,7 +433,7 @@ const tabs = ref([
low-height
:is-loading="edit.loading"
:disabled="!edit.submittable"
@click.stop="() => { console.log('EDITF', editForm); editForm?.submit(); /*showEditModal = false;*/ }"
@click.stop="() => { editForm?.submit(); }"
>
{{ t('views.channels.DetailBase.button.updateChannel') }}
</Button>