mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2026-03-01 12:44:37 +00:00
fix(webapp): add responsive masonry layout and skeleton loading UI (#9282)
This commit is contained in:
parent
64594a3235
commit
e3a41cb828
@ -1,9 +1,5 @@
|
||||
<template>
|
||||
<div
|
||||
class="ds-grid"
|
||||
:style="{ gridAutoRows: '20px', rowGap: '16px', columnGap: '16px' }"
|
||||
:class="[itemsCalculating ? 'reset-grid-height' : '']"
|
||||
>
|
||||
<div class="ds-grid" :style="gridStyle" :class="[itemsCalculating ? 'reset-grid-height' : '']">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
@ -13,16 +9,28 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
itemsCalculating: 0,
|
||||
isMobile: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
gridStyle() {
|
||||
const size = this.isMobile ? '1px' : '2px'
|
||||
return { gridAutoRows: size, rowGap: size }
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
isMobile() {
|
||||
this.$nextTick(() => {
|
||||
this.$children.forEach((child) => {
|
||||
if (child.calculateItemHeight) child.calculateItemHeight()
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$on('calculating-item-height', this.startCalculation)
|
||||
this.$on('finished-calculating-item-height', this.endCalculation)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$off('calculating-item-height', this.startCalculation)
|
||||
this.$off('finished-calculating-item-height', this.endCalculation)
|
||||
},
|
||||
methods: {
|
||||
startCalculation() {
|
||||
this.itemsCalculating += 1
|
||||
@ -30,6 +38,24 @@ export default {
|
||||
endCalculation() {
|
||||
this.itemsCalculating -= 1
|
||||
},
|
||||
checkMobile() {
|
||||
this.isMobile = window.innerWidth <= 810
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.checkMobile()
|
||||
// Children mount before parent — recalculate their spans with correct grid values
|
||||
this.$nextTick(() => {
|
||||
this.$children.forEach((child) => {
|
||||
if (child.calculateItemHeight) child.calculateItemHeight()
|
||||
})
|
||||
})
|
||||
window.addEventListener('resize', this.checkMobile)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$off('calculating-item-height', this.startCalculation)
|
||||
this.$off('finished-calculating-item-height', this.endCalculation)
|
||||
window.removeEventListener('resize', this.checkMobile)
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -37,6 +63,11 @@ export default {
|
||||
<style lang="scss">
|
||||
.ds-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
|
||||
column-gap: 16px;
|
||||
|
||||
@media (max-width: 810px) {
|
||||
column-gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.reset-grid-height {
|
||||
|
||||
@ -7,38 +7,59 @@ describe('MasonryGridItem', () => {
|
||||
let wrapper
|
||||
|
||||
describe('given an imageAspectRatio', () => {
|
||||
it('sets the initial rowSpan to 13 when the ratio is higher than 1.3', () => {
|
||||
it('sets the initial rowSpan to 114 when the ratio is higher than 1.3', () => {
|
||||
const propsData = { imageAspectRatio: 2 }
|
||||
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||
|
||||
expect(wrapper.vm.rowSpan).toBe(13)
|
||||
expect(wrapper.vm.rowSpan).toBe(114)
|
||||
})
|
||||
|
||||
it('sets the initial rowSpan to 15 when the ratio is between 1.3 and 1', () => {
|
||||
it('sets the initial rowSpan to 114 when the ratio is exactly 1.3', () => {
|
||||
const propsData = { imageAspectRatio: 1.3 }
|
||||
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||
|
||||
expect(wrapper.vm.rowSpan).toBe(114)
|
||||
})
|
||||
|
||||
it('sets the initial rowSpan to 132 when the ratio is between 1.3 and 1', () => {
|
||||
const propsData = { imageAspectRatio: 1.1 }
|
||||
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||
|
||||
expect(wrapper.vm.rowSpan).toBe(15)
|
||||
expect(wrapper.vm.rowSpan).toBe(132)
|
||||
})
|
||||
|
||||
it('sets the initial rowSpan to 18 when the ratio is between 1 and 0.7', () => {
|
||||
it('sets the initial rowSpan to 132 when the ratio is exactly 1', () => {
|
||||
const propsData = { imageAspectRatio: 1.0 }
|
||||
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||
|
||||
expect(wrapper.vm.rowSpan).toBe(132)
|
||||
})
|
||||
|
||||
it('sets the initial rowSpan to 159 when the ratio is between 1 and 0.7', () => {
|
||||
const propsData = { imageAspectRatio: 0.8 }
|
||||
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||
|
||||
expect(wrapper.vm.rowSpan).toBe(159)
|
||||
})
|
||||
|
||||
it('sets the initial rowSpan to 159 when the ratio is exactly 0.7', () => {
|
||||
const propsData = { imageAspectRatio: 0.7 }
|
||||
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||
|
||||
expect(wrapper.vm.rowSpan).toBe(18)
|
||||
expect(wrapper.vm.rowSpan).toBe(159)
|
||||
})
|
||||
|
||||
it('sets the initial rowSpan to 25 when the ratio is lower than 0.7', () => {
|
||||
it('sets the initial rowSpan to 222 when the ratio is lower than 0.7', () => {
|
||||
const propsData = { imageAspectRatio: 0.3 }
|
||||
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||
expect(wrapper.vm.rowSpan).toBe(25)
|
||||
expect(wrapper.vm.rowSpan).toBe(222)
|
||||
})
|
||||
})
|
||||
|
||||
describe('given no aspect ratio', () => {
|
||||
it('sets the initial rowSpan to 8 when not given an imageAspectRatio', () => {
|
||||
wrapper = mount(MasonryGridItem, { localVue })
|
||||
expect(wrapper.vm.rowSpan).toBe(8)
|
||||
})
|
||||
describe('given no aspect ratio', () => {
|
||||
it('sets the initial rowSpan to 69', () => {
|
||||
wrapper = mount(MasonryGridItem, { localVue })
|
||||
expect(wrapper.vm.rowSpan).toBe(69)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -9,10 +9,10 @@ const landscapeRatio = 1.3
|
||||
const squareRatio = 1
|
||||
const portraitRatio = 0.7
|
||||
const getRowSpan = (aspectRatio) => {
|
||||
if (aspectRatio >= landscapeRatio) return 13
|
||||
else if (aspectRatio >= squareRatio) return 15
|
||||
else if (aspectRatio >= portraitRatio) return 18
|
||||
else return 25
|
||||
if (aspectRatio >= landscapeRatio) return 114
|
||||
else if (aspectRatio >= squareRatio) return 132
|
||||
else if (aspectRatio >= portraitRatio) return 159
|
||||
else return 222
|
||||
}
|
||||
|
||||
export default {
|
||||
@ -24,7 +24,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rowSpan: this.imageAspectRatio ? getRowSpan(this.imageAspectRatio) : 8,
|
||||
rowSpan: this.imageAspectRatio ? getRowSpan(this.imageAspectRatio) : 69,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@ -12,7 +12,9 @@
|
||||
:highlight="isPinned"
|
||||
>
|
||||
<template v-if="post.image" #heroImage>
|
||||
<responsive-image :image="post.image" sizes="640px" class="image" />
|
||||
<div class="image-placeholder" :style="{ aspectRatio: post.image.aspectRatio }">
|
||||
<responsive-image :image="post.image" sizes="640px" class="image" />
|
||||
</div>
|
||||
</template>
|
||||
<client-only>
|
||||
<div class="post-user-row">
|
||||
@ -23,6 +25,17 @@
|
||||
:typ="post.postType[0]"
|
||||
/>
|
||||
</div>
|
||||
<template #placeholder>
|
||||
<div class="post-user-row">
|
||||
<div class="user-teaser-placeholder">
|
||||
<div class="placeholder-avatar" />
|
||||
<div class="placeholder-text">
|
||||
<div class="placeholder-line placeholder-line--name" />
|
||||
<div class="placeholder-line placeholder-line--date" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</client-only>
|
||||
<h2 class="title hyphenate-text">{{ post.title }}</h2>
|
||||
<client-only>
|
||||
@ -133,6 +146,11 @@
|
||||
<slot name="dateTime"></slot>
|
||||
</span>
|
||||
</div>
|
||||
<template v-if="post.createdAt" #placeholder>
|
||||
<div class="date-row">
|
||||
<span class="placeholder-line placeholder-line--date-footer" />
|
||||
</div>
|
||||
</template>
|
||||
</client-only>
|
||||
</os-card>
|
||||
</nuxt-link>
|
||||
@ -189,16 +207,6 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
const { image } = this.post
|
||||
if (!image) return
|
||||
const width = this.$el.offsetWidth
|
||||
const height = Math.min(width / image.aspectRatio, 2000)
|
||||
const imageElement = this.$el.querySelector('.os-card__hero-image')
|
||||
if (imageElement) {
|
||||
imageElement.style.height = `${height}px`
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user',
|
||||
@ -289,6 +297,10 @@ export default {
|
||||
height: 100%;
|
||||
color: $text-color-base;
|
||||
padding-top: 16px;
|
||||
|
||||
@media (max-width: 810px) {
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.post-user-row {
|
||||
@ -315,13 +327,24 @@ export default {
|
||||
flex-direction: column;
|
||||
overflow: visible;
|
||||
height: 100%;
|
||||
padding-bottom: $space-x-small;
|
||||
|
||||
> .os-card__hero-image {
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
.image-placeholder {
|
||||
width: 100%;
|
||||
background-color: $color-neutral-80;
|
||||
|
||||
> .image {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
&.--blur-image > .os-card__hero-image .image {
|
||||
filter: blur($blur-radius);
|
||||
}
|
||||
@ -333,6 +356,8 @@ export default {
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
padding-bottom: $space-x-small !important;
|
||||
|
||||
.content {
|
||||
flex-grow: 1;
|
||||
margin-bottom: $space-small;
|
||||
@ -368,10 +393,55 @@ export default {
|
||||
margin-bottom: $space-small;
|
||||
}
|
||||
|
||||
.user-teaser-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: $space-small;
|
||||
|
||||
.placeholder-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
opacity: 0.15;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding-left: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.placeholder-line {
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
background: currentColor;
|
||||
opacity: 0.15;
|
||||
|
||||
&--name {
|
||||
width: 120px;
|
||||
}
|
||||
&--date {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.date-row {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: $space-small;
|
||||
|
||||
> .placeholder-line--date-footer {
|
||||
width: 100px;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
background: currentColor;
|
||||
opacity: 0.15;
|
||||
}
|
||||
> .text {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
127
webapp/components/PostTeaser/PostTeaserSkeleton.vue
Normal file
127
webapp/components/PostTeaser/PostTeaserSkeleton.vue
Normal file
@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<div class="post-teaser-skeleton">
|
||||
<div class="skeleton-image" />
|
||||
<div class="skeleton-body">
|
||||
<div class="skeleton-user">
|
||||
<div class="skeleton-avatar" />
|
||||
<div class="skeleton-user-text">
|
||||
<div class="skeleton-line skeleton-line--short" />
|
||||
<div class="skeleton-line skeleton-line--xshort" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="skeleton-title">
|
||||
<div class="skeleton-line" />
|
||||
<div class="skeleton-line skeleton-line--medium" />
|
||||
</div>
|
||||
<div class="skeleton-content">
|
||||
<div class="skeleton-line" />
|
||||
<div class="skeleton-line" />
|
||||
<div class="skeleton-line skeleton-line--long" />
|
||||
</div>
|
||||
<div class="skeleton-footer">
|
||||
<div class="skeleton-line skeleton-line--short" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PostTeaserSkeleton',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@keyframes skeleton-pulse {
|
||||
0% {
|
||||
opacity: 0.15;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.3;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.15;
|
||||
}
|
||||
}
|
||||
|
||||
.post-teaser-skeleton {
|
||||
background: #fff;
|
||||
border-radius: $border-radius-base;
|
||||
box-shadow: $box-shadow-base;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.skeleton-image {
|
||||
width: 100%;
|
||||
padding-bottom: 56%;
|
||||
background: currentColor;
|
||||
animation: skeleton-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.skeleton-body {
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.skeleton-user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.skeleton-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
flex-shrink: 0;
|
||||
animation: skeleton-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.skeleton-user-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.skeleton-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.skeleton-footer {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.skeleton-line {
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
background: currentColor;
|
||||
animation: skeleton-pulse 1.5s ease-in-out infinite;
|
||||
width: 100%;
|
||||
|
||||
&--xshort {
|
||||
width: 25%;
|
||||
}
|
||||
&--short {
|
||||
width: 40%;
|
||||
}
|
||||
&--medium {
|
||||
width: 65%;
|
||||
}
|
||||
&--long {
|
||||
width: 85%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -35,6 +35,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
progressBarWidth() {
|
||||
if (!this.goal) return 'width: 0%;'
|
||||
return `width: ${(this.progress / this.goal) * 100}%;`
|
||||
},
|
||||
progressBarColorClass() {
|
||||
@ -59,7 +60,6 @@ export default {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
margin-right: $space-x-small;
|
||||
}
|
||||
|
||||
.progress-bar__goal {
|
||||
@ -108,7 +108,6 @@ export default {
|
||||
|
||||
.progress-bar__label {
|
||||
position: relative;
|
||||
float: right;
|
||||
|
||||
@media (max-width: 350px) {
|
||||
font-size: $font-size-small;
|
||||
@ -117,7 +116,7 @@ export default {
|
||||
|
||||
.progress-bar-button {
|
||||
position: relative;
|
||||
float: right;
|
||||
margin-left: $space-x-small;
|
||||
|
||||
@media (max-width: 810px) {
|
||||
display: none;
|
||||
|
||||
@ -117,10 +117,6 @@ export default {
|
||||
if (!(id && slug)) return ''
|
||||
return { name: 'groups-id-slug', params: { slug, id } }
|
||||
},
|
||||
groupSlug() {
|
||||
const { slug } = this.group || {}
|
||||
return slug && `&${slug}`
|
||||
},
|
||||
groupName() {
|
||||
const { name } = this.group || {}
|
||||
return name || this.$t('profile.userAnonym')
|
||||
|
||||
@ -66,10 +66,15 @@ export default {
|
||||
padding-bottom: 8rem;
|
||||
}
|
||||
|
||||
.desktop-footer {
|
||||
@media (max-width: 810px) {
|
||||
@media (max-width: 810px) {
|
||||
.desktop-footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ds-container {
|
||||
padding-left: $space-x-small !important;
|
||||
padding-right: $space-x-small !important;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-modul {
|
||||
|
||||
@ -224,8 +224,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
School For Citizens
|
||||
@ -233,8 +232,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&school-for-citizens
|
||||
@ -536,8 +534,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="chip"
|
||||
>
|
||||
<span
|
||||
class="os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em]"
|
||||
style="word-break: break-all;"
|
||||
class="word-break-all os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em] word-break-all"
|
||||
>
|
||||
Our children shall receive education for life.
|
||||
</span>
|
||||
@ -990,7 +987,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
@ -1148,8 +1145,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
School For Citizens
|
||||
@ -1157,8 +1153,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&school-for-citizens
|
||||
@ -1413,8 +1408,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="chip"
|
||||
>
|
||||
<span
|
||||
class="os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em]"
|
||||
style="word-break: break-all;"
|
||||
class="word-break-all os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em] word-break-all"
|
||||
>
|
||||
Our children shall receive education for life.
|
||||
</span>
|
||||
@ -1498,7 +1492,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
@ -1656,8 +1650,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
School For Citizens
|
||||
@ -1665,8 +1658,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&school-for-citizens
|
||||
@ -1940,8 +1932,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="chip"
|
||||
>
|
||||
<span
|
||||
class="os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em]"
|
||||
style="word-break: break-all;"
|
||||
class="word-break-all os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em] word-break-all"
|
||||
>
|
||||
Our children shall receive education for life.
|
||||
</span>
|
||||
@ -2025,7 +2016,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
@ -2278,8 +2269,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
School For Citizens
|
||||
@ -2287,8 +2277,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&school-for-citizens
|
||||
@ -2589,8 +2578,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="chip"
|
||||
>
|
||||
<span
|
||||
class="os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em]"
|
||||
style="word-break: break-all;"
|
||||
class="word-break-all os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em] word-break-all"
|
||||
>
|
||||
Our children shall receive education for life.
|
||||
</span>
|
||||
@ -3043,7 +3031,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
@ -3384,8 +3372,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
Yoga Practice
|
||||
@ -3393,8 +3380,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&yoga-practice
|
||||
@ -4081,7 +4067,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
@ -4239,8 +4225,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
Yoga Practice
|
||||
@ -4248,8 +4233,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&yoga-practice
|
||||
@ -4882,7 +4866,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
@ -5040,8 +5024,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
Yoga Practice
|
||||
@ -5049,8 +5032,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&yoga-practice
|
||||
@ -5702,7 +5684,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
@ -5955,8 +5937,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
Yoga Practice
|
||||
@ -5964,8 +5945,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&yoga-practice
|
||||
@ -6651,7 +6631,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
@ -6992,8 +6972,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
Investigative Journalism
|
||||
@ -7001,8 +6980,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&investigative-journalism
|
||||
@ -7303,8 +7281,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
class="chip"
|
||||
>
|
||||
<span
|
||||
class="os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em]"
|
||||
style="word-break: break-all;"
|
||||
class="word-break-all os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em] word-break-all"
|
||||
>
|
||||
Investigative journalists share ideas and insights and can collaborate.
|
||||
</span>
|
||||
@ -7774,7 +7751,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
@ -8039,8 +8016,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
class="ds-my-small"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all;"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
|
||||
Investigative Journalism
|
||||
@ -8048,8 +8024,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-center ds-text-soft"
|
||||
style="word-break: break-all;"
|
||||
class="ds-text ds-text-center ds-text-soft word-break-all"
|
||||
>
|
||||
|
||||
&investigative-journalism
|
||||
@ -8349,8 +8324,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
class="chip"
|
||||
>
|
||||
<span
|
||||
class="os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em]"
|
||||
style="word-break: break-all;"
|
||||
class="word-break-all os-badge inline-flex w-fit items-center gap-[0.25em] font-semibold text-[var(--color-default-contrast)] bg-[var(--color-default)] text-[0.75rem] py-[0.2em] px-[0.8em] rounded-[2em] word-break-all"
|
||||
>
|
||||
Investigative journalists share ideas and insights and can collaborate.
|
||||
</span>
|
||||
@ -8820,7 +8794,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
style="grid-row-end: span 4; grid-column: 1 / -1;"
|
||||
|
||||
@ -30,13 +30,12 @@
|
||||
<div class="ds-my-small">
|
||||
<!-- group name -->
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin"
|
||||
style="word-break: break-all"
|
||||
class="ds-heading ds-heading-h3 ds-heading-align-center ds-heading-no-margin word-break-all"
|
||||
>
|
||||
{{ groupName }}
|
||||
</h3>
|
||||
<!-- group slug -->
|
||||
<p class="ds-text ds-text-center ds-text-soft" style="word-break: break-all">
|
||||
<p class="ds-text ds-text-center ds-text-soft word-break-all">
|
||||
{{ `&${groupSlug}` }}
|
||||
</p>
|
||||
<!-- group location -->
|
||||
@ -163,7 +162,7 @@
|
||||
</p>
|
||||
<div class="ds-my-xx-small"></div>
|
||||
<div class="chip" align="center">
|
||||
<os-badge style="word-break: break-all">{{ group.about }}</os-badge>
|
||||
<os-badge class="word-break-all">{{ group.about }}</os-badge>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -710,6 +709,9 @@ export default {
|
||||
margin-bottom: $space-small;
|
||||
}
|
||||
}
|
||||
.word-break-all {
|
||||
word-break: break-all;
|
||||
}
|
||||
.collaps-button {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
@ -110,8 +110,14 @@
|
||||
!isMobile && posts.length <= 2 ? 'grid-column-helper' : '',
|
||||
]"
|
||||
>
|
||||
<!-- skeleton placeholders while loading -->
|
||||
<template v-if="$apollo.loading && posts.length === 0">
|
||||
<masonry-grid-item v-for="n in 6" :key="'skeleton-' + n" :imageAspectRatio="1.5">
|
||||
<post-teaser-skeleton />
|
||||
</masonry-grid-item>
|
||||
</template>
|
||||
<!-- news feed -->
|
||||
<template v-if="hasResults">
|
||||
<template v-else-if="hasResults">
|
||||
<masonry-grid-item
|
||||
v-for="post in posts"
|
||||
:key="post.id"
|
||||
@ -160,6 +166,7 @@ import DonationInfo from '~/components/DonationInfo/DonationInfo.vue'
|
||||
import HashtagsFilter from '~/components/HashtagsFilter/HashtagsFilter.vue'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
import PostTeaser from '~/components/PostTeaser/PostTeaser.vue'
|
||||
import PostTeaserSkeleton from '~/components/PostTeaser/PostTeaserSkeleton.vue'
|
||||
import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue'
|
||||
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
|
||||
import HeaderButton from '~/components/FilterMenu/HeaderButton'
|
||||
@ -179,6 +186,7 @@ export default {
|
||||
OsIcon,
|
||||
OsSpinner,
|
||||
PostTeaser,
|
||||
PostTeaserSkeleton,
|
||||
HcEmpty,
|
||||
MasonryGrid,
|
||||
MasonryGridItem,
|
||||
|
||||
@ -445,7 +445,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
>
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
class="tab-navigation"
|
||||
@ -1168,7 +1168,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
>
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
class="tab-navigation"
|
||||
@ -1715,7 +1715,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
>
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
class="tab-navigation"
|
||||
@ -2341,7 +2341,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
>
|
||||
<div
|
||||
class="ds-grid"
|
||||
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
|
||||
style="grid-auto-rows: 2px; row-gap: 2px;"
|
||||
>
|
||||
<div
|
||||
class="tab-navigation"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user