mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Merge pull request #2317 from Human-Connection/2253-fix-scroll-layout-issue
2253 fix scroll layout issue
This commit is contained in:
commit
9fd4ad47dd
@ -39,4 +39,5 @@ module.exports = {
|
|||||||
default: () => new Date().toISOString(),
|
default: () => new Date().toISOString(),
|
||||||
},
|
},
|
||||||
language: { type: 'string', allow: [null] },
|
language: { type: 'string', allow: [null] },
|
||||||
|
imageAspectRatio: { type: 'float', default: 1.0 },
|
||||||
}
|
}
|
||||||
|
|||||||
@ -309,7 +309,15 @@ export default {
|
|||||||
},
|
},
|
||||||
Post: {
|
Post: {
|
||||||
...Resolver('Post', {
|
...Resolver('Post', {
|
||||||
undefinedToNull: ['activityId', 'objectId', 'image', 'language', 'pinnedAt', 'pinned'],
|
undefinedToNull: [
|
||||||
|
'activityId',
|
||||||
|
'objectId',
|
||||||
|
'image',
|
||||||
|
'language',
|
||||||
|
'pinnedAt',
|
||||||
|
'pinned',
|
||||||
|
'imageAspectRatio',
|
||||||
|
],
|
||||||
hasMany: {
|
hasMany: {
|
||||||
tags: '-[:TAGGED]->(related:Tag)',
|
tags: '-[:TAGGED]->(related:Tag)',
|
||||||
categories: '-[:CATEGORIZED]->(related:Category)',
|
categories: '-[:CATEGORIZED]->(related:Category)',
|
||||||
|
|||||||
@ -119,6 +119,7 @@ type Post {
|
|||||||
contentExcerpt: String
|
contentExcerpt: String
|
||||||
image: String
|
image: String
|
||||||
imageUpload: Upload
|
imageUpload: Upload
|
||||||
|
imageAspectRatio: Float
|
||||||
visibility: Visibility
|
visibility: Visibility
|
||||||
deleted: Boolean
|
deleted: Boolean
|
||||||
disabled: Boolean
|
disabled: Boolean
|
||||||
@ -182,6 +183,7 @@ type Mutation {
|
|||||||
language: String
|
language: String
|
||||||
categoryIds: [ID]
|
categoryIds: [ID]
|
||||||
contentExcerpt: String
|
contentExcerpt: String
|
||||||
|
imageAspectRatio: Float
|
||||||
): Post
|
): Post
|
||||||
UpdatePost(
|
UpdatePost(
|
||||||
id: ID!
|
id: ID!
|
||||||
@ -194,6 +196,7 @@ type Mutation {
|
|||||||
visibility: Visibility
|
visibility: Visibility
|
||||||
language: String
|
language: String
|
||||||
categoryIds: [ID]
|
categoryIds: [ID]
|
||||||
|
imageAspectRatio: Float
|
||||||
): Post
|
): Post
|
||||||
DeletePost(id: ID!): Post
|
DeletePost(id: ID!): Post
|
||||||
AddPostEmotions(to: _PostInput!, data: _EMOTEDInput!): EMOTED
|
AddPostEmotions(to: _PostInput!, data: _EMOTEDInput!): EMOTED
|
||||||
@ -218,6 +221,7 @@ type Query {
|
|||||||
offset: Int
|
offset: Int
|
||||||
orderBy: [_PostOrdering]
|
orderBy: [_PostOrdering]
|
||||||
filter: _PostFilter
|
filter: _PostFilter
|
||||||
|
imageAspectRatio: Float
|
||||||
): [Post]
|
): [Post]
|
||||||
PostsEmotionsCountByEmotion(postId: ID!, data: _EMOTEDInput!): Int!
|
PostsEmotionsCountByEmotion(postId: ID!, data: _EMOTEDInput!): Int!
|
||||||
PostsEmotionsByCurrentUser(postId: ID!): [String]
|
PostsEmotionsByCurrentUser(postId: ID!): [String]
|
||||||
|
|||||||
@ -19,6 +19,7 @@ export default function create() {
|
|||||||
visibility: 'public',
|
visibility: 'public',
|
||||||
deleted: false,
|
deleted: false,
|
||||||
categoryIds: [],
|
categoryIds: [],
|
||||||
|
imageAspectRatio: 1.333,
|
||||||
}
|
}
|
||||||
args = {
|
args = {
|
||||||
...defaults,
|
...defaults,
|
||||||
|
|||||||
@ -350,15 +350,17 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
author: peterLustig,
|
author: peterLustig,
|
||||||
id: 'p0',
|
id: 'p0',
|
||||||
language: sample(languages),
|
language: sample(languages),
|
||||||
image: faker.image.unsplash.food(),
|
image: faker.image.unsplash.food(300, 169),
|
||||||
categoryIds: ['cat16'],
|
categoryIds: ['cat16'],
|
||||||
|
imageAspectRatio: 300 / 169,
|
||||||
}),
|
}),
|
||||||
factory.create('Post', {
|
factory.create('Post', {
|
||||||
author: bobDerBaumeister,
|
author: bobDerBaumeister,
|
||||||
id: 'p1',
|
id: 'p1',
|
||||||
language: sample(languages),
|
language: sample(languages),
|
||||||
image: faker.image.unsplash.technology(),
|
image: faker.image.unsplash.technology(300, 1500),
|
||||||
categoryIds: ['cat1'],
|
categoryIds: ['cat1'],
|
||||||
|
imageAspectRatio: 300 / 1500,
|
||||||
}),
|
}),
|
||||||
factory.create('Post', {
|
factory.create('Post', {
|
||||||
author: huey,
|
author: huey,
|
||||||
@ -382,8 +384,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
authorId: 'u1',
|
authorId: 'u1',
|
||||||
id: 'p6',
|
id: 'p6',
|
||||||
language: sample(languages),
|
language: sample(languages),
|
||||||
image: faker.image.unsplash.buildings(),
|
image: faker.image.unsplash.buildings(300, 857),
|
||||||
categoryIds: ['cat6'],
|
categoryIds: ['cat6'],
|
||||||
|
imageAspectRatio: 300 / 857,
|
||||||
}),
|
}),
|
||||||
factory.create('Post', {
|
factory.create('Post', {
|
||||||
author: huey,
|
author: huey,
|
||||||
@ -400,8 +403,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
author: louie,
|
author: louie,
|
||||||
id: 'p11',
|
id: 'p11',
|
||||||
language: sample(languages),
|
language: sample(languages),
|
||||||
image: faker.image.unsplash.people(),
|
image: faker.image.unsplash.people(300, 901),
|
||||||
categoryIds: ['cat11'],
|
categoryIds: ['cat11'],
|
||||||
|
imageAspectRatio: 300 / 901,
|
||||||
}),
|
}),
|
||||||
factory.create('Post', {
|
factory.create('Post', {
|
||||||
author: bobDerBaumeister,
|
author: bobDerBaumeister,
|
||||||
@ -413,8 +417,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
author: jennyRostock,
|
author: jennyRostock,
|
||||||
id: 'p14',
|
id: 'p14',
|
||||||
language: sample(languages),
|
language: sample(languages),
|
||||||
image: faker.image.unsplash.objects(),
|
image: faker.image.unsplash.objects(300, 200),
|
||||||
categoryIds: ['cat14'],
|
categoryIds: ['cat14'],
|
||||||
|
imageAspectRatio: 300 / 450,
|
||||||
}),
|
}),
|
||||||
factory.create('Post', {
|
factory.create('Post', {
|
||||||
author: huey,
|
author: huey,
|
||||||
@ -434,8 +439,20 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
const hashtagAndMention1 =
|
const hashtagAndMention1 =
|
||||||
'The new physics of <a class="hashtag" data-hashtag-id="QuantenFlussTheorie" href="/?hashtag=QuantenFlussTheorie">#QuantenFlussTheorie</a> can explain <a class="hashtag" data-hashtag-id="QuantumGravity" href="/?hashtag=QuantumGravity">#QuantumGravity</a>! <a class="mention" data-mention-id="u1" href="/profile/u1">@peter-lustig</a> got that already. ;-)'
|
'The new physics of <a class="hashtag" data-hashtag-id="QuantenFlussTheorie" href="/?hashtag=QuantenFlussTheorie">#QuantenFlussTheorie</a> can explain <a class="hashtag" data-hashtag-id="QuantumGravity" href="/?hashtag=QuantumGravity">#QuantumGravity</a>! <a class="mention" data-mention-id="u1" href="/profile/u1">@peter-lustig</a> got that already. ;-)'
|
||||||
const createPostMutation = gql`
|
const createPostMutation = gql`
|
||||||
mutation($id: ID, $title: String!, $content: String!, $categoryIds: [ID]) {
|
mutation(
|
||||||
CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) {
|
$id: ID
|
||||||
|
$title: String!
|
||||||
|
$content: String!
|
||||||
|
$categoryIds: [ID]
|
||||||
|
$imageAspectRatio: Float
|
||||||
|
) {
|
||||||
|
CreatePost(
|
||||||
|
id: $id
|
||||||
|
title: $title
|
||||||
|
content: $content
|
||||||
|
categoryIds: $categoryIds
|
||||||
|
imageAspectRatio: $imageAspectRatio
|
||||||
|
) {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -449,6 +466,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
title: `Nature Philosophy Yoga`,
|
title: `Nature Philosophy Yoga`,
|
||||||
content: hashtag1,
|
content: hashtag1,
|
||||||
categoryIds: ['cat2'],
|
categoryIds: ['cat2'],
|
||||||
|
imageAspectRatio: 300 / 200,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
@ -458,6 +476,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
title: 'This is post #7',
|
title: 'This is post #7',
|
||||||
content: `${mention1} ${faker.lorem.paragraph()}`,
|
content: `${mention1} ${faker.lorem.paragraph()}`,
|
||||||
categoryIds: ['cat7'],
|
categoryIds: ['cat7'],
|
||||||
|
imageAspectRatio: 300 / 180,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
@ -468,6 +487,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
title: `Quantum Flow Theory explains Quantum Gravity`,
|
title: `Quantum Flow Theory explains Quantum Gravity`,
|
||||||
content: hashtagAndMention1,
|
content: hashtagAndMention1,
|
||||||
categoryIds: ['cat8'],
|
categoryIds: ['cat8'],
|
||||||
|
imageAspectRatio: 300 / 900,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
@ -477,6 +497,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
title: 'This is post #12',
|
title: 'This is post #12',
|
||||||
content: `${mention2} ${faker.lorem.paragraph()}`,
|
content: `${mention2} ${faker.lorem.paragraph()}`,
|
||||||
categoryIds: ['cat12'],
|
categoryIds: ['cat12'],
|
||||||
|
imageAspectRatio: 300 / 200,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
|||||||
30
neo4j/db_manipulation/add_image_aspect_ratio.sh
Executable file
30
neo4j/db_manipulation/add_image_aspect_ratio.sh
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ -z "$NEO4J_USERNAME" ] || [ -z "$NEO4J_PASSWORD" ]; then
|
||||||
|
echo "Please set NEO4J_USERNAME and NEO4J_PASSWORD environment variables."
|
||||||
|
echo "Database manipulation is not possible without connecting to the database."
|
||||||
|
echo "E.g. you could \`cp .env.template .env\` unless you run the script in a docker container"
|
||||||
|
fi
|
||||||
|
|
||||||
|
until echo 'RETURN "Connection successful" as info;' | cypher-shell
|
||||||
|
do
|
||||||
|
echo "Connecting to neo4j failed, trying again..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
for image in uploads/*; do
|
||||||
|
[ -e "$image" ] || continue
|
||||||
|
IMAGE_WIDTH=$( identify -format '%w' "$image" )
|
||||||
|
IMAGE_HEIGHT=$( identify -format '%h' "$image" )
|
||||||
|
IMAGE_ASPECT_RATIO=$(echo | awk "{ print ${IMAGE_WIDTH}/${IMAGE_HEIGHT}}")
|
||||||
|
|
||||||
|
|
||||||
|
echo "$image"
|
||||||
|
echo "$IMAGE_ASPECT_RATIO"
|
||||||
|
echo "
|
||||||
|
match (post:Post {image: '/"${image}"'})
|
||||||
|
set post.imageAspectRatio = "${IMAGE_ASPECT_RATIO}"
|
||||||
|
return post;
|
||||||
|
" | cypher-shell
|
||||||
|
done
|
||||||
@ -198,6 +198,7 @@ describe('ContributionForm.vue', () => {
|
|||||||
id: null,
|
id: null,
|
||||||
categoryIds: ['cat12'],
|
categoryIds: ['cat12'],
|
||||||
imageUpload: null,
|
imageUpload: null,
|
||||||
|
imageAspectRatio: null,
|
||||||
image: null,
|
image: null,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -352,6 +353,7 @@ describe('ContributionForm.vue', () => {
|
|||||||
categoryIds: ['cat12'],
|
categoryIds: ['cat12'],
|
||||||
image,
|
image,
|
||||||
imageUpload: null,
|
imageUpload: null,
|
||||||
|
imageAspectRatio: null,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -7,7 +7,11 @@
|
|||||||
@submit="submit"
|
@submit="submit"
|
||||||
>
|
>
|
||||||
<template slot-scope="{ errors }">
|
<template slot-scope="{ errors }">
|
||||||
<hc-teaser-image :contribution="contribution" @addTeaserImage="addTeaserImage">
|
<hc-teaser-image
|
||||||
|
:contribution="contribution"
|
||||||
|
@addTeaserImage="addTeaserImage"
|
||||||
|
@addImageAspectRatio="addImageAspectRatio"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
v-if="contribution"
|
v-if="contribution"
|
||||||
class="contribution-image"
|
class="contribution-image"
|
||||||
@ -128,6 +132,7 @@ export default {
|
|||||||
title: '',
|
title: '',
|
||||||
content: '',
|
content: '',
|
||||||
teaserImage: null,
|
teaserImage: null,
|
||||||
|
imageAspectRatio: null,
|
||||||
image: null,
|
image: null,
|
||||||
language: null,
|
language: null,
|
||||||
categoryIds: [],
|
categoryIds: [],
|
||||||
@ -190,6 +195,7 @@ export default {
|
|||||||
content,
|
content,
|
||||||
image,
|
image,
|
||||||
teaserImage,
|
teaserImage,
|
||||||
|
imageAspectRatio,
|
||||||
categoryIds,
|
categoryIds,
|
||||||
} = this.form
|
} = this.form
|
||||||
this.loading = true
|
this.loading = true
|
||||||
@ -204,6 +210,7 @@ export default {
|
|||||||
language,
|
language,
|
||||||
image,
|
image,
|
||||||
imageUpload: teaserImage,
|
imageUpload: teaserImage,
|
||||||
|
imageAspectRatio,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
@ -227,6 +234,9 @@ export default {
|
|||||||
addTeaserImage(file) {
|
addTeaserImage(file) {
|
||||||
this.form.teaserImage = file
|
this.form.teaserImage = file
|
||||||
},
|
},
|
||||||
|
addImageAspectRatio(aspectRatio) {
|
||||||
|
this.form.imageAspectRatio = aspectRatio
|
||||||
|
},
|
||||||
categoryIds(categories) {
|
categoryIds(categories) {
|
||||||
return categories.map(c => c.id)
|
return categories.map(c => c.id)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,23 +6,36 @@ const localVue = global.localVue
|
|||||||
|
|
||||||
describe('MasonryGrid', () => {
|
describe('MasonryGrid', () => {
|
||||||
let wrapper
|
let wrapper
|
||||||
let masonryGrid
|
let masonryGridItem
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = mount(MasonryGrid, { localVue })
|
wrapper = mount(MasonryGrid, { localVue })
|
||||||
masonryGrid = wrapper.vm.$children[0]
|
masonryGridItem = wrapper.vm.$children[0]
|
||||||
})
|
})
|
||||||
|
|
||||||
it('adds the "reset-grid-height" class when one or more children are updating', () => {
|
it('adds the "reset-grid-height" class when itemsCalculating is more than 0', () => {
|
||||||
masonryGrid.$emit('calculating-item-height')
|
wrapper.setData({ itemsCalculating: 1 })
|
||||||
|
|
||||||
expect(wrapper.classes()).toContain('reset-grid-height')
|
expect(wrapper.classes()).toContain('reset-grid-height')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('removes the "reset-grid-height" class when all children have completed updating', () => {
|
it('removes the "reset-grid-height" class when itemsCalculating is 0', () => {
|
||||||
wrapper.setData({ itemsCalculating: 1 })
|
wrapper.setData({ itemsCalculating: 0 })
|
||||||
masonryGrid.$emit('finished-calculating-item-height')
|
|
||||||
|
|
||||||
expect(wrapper.classes()).not.toContain('reset-grid-height')
|
expect(wrapper.classes()).not.toContain('reset-grid-height')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('adds 1 to itemsCalculating when a child emits "calculating-item-height"', () => {
|
||||||
|
wrapper.setData({ itemsCalculating: 0 })
|
||||||
|
masonryGridItem.$emit('calculating-item-height')
|
||||||
|
|
||||||
|
expect(wrapper.vm.itemsCalculating).toBe(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('subtracts 1 from itemsCalculating when a child emits "finished-calculating-item-height"', () => {
|
||||||
|
wrapper.setData({ itemsCalculating: 2 })
|
||||||
|
masonryGridItem.$emit('finished-calculating-item-height')
|
||||||
|
|
||||||
|
expect(wrapper.vm.itemsCalculating).toBe(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<ds-grid
|
<ds-grid
|
||||||
:min-column-width="300"
|
|
||||||
v-on:calculating-item-height="startCalculation"
|
v-on:calculating-item-height="startCalculation"
|
||||||
v-on:finished-calculating-item-height="endCalculation"
|
v-on:finished-calculating-item-height="endCalculation"
|
||||||
:class="[itemsCalculating ? 'reset-grid-height' : '']"
|
:class="[itemsCalculating ? 'reset-grid-height' : '']"
|
||||||
@ -27,7 +26,14 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style lang="scss">
|
||||||
|
/* dirty fix to override broken styleguide inline-styles */
|
||||||
|
.ds-grid {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)) !important;
|
||||||
|
gap: 16px !important;
|
||||||
|
grid-auto-rows: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.reset-grid-height {
|
.reset-grid-height {
|
||||||
grid-auto-rows: auto !important;
|
grid-auto-rows: auto !important;
|
||||||
align-items: self-start;
|
align-items: self-start;
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { config, shallowMount } from '@vue/test-utils'
|
import { config, mount } from '@vue/test-utils'
|
||||||
|
|
||||||
import MasonryGridItem from './MasonryGridItem'
|
import MasonryGridItem from './MasonryGridItem'
|
||||||
|
|
||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
@ -9,24 +8,41 @@ config.stubs['ds-grid-item'] = '<span><slot /></span>'
|
|||||||
describe('MasonryGridItem', () => {
|
describe('MasonryGridItem', () => {
|
||||||
let wrapper
|
let wrapper
|
||||||
|
|
||||||
beforeEach(() => {
|
describe('given an imageAspectRatio', () => {
|
||||||
wrapper = shallowMount(MasonryGridItem, { localVue })
|
it('sets the initial rowSpan to 13 when the ratio is higher than 1.3', () => {
|
||||||
wrapper.vm.$parent.$emit = jest.fn()
|
const propsData = { imageAspectRatio: 2 }
|
||||||
|
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||||
|
|
||||||
|
expect(wrapper.vm.rowSpan).toBe(13)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets the initial rowSpan to 15 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)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets the initial rowSpan to 18 when the ratio is between 1 and 0.7', () => {
|
||||||
|
const propsData = { imageAspectRatio: 0.7 }
|
||||||
|
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||||
|
|
||||||
|
expect(wrapper.vm.rowSpan).toBe(18)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets the initial rowSpan to 25 when the ratio is lower than 0.7', () => {
|
||||||
|
const propsData = { imageAspectRatio: 0.3 }
|
||||||
|
wrapper = mount(MasonryGridItem, { localVue, propsData })
|
||||||
|
|
||||||
|
expect(wrapper.vm.rowSpan).toBe(25)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('emits "calculating-item-height" when starting calculation', async () => {
|
describe('given no aspect ratio', () => {
|
||||||
wrapper.vm.calculateItemHeight()
|
it('sets the initial rowSpan to 8 when not given an imageAspectRatio', () => {
|
||||||
await wrapper.vm.$nextTick()
|
wrapper = mount(MasonryGridItem, { localVue })
|
||||||
|
|
||||||
const firstCallArgument = wrapper.vm.$parent.$emit.mock.calls[0][0]
|
expect(wrapper.vm.rowSpan).toBe(8)
|
||||||
expect(firstCallArgument).toBe('calculating-item-height')
|
})
|
||||||
})
|
|
||||||
|
|
||||||
it('emits "finished-calculating-item-height" after the calculation', async () => {
|
|
||||||
wrapper.vm.calculateItemHeight()
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
|
|
||||||
const secondCallArgument = wrapper.vm.$parent.$emit.mock.calls[1][0]
|
|
||||||
expect(secondCallArgument).toBe('finished-calculating-item-height')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,15 +5,33 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
props: {
|
||||||
|
imageAspectRatio: {
|
||||||
|
type: Number,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
rowSpan: 10,
|
rowSpan: this.imageAspectRatio ? getRowSpan(this.imageAspectRatio) : 8,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
calculateItemHeight() {
|
calculateItemHeight() {
|
||||||
this.$parent.$emit('calculating-item-height')
|
this.$parent.$emit('calculating-item-height')
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const gridStyle = this.$parent.$el.style
|
const gridStyle = this.$parent.$el.style
|
||||||
const rowHeight = parseInt(gridStyle.gridAutoRows)
|
const rowHeight = parseInt(gridStyle.gridAutoRows)
|
||||||
@ -27,13 +45,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const image = this.$el.querySelector('img')
|
this.calculateItemHeight()
|
||||||
if (image) {
|
|
||||||
image.onload = () => this.calculateItemHeight()
|
|
||||||
} else {
|
|
||||||
// use timeout to make sure layout is set up before calculation
|
|
||||||
setTimeout(() => this.calculateItemHeight(), 0)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<ds-space margin-bottom="small" />
|
<ds-space margin-bottom="small" />
|
||||||
<!-- Username, Image & Date of Post -->
|
<!-- Username, Image & Date of Post -->
|
||||||
<div>
|
<div class="user-wrapper">
|
||||||
<client-only>
|
<client-only>
|
||||||
<hc-user :user="post.author" :trunc="35" :date-time="post.createdAt" />
|
<hc-user :user="post.author" :trunc="35" :date-time="post.createdAt" />
|
||||||
</client-only>
|
</client-only>
|
||||||
@ -141,10 +141,19 @@ export default {
|
|||||||
this.$emit('unpinPost', post)
|
this.$emit('unpinPost', post)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
const width = this.$el.offsetWidth
|
||||||
|
const height = Math.min(width / this.post.imageAspectRatio, 2000)
|
||||||
|
const imageElement = this.$el.querySelector('.ds-card-image')
|
||||||
|
|
||||||
|
if (imageElement) {
|
||||||
|
imageElement.style.height = `${height}px`
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss">
|
||||||
.ds-card-image img {
|
.ds-card-image img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 2000px;
|
max-height: 2000px;
|
||||||
@ -159,9 +168,21 @@ export default {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
/*.ds-card-footer {
|
> .ds-card-content {
|
||||||
}*/
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* workaround to avoid jumping layout when footer is rendered */
|
||||||
|
> .ds-card-footer {
|
||||||
|
height: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* workaround to avoid jumping layout when hc-user is rendered */
|
||||||
|
.user-wrapper {
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
.content-menu {
|
.content-menu {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|||||||
@ -112,10 +112,12 @@ export default {
|
|||||||
this.showCropper = false
|
this.showCropper = false
|
||||||
const canvas = this.cropper.getCroppedCanvas()
|
const canvas = this.cropper.getCroppedCanvas()
|
||||||
canvas.toBlob(blob => {
|
canvas.toBlob(blob => {
|
||||||
|
const imageAspectRatio = canvas.width / canvas.height
|
||||||
this.setupPreview(canvas)
|
this.setupPreview(canvas)
|
||||||
this.removeCropper()
|
this.removeCropper()
|
||||||
const croppedImageFile = new File([blob], this.file.name, { type: 'image/jpeg' })
|
const croppedImageFile = new File([blob], this.file.name, { type: this.file.type })
|
||||||
this.$emit('addTeaserImage', croppedImageFile)
|
this.$emit('addTeaserImage', croppedImageFile)
|
||||||
|
this.$emit('addImageAspectRatio', imageAspectRatio)
|
||||||
}, 'image/jpeg')
|
}, 'image/jpeg')
|
||||||
},
|
},
|
||||||
setupPreview(canvas) {
|
setupPreview(canvas) {
|
||||||
|
|||||||
@ -148,7 +148,6 @@ export default {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.avatar {
|
.avatar {
|
||||||
display: inline-block;
|
|
||||||
float: left;
|
float: left;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@ -64,6 +64,7 @@ export const postFragment = lang => gql`
|
|||||||
role
|
role
|
||||||
}
|
}
|
||||||
pinnedAt
|
pinnedAt
|
||||||
|
imageAspectRatio
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
export const commentFragment = lang => gql`
|
export const commentFragment = lang => gql`
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export default () => {
|
|||||||
$language: String
|
$language: String
|
||||||
$categoryIds: [ID]
|
$categoryIds: [ID]
|
||||||
$imageUpload: Upload
|
$imageUpload: Upload
|
||||||
|
$imageAspectRatio: Float
|
||||||
) {
|
) {
|
||||||
CreatePost(
|
CreatePost(
|
||||||
title: $title
|
title: $title
|
||||||
@ -16,6 +17,7 @@ export default () => {
|
|||||||
language: $language
|
language: $language
|
||||||
categoryIds: $categoryIds
|
categoryIds: $categoryIds
|
||||||
imageUpload: $imageUpload
|
imageUpload: $imageUpload
|
||||||
|
imageAspectRatio: $imageAspectRatio
|
||||||
) {
|
) {
|
||||||
title
|
title
|
||||||
slug
|
slug
|
||||||
@ -34,6 +36,7 @@ export default () => {
|
|||||||
$imageUpload: Upload
|
$imageUpload: Upload
|
||||||
$categoryIds: [ID]
|
$categoryIds: [ID]
|
||||||
$image: String
|
$image: String
|
||||||
|
$imageAspectRatio: Float
|
||||||
) {
|
) {
|
||||||
UpdatePost(
|
UpdatePost(
|
||||||
id: $id
|
id: $id
|
||||||
@ -43,6 +46,7 @@ export default () => {
|
|||||||
imageUpload: $imageUpload
|
imageUpload: $imageUpload
|
||||||
categoryIds: $categoryIds
|
categoryIds: $categoryIds
|
||||||
image: $image
|
image: $image
|
||||||
|
imageAspectRatio: $imageAspectRatio
|
||||||
) {
|
) {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
@ -55,6 +59,7 @@ export default () => {
|
|||||||
name
|
name
|
||||||
role
|
role
|
||||||
}
|
}
|
||||||
|
imageAspectRatio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
|||||||
@ -16,10 +16,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</ds-grid-item>
|
</ds-grid-item>
|
||||||
<template v-if="hasResults">
|
<template v-if="hasResults">
|
||||||
<masonry-grid-item v-for="post in posts" :key="post.id">
|
<masonry-grid-item
|
||||||
|
v-for="post in posts"
|
||||||
|
:key="post.id"
|
||||||
|
:imageAspectRatio="post.imageAspectRatio"
|
||||||
|
>
|
||||||
<hc-post-card
|
<hc-post-card
|
||||||
:post="post"
|
:post="post"
|
||||||
:width="{ base: '100%', xs: '100%', md: '50%', xl: '33%' }"
|
|
||||||
@removePostFromList="deletePost"
|
@removePostFromList="deletePost"
|
||||||
@pinPost="pinPost"
|
@pinPost="pinPost"
|
||||||
@unpinPost="unpinPost"
|
@unpinPost="unpinPost"
|
||||||
|
|||||||
@ -19,7 +19,11 @@
|
|||||||
<h3>{{ $t('post.moreInfo.titleOfRelatedContributionsSection') }}</h3>
|
<h3>{{ $t('post.moreInfo.titleOfRelatedContributionsSection') }}</h3>
|
||||||
<ds-section>
|
<ds-section>
|
||||||
<masonry-grid v-if="post.relatedContributions && post.relatedContributions.length">
|
<masonry-grid v-if="post.relatedContributions && post.relatedContributions.length">
|
||||||
<masonry-grid-item v-for="relatedPost in post.relatedContributions" :key="relatedPost.id">
|
<masonry-grid-item
|
||||||
|
v-for="relatedPost in post.relatedContributions"
|
||||||
|
:key="relatedPost.id"
|
||||||
|
:imageAspectRatio="relatedPost.imageAspectRatio"
|
||||||
|
>
|
||||||
<hc-post-card
|
<hc-post-card
|
||||||
:post="relatedPost"
|
:post="relatedPost"
|
||||||
:width="{ base: '100%', lg: 1 }"
|
:width="{ base: '100%', lg: 1 }"
|
||||||
|
|||||||
@ -115,7 +115,7 @@ describe('ProfileSlug', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('displays a loading spinner below the posts list', () => {
|
it('displays a loading spinner below the posts list', () => {
|
||||||
expect(wrapper.find('.user-profile-posts-list .ds-spinner').exists()).toBe(true)
|
expect(wrapper.find('.ds-spinner').exists()).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -168,7 +168,7 @@
|
|||||||
</ds-flex-item>
|
</ds-flex-item>
|
||||||
|
|
||||||
<ds-flex-item :width="{ base: '100%', sm: 3, md: 5, lg: 3 }">
|
<ds-flex-item :width="{ base: '100%', sm: 3, md: 5, lg: 3 }">
|
||||||
<masonry-grid class="user-profile-posts-list">
|
<masonry-grid>
|
||||||
<ds-grid-item class="profile-top-navigation" :row-span="3" column-span="fullWidth">
|
<ds-grid-item class="profile-top-navigation" :row-span="3" column-span="fullWidth">
|
||||||
<ds-card class="ds-tab-nav">
|
<ds-card class="ds-tab-nav">
|
||||||
<ul class="Tabs">
|
<ul class="Tabs">
|
||||||
@ -232,7 +232,11 @@
|
|||||||
</ds-grid-item>
|
</ds-grid-item>
|
||||||
|
|
||||||
<template v-if="posts.length">
|
<template v-if="posts.length">
|
||||||
<masonry-grid-item v-for="post in posts" :key="post.id">
|
<masonry-grid-item
|
||||||
|
v-for="post in posts"
|
||||||
|
:key="post.id"
|
||||||
|
:imageAspectRatio="post.imageAspectRatio"
|
||||||
|
>
|
||||||
<hc-post-card
|
<hc-post-card
|
||||||
:post="post"
|
:post="post"
|
||||||
:width="{ base: '100%', md: '100%', xl: '50%' }"
|
:width="{ base: '100%', md: '100%', xl: '50%' }"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user