media improvement
This commit is contained in:
@@ -83,14 +83,6 @@ li {
|
|||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img {
|
|
||||||
width: 100%;
|
|
||||||
max-height: 250px;
|
|
||||||
min-height: 160px;
|
|
||||||
object-fit: cover;
|
|
||||||
object-position: top;
|
|
||||||
aspect-ratio: 1.7778;
|
|
||||||
}
|
|
||||||
|
|
||||||
.place {
|
.place {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
v-card.h-event.event.d-flex(itemscope itemtype="https://schema.org/Event")
|
v-card.h-event.event.d-flex(itemscope itemtype="https://schema.org/Event")
|
||||||
nuxt-link(:to='`/event/${event.slug || event.id}`' itemprop="url")
|
nuxt-link(:to='`/event/${event.slug || event.id}`' itemprop="url")
|
||||||
img.img.u-featured(:src='thumbnail' :alt='alt' :loading='this.lazy?"lazy":"eager"' itemprop="image" :style="{ 'object-position': thumbnailPosition }")
|
MyPicture(:event='event' thumb :lazy='lazy')
|
||||||
v-icon.float-right.mr-1(v-if='event.parentId' color='success' v-text='mdiRepeat')
|
v-icon.float-right.mr-1(v-if='event.parentId' color='success' v-text='mdiRepeat')
|
||||||
.title.p-name(itemprop="name") {{event.title}}
|
.title.p-name(itemprop="name") {{event.title}}
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import clipboard from '../assets/clipboard'
|
import clipboard from '../assets/clipboard'
|
||||||
|
import MyPicture from '~/components/MyPicture'
|
||||||
import { mdiRepeat, mdiPencil, mdiDotsVertical, mdiContentCopy,
|
import { mdiRepeat, mdiPencil, mdiDotsVertical, mdiContentCopy,
|
||||||
mdiCalendarExport, mdiDeleteForever, mdiCalendar, mdiMapMarker } from '@mdi/js'
|
mdiCalendarExport, mdiDeleteForever, mdiCalendar, mdiMapMarker } from '@mdi/js'
|
||||||
|
|
||||||
@@ -58,6 +59,9 @@ export default {
|
|||||||
return { mdiRepeat, mdiPencil, mdiDotsVertical, mdiContentCopy, mdiCalendarExport,
|
return { mdiRepeat, mdiPencil, mdiDotsVertical, mdiContentCopy, mdiCalendarExport,
|
||||||
mdiDeleteForever, mdiMapMarker, mdiCalendar }
|
mdiDeleteForever, mdiMapMarker, mdiCalendar }
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
MyPicture
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
event: { type: Object, default: () => ({}) },
|
event: { type: Object, default: () => ({}) },
|
||||||
lazy: Boolean
|
lazy: Boolean
|
||||||
@@ -65,25 +69,6 @@ export default {
|
|||||||
mixins: [clipboard],
|
mixins: [clipboard],
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['settings']),
|
...mapState(['settings']),
|
||||||
thumbnail () {
|
|
||||||
let path
|
|
||||||
if (this.event.media && this.event.media.length) {
|
|
||||||
path = '/media/thumb/' + this.event.media[0].url
|
|
||||||
} else {
|
|
||||||
path = '/noimg.svg'
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
},
|
|
||||||
alt () {
|
|
||||||
return this.event.media && this.event.media.length ? this.event.media[0].name : ''
|
|
||||||
},
|
|
||||||
thumbnailPosition () {
|
|
||||||
if (this.event.media && this.event.media.length && this.event.media[0].focalpoint) {
|
|
||||||
const focalpoint = this.event.media[0].focalpoint
|
|
||||||
return `${(focalpoint[0] + 1) * 50}% ${(focalpoint[1] + 1) * 50}%`
|
|
||||||
}
|
|
||||||
return 'center center'
|
|
||||||
},
|
|
||||||
is_mine () {
|
is_mine () {
|
||||||
if (!this.$auth.user) {
|
if (!this.$auth.user) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -151,7 +151,7 @@
|
|||||||
"each_month": "Each month",
|
"each_month": "Each month",
|
||||||
"due": "until",
|
"due": "until",
|
||||||
"from": "From",
|
"from": "From",
|
||||||
"image_too_big": "The image can't be bigger than 4 MB",
|
"image_too_big": "The image can't be bigger than 4MB",
|
||||||
"interact_with_me_at": "Interact with me on fediverse at",
|
"interact_with_me_at": "Interact with me on fediverse at",
|
||||||
"follow_me_description": "One of the ways to stay up to date on events published here on {title},\nis following the account <u>{account}</u> from the fediverse, for example via Mastodon, and possibly add resources to an event from there.<br/><br/>\nIf you have never heard of Mastodon and the fediverse we recommend reading <a href='https://www.savjee.be/videos/simply-explained/mastodon-and-fediverse-explained/'>this article</a>.<br/><br/>Enter your instance below (e.g. mastodon.social)",
|
"follow_me_description": "One of the ways to stay up to date on events published here on {title},\nis following the account <u>{account}</u> from the fediverse, for example via Mastodon, and possibly add resources to an event from there.<br/><br/>\nIf you have never heard of Mastodon and the fediverse we recommend reading <a href='https://www.savjee.be/videos/simply-explained/mastodon-and-fediverse-explained/'>this article</a>.<br/><br/>Enter your instance below (e.g. mastodon.social)",
|
||||||
"interact_with_me": "Follow me",
|
"interact_with_me": "Follow me",
|
||||||
@@ -159,7 +159,11 @@
|
|||||||
"import_URL": "Import from URL",
|
"import_URL": "Import from URL",
|
||||||
"import_ICS": "Import from ICS",
|
"import_ICS": "Import from ICS",
|
||||||
"ics": "ICS",
|
"ics": "ICS",
|
||||||
"import_description": "You can import events from other platforms and other instances through standard formats (ics and h-event)"
|
"import_description": "You can import events from other platforms and other instances through standard formats (ics and h-event)",
|
||||||
|
"alt_text_description": "Description for people with visual impairments",
|
||||||
|
"choose_focal_point": "Choose the focal point",
|
||||||
|
"remove_media_confirmation": "Do you confirm the image removal?",
|
||||||
|
"download_flyer": "Download flyer"
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"place_description": "If you have gotten the place or address wrong, you can change it.<br/>All current and past events associated with this place will change address.",
|
"place_description": "If you have gotten the place or address wrong, you can change it.<br/>All current and past events associated with this place will change address.",
|
||||||
|
|||||||
@@ -151,7 +151,7 @@
|
|||||||
"each_month": "Ogni mese",
|
"each_month": "Ogni mese",
|
||||||
"due": "alle",
|
"due": "alle",
|
||||||
"from": "Dalle",
|
"from": "Dalle",
|
||||||
"image_too_big": "L'immagine non può essere più grande di 4 MB",
|
"image_too_big": "L'immagine non può essere più grande di 4MB",
|
||||||
"interact_with_me": "Seguimi dal fediverso",
|
"interact_with_me": "Seguimi dal fediverso",
|
||||||
"follow_me_description": "Tra i vari modi di rimanere aggiornati degli eventi pubblicati qui su {title},\npuoi seguire l'account <u>{account}</u> dal fediverso, ad esempio via Mastodon, ed eventualmente aggiungere risorse ad un evento da lì.<br/><br/>\nSe non hai mai sentito parlare di Mastodon e del fediverso ti consigliamo di leggere <a href='https://cagizero.wordpress.com/2018/10/25/cose-mastodon/'>questo articolo</a>.<br/><br/> Inserisci la tua istanza qui sotto (es. mastodon.cisti.org o mastodon.bida.im)",
|
"follow_me_description": "Tra i vari modi di rimanere aggiornati degli eventi pubblicati qui su {title},\npuoi seguire l'account <u>{account}</u> dal fediverso, ad esempio via Mastodon, ed eventualmente aggiungere risorse ad un evento da lì.<br/><br/>\nSe non hai mai sentito parlare di Mastodon e del fediverso ti consigliamo di leggere <a href='https://cagizero.wordpress.com/2018/10/25/cose-mastodon/'>questo articolo</a>.<br/><br/> Inserisci la tua istanza qui sotto (es. mastodon.cisti.org o mastodon.bida.im)",
|
||||||
"only_future": "solo eventi futuri",
|
"only_future": "solo eventi futuri",
|
||||||
@@ -160,9 +160,10 @@
|
|||||||
"import_URL": "Importa da URL (ics o h-event)",
|
"import_URL": "Importa da URL (ics o h-event)",
|
||||||
"ics": "ICS",
|
"ics": "ICS",
|
||||||
"import_description": "Puoi importare eventi da altre piattaforme e da altre istanze attraverso i formati standard (ics e h-event)",
|
"import_description": "Puoi importare eventi da altre piattaforme e da altre istanze attraverso i formati standard (ics e h-event)",
|
||||||
"alt_text_description": "Descrizione per utenti con disabilità visive",
|
"alt_text_description": "Descrizione per persone con disabilità visive",
|
||||||
"choose_focal_point": "Scegli il punto centrale cliccando",
|
"choose_focal_point": "Scegli il punto centrale cliccando",
|
||||||
"remove_media_confirmation": "Confermi l'eliminazione dell'immagine?"
|
"remove_media_confirmation": "Confermi l'eliminazione dell'immagine?",
|
||||||
|
"download_flyer": "Scarica volantino"
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"place_description": "Nel caso in cui un luogo sia errato o cambi indirizzo, puoi modificarlo.<br/>Considera che tutti gli eventi associati a questo luogo cambieranno indirizzo (anche quelli passati).",
|
"place_description": "Nel caso in cui un luogo sia errato o cambi indirizzo, puoi modificarlo.<br/>Considera che tutti gli eventi associati a questo luogo cambieranno indirizzo (anche quelli passati).",
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ module.exports = {
|
|||||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
|
||||||
],
|
],
|
||||||
link: [{ rel: 'icon', type: 'image/png', href: '/logo.png' }],
|
link: [{ rel: 'icon', type: 'image/png', href: '/logo.png' }],
|
||||||
link: [{ rel: 'preload', type: 'image/png', href: '/logo.png', as: 'image' }],
|
|
||||||
script: [{ src: '/gancio-events.es.js', async: true, body: true }],
|
script: [{ src: '/gancio-events.es.js', async: true, body: true }],
|
||||||
},
|
},
|
||||||
dev: isDev,
|
dev: isDev,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
v-col.col-12.col-sm-4
|
v-col.col-12.col-sm-4
|
||||||
p {{$t('event.choose_focal_point')}}
|
p {{$t('event.choose_focal_point')}}
|
||||||
img.img.d-none.d-sm-block(v-if='mediaPreview'
|
img.mediaPreview.d-none.d-sm-block(v-if='mediaPreview'
|
||||||
:src='mediaPreview' :style="{ 'object-position': position }")
|
:src='mediaPreview' :style="{ 'object-position': position }")
|
||||||
|
|
||||||
v-textarea.mt-4(type='text'
|
v-textarea.mt-4(type='text'
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
v-btn(text color='primary' @click='openMediaDetails = true') {{$t('common.edit')}}
|
v-btn(text color='primary' @click='openMediaDetails = true') {{$t('common.edit')}}
|
||||||
v-btn(text color='error' @click='remove') {{$t('common.remove')}}
|
v-btn(text color='error' @click='remove') {{$t('common.remove')}}
|
||||||
div(v-if='mediaPreview')
|
div(v-if='mediaPreview')
|
||||||
img.img.col-12.ml-3(:src='mediaPreview' :style="{ 'object-position': savedPosition }")
|
img.mediaPreview.col-12.ml-3(:src='mediaPreview' :style="{ 'object-position': savedPosition }")
|
||||||
span.float-right {{event.media[0].name}}
|
span.float-right {{event.media[0].name}}
|
||||||
v-file-input(
|
v-file-input(
|
||||||
v-else
|
v-else
|
||||||
@@ -53,7 +53,7 @@ export default {
|
|||||||
name: 'MediaInput',
|
name: 'MediaInput',
|
||||||
props: {
|
props: {
|
||||||
value: { type: Object, default: () => ({ image: null }) },
|
value: { type: Object, default: () => ({ image: null }) },
|
||||||
event: { type: Object, default: () => {} }
|
event: { type: Object, default: () => ({}) }
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -142,7 +142,7 @@ export default {
|
|||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img {
|
.mediaPreview {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
object-position: top;
|
object-position: top;
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
v-row
|
v-row
|
||||||
v-col(cols=12 md=6)
|
v-col(cols=12 md=6)
|
||||||
v-combobox(ref='place'
|
v-combobox(ref='place'
|
||||||
:rules="[$validators.required('common.where')]"
|
:rules="[$validators.required('common.where')]"
|
||||||
:label="$t('common.where')"
|
:label="$t('common.where')"
|
||||||
:hint="$t('event.where_description')"
|
:hint="$t('event.where_description')"
|
||||||
:search-input.sync="placeName"
|
:search-input.sync="placeName"
|
||||||
:prepend-icon='mdiMapMarker'
|
:prepend-icon='mdiMapMarker'
|
||||||
persistent-hint
|
persistent-hint
|
||||||
:value="value.name"
|
:value="value.name"
|
||||||
:items="filteredPlaces"
|
:items="filteredPlaces"
|
||||||
no-filter
|
no-filter
|
||||||
item-text='name'
|
item-text='name'
|
||||||
@change='selectPlace')
|
@change='selectPlace')
|
||||||
template(v-slot:item="{ item, attrs, on }")
|
template(v-slot:item="{ item, attrs, on }")
|
||||||
v-list-item(v-bind='attrs' v-on='on')
|
v-list-item(v-bind='attrs' v-on='on')
|
||||||
v-list-item-content(two-line v-if='item.create')
|
v-list-item-content(two-line v-if='item.create')
|
||||||
v-list-item-title <v-icon color='primary' v-text='mdiPlus' :aria-label='add'></v-icon> {{item.name}}
|
v-list-item-title <v-icon color='primary' v-text='mdiPlus' :aria-label='$t("common.add")'></v-icon> {{item.name}}
|
||||||
v-list-item-content(two-line v-else)
|
v-list-item-content(two-line v-else)
|
||||||
v-list-item-title(v-text='item.name')
|
v-list-item-title(v-text='item.name')
|
||||||
v-list-item-subtitle(v-text='item.address')
|
v-list-item-subtitle(v-text='item.address')
|
||||||
|
|
||||||
v-col(cols=12 md=6)
|
v-col(cols=12 md=6)
|
||||||
v-text-field(ref='address'
|
v-text-field(ref='address'
|
||||||
:prepend-icon='mdiMap'
|
:prepend-icon='mdiMap'
|
||||||
:disabled='disableAddress'
|
:disabled='disableAddress'
|
||||||
:rules="[ v => disableAddress ? true : $validators.required('common.address')(v)]"
|
:rules="[ v => disableAddress ? true : $validators.required('common.address')(v)]"
|
||||||
:label="$t('common.address')"
|
:label="$t('common.address')"
|
||||||
@change="changeAddress"
|
@change="changeAddress"
|
||||||
:value="value.address")
|
:value="value.address")
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@@ -61,8 +61,7 @@ export default {
|
|||||||
if (tmpName === placeName) { nameMatch = true }
|
if (tmpName === placeName) { nameMatch = true }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (tmpAddress.includes(placeName)) { return true }
|
return tmpAddress.includes(placeName)
|
||||||
return false
|
|
||||||
})
|
})
|
||||||
if (!nameMatch) {
|
if (!nameMatch) {
|
||||||
matches.unshift({ create: true, name: this.placeName })
|
matches.unshift({ create: true, name: this.placeName })
|
||||||
|
|||||||
@@ -11,13 +11,7 @@ v-container#event.pa-0.pa-sm-2
|
|||||||
v-row
|
v-row
|
||||||
v-col.col-12.col-lg-8
|
v-col.col-12.col-lg-8
|
||||||
//- fake image to use u-featured in h-event microformat
|
//- fake image to use u-featured in h-event microformat
|
||||||
img.u-featured(v-show='false' v-if='hasMedia' :src='event | mediaURL' itemprop="image")
|
MyPicture(v-if='hasMedia' :event='event')
|
||||||
v-img.main_image.mb-3(
|
|
||||||
contain
|
|
||||||
:alt='event | mediaURL("alt")'
|
|
||||||
:src='event | mediaURL'
|
|
||||||
:lazy-src='event | mediaURL("thumb")'
|
|
||||||
v-if='hasMedia')
|
|
||||||
.p-description.text-body-1.pa-3.rounded(v-if='!hasMedia && event.description' itemprop='description' v-html='event.description')
|
.p-description.text-body-1.pa-3.rounded(v-if='!hasMedia && event.description' itemprop='description' v-html='event.description')
|
||||||
|
|
||||||
v-col.col-12.col-lg-4
|
v-col.col-12.col-lg-4
|
||||||
@@ -55,6 +49,9 @@ v-container#event.pa-0.pa-sm-2
|
|||||||
v-btn.ml-2(large icon :title="$t('common.add_to_calendar')" color='primary' :aria-label="$t('common.add_to_calendar')"
|
v-btn.ml-2(large icon :title="$t('common.add_to_calendar')" color='primary' :aria-label="$t('common.add_to_calendar')"
|
||||||
:href='`/api/event/${event.slug || event.id}.ics`')
|
:href='`/api/event/${event.slug || event.id}.ics`')
|
||||||
v-icon(v-text='mdiCalendarExport')
|
v-icon(v-text='mdiCalendarExport')
|
||||||
|
v-btn.ml-2(v-if='hasMedia' large icon :title="$t('event.download_flyer')" color='primary' :aria-label="$t('event.download_flyer')"
|
||||||
|
:href='event | mediaURL')
|
||||||
|
v-icon(v-text='mdiFileDownloadOutline')
|
||||||
|
|
||||||
.p-description.text-body-1.pa-3.rounded(v-if='hasMedia && event.description' itemprop='description' v-html='event.description')
|
.p-description.text-body-1.pa-3.rounded(v-if='hasMedia && event.description' itemprop='description' v-html='event.description')
|
||||||
|
|
||||||
@@ -133,10 +130,11 @@ import { mapState } from 'vuex'
|
|||||||
import get from 'lodash/get'
|
import get from 'lodash/get'
|
||||||
import moment from 'dayjs'
|
import moment from 'dayjs'
|
||||||
import clipboard from '../../assets/clipboard'
|
import clipboard from '../../assets/clipboard'
|
||||||
|
import MyPicture from '~/components/MyPicture'
|
||||||
const htmlToText = require('html-to-text')
|
const htmlToText = require('html-to-text')
|
||||||
|
|
||||||
import { mdiArrowLeft, mdiArrowRight, mdiDotsVertical, mdiCodeTags, mdiClose,
|
import { mdiArrowLeft, mdiArrowRight, mdiDotsVertical, mdiCodeTags, mdiClose,
|
||||||
mdiEye, mdiEyeOff, mdiDelete, mdiRepeat, mdiLock,
|
mdiEye, mdiEyeOff, mdiDelete, mdiRepeat, mdiLock, mdiFileDownloadOutline,
|
||||||
mdiCalendarExport, mdiCalendar, mdiContentCopy, mdiMapMarker } from '@mdi/js'
|
mdiCalendarExport, mdiCalendar, mdiContentCopy, mdiMapMarker } from '@mdi/js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -145,8 +143,9 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
EventAdmin: () => import(/* webpackChunkName: "event" */'./eventAdmin'),
|
EventAdmin: () => import(/* webpackChunkName: "event" */'./eventAdmin'),
|
||||||
EmbedEvent: () => import(/* webpackChunkName: "event" */'./embedEvent'),
|
EmbedEvent: () => import(/* webpackChunkName: "event" */'./embedEvent'),
|
||||||
|
MyPicture
|
||||||
},
|
},
|
||||||
async asyncData ({ $axios, params, error, store }) {
|
async asyncData ({ $axios, params, error }) {
|
||||||
try {
|
try {
|
||||||
const event = await $axios.$get(`/event/${params.slug}`)
|
const event = await $axios.$get(`/event/${params.slug}`)
|
||||||
return { event }
|
return { event }
|
||||||
@@ -156,7 +155,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
mdiArrowLeft, mdiArrowRight, mdiDotsVertical, mdiCodeTags, mdiCalendarExport, mdiCalendar,
|
mdiArrowLeft, mdiArrowRight, mdiDotsVertical, mdiCodeTags, mdiCalendarExport, mdiCalendar, mdiFileDownloadOutline,
|
||||||
mdiMapMarker, mdiContentCopy, mdiClose, mdiDelete, mdiEye, mdiEyeOff, mdiRepeat, mdiLock,
|
mdiMapMarker, mdiContentCopy, mdiClose, mdiDelete, mdiEye, mdiEyeOff, mdiRepeat, mdiLock,
|
||||||
currentAttachment: 0,
|
currentAttachment: 0,
|
||||||
event: {},
|
event: {},
|
||||||
@@ -330,11 +329,4 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
|
||||||
.main_image {
|
|
||||||
margin: 0 auto;
|
|
||||||
border-radius: 5px;
|
|
||||||
transition: max-height 0.2s;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -12,48 +12,43 @@ try {
|
|||||||
|
|
||||||
const DiskStorage = {
|
const DiskStorage = {
|
||||||
_handleFile (req, file, cb) {
|
_handleFile (req, file, cb) {
|
||||||
const filename = crypto.randomBytes(16).toString('hex') + '.jpg'
|
const filename = crypto.randomBytes(16).toString('hex')
|
||||||
const finalPath = path.resolve(config.upload_path, filename)
|
const sharpStream = sharp({ failOnError: true })
|
||||||
const thumbPath = path.resolve(config.upload_path, 'thumb', filename)
|
const promises = [
|
||||||
const outStream = fs.createWriteStream(finalPath)
|
sharpStream.clone().resize(500, null, { withoutEnlargement: true }).jpeg({ quality: 90, mozjpeg: true }).toFile(path.resolve(config.upload_path, 'thumb', filename + '.jpg')),
|
||||||
const thumbStream = fs.createWriteStream(thumbPath)
|
sharpStream.clone().resize(500).webp({ quality: 90, alphaQuality: 0, effort: 6 }).toFile(path.resolve(config.upload_path, 'thumb', filename + '.webp')),
|
||||||
|
sharpStream.clone().resize(1200, null, { withoutEnlargement: true } ).jpeg({ quality: 98, mozjpeg: true }).toFile(path.resolve(config.upload_path, filename + '.jpg')),
|
||||||
|
sharpStream.clone().resize(1200).webp({ quality: 98, alphaQuality: 0, effor: 6 }).toFile(path.resolve(config.upload_path, filename + '.webp')),
|
||||||
|
sharpStream.clone()
|
||||||
|
.resize(6)
|
||||||
|
.png({ quality: 20, palette: true, alphaQuality: 0, effort: 6})
|
||||||
|
.toBuffer()
|
||||||
|
.then(buffer => buffer.toString('base64'))
|
||||||
|
]
|
||||||
|
|
||||||
const resizer = sharp().resize(1200).jpeg({ quality: 98 })
|
file.stream.pipe(sharpStream)
|
||||||
const thumbnailer = sharp().resize(500).jpeg({ quality: 98 })
|
Promise.all(promises)
|
||||||
let onError = false
|
.then(res => {
|
||||||
const err = e => {
|
const info = res[2]
|
||||||
if (onError) {
|
const preview = res[4]
|
||||||
log.error('[UPLOAD]', err)
|
console.error(preview)
|
||||||
return
|
cb(null, {
|
||||||
}
|
destination: config.upload_path,
|
||||||
onError = true
|
filename: filename + '.jpg',
|
||||||
log.error('[UPLOAD]', e)
|
path: path.resolve(config.upload_path, filename + '.jpg'),
|
||||||
req.err = e
|
height: info.height,
|
||||||
cb(null)
|
width: info.width,
|
||||||
}
|
size: info.size,
|
||||||
|
preview
|
||||||
file.stream
|
})
|
||||||
.pipe(thumbnailer)
|
})
|
||||||
.on('error', err)
|
.catch(err => {
|
||||||
.pipe(thumbStream)
|
console.error(err)
|
||||||
.on('error', err)
|
req.err = err
|
||||||
|
cb(null)
|
||||||
file.stream
|
|
||||||
.pipe(resizer)
|
|
||||||
.on('error', err)
|
|
||||||
.pipe(outStream)
|
|
||||||
.on('error', err)
|
|
||||||
|
|
||||||
outStream.on('finish', () => {
|
|
||||||
cb(null, {
|
|
||||||
destination: config.upload_path,
|
|
||||||
filename,
|
|
||||||
path: finalPath,
|
|
||||||
size: outStream.bytesWritten
|
|
||||||
})
|
})
|
||||||
})
|
|
||||||
},
|
},
|
||||||
_removeFile (req, file, cb) {
|
_removeFile (_req, file, cb) {
|
||||||
delete file.destination
|
delete file.destination
|
||||||
delete file.filename
|
delete file.filename
|
||||||
fs.unlink(file.path, cb)
|
fs.unlink(file.path, cb)
|
||||||
|
|||||||
@@ -22,18 +22,22 @@
|
|||||||
|
|
||||||
function when (event) {
|
function when (event) {
|
||||||
return new Date(event.start_datetime*1000)
|
return new Date(event.start_datetime*1000)
|
||||||
.toLocaleDateString(undefined,
|
.toLocaleDateString(undefined,
|
||||||
{
|
{
|
||||||
weekday: 'long',
|
weekday: 'long',
|
||||||
month: 'short',
|
month: 'short',
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
hour: '2-digit',
|
hour: '2-digit',
|
||||||
minute: '2-digit'
|
minute: '2-digit'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function thumbnail(event) {
|
function thumbnail(event, format) {
|
||||||
return `${baseurl}/media/thumb/${event.media[0].url}`
|
const imgPath = event.media[0].url
|
||||||
|
if (format === 'webp') {
|
||||||
|
return `${baseurl}/media/thumb/${imgPath.replace(/.jpg$/, '.webp')}`
|
||||||
|
}
|
||||||
|
return `${baseurl}/media/thumb/${imgPath}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function position(event) {
|
function position(event) {
|
||||||
@@ -49,7 +53,11 @@
|
|||||||
{#if event}
|
{#if event}
|
||||||
<a href='{baseurl}/event/{event.slug || event.id}' class='card' target='_blank'>
|
<a href='{baseurl}/event/{event.slug || event.id}' class='card' target='_blank'>
|
||||||
{#if event.media.length}
|
{#if event.media.length}
|
||||||
<img src="{thumbnail(event)}" alt="{event.media[0].name}" style="object-position: {position(event)}; aspect-ratio=1.7778;">
|
|
||||||
|
<picture>
|
||||||
|
<source srcset="{thumbnail(event, 'webp')}" type='image/webp' />
|
||||||
|
<img src="{thumbnail(event)}" alt="{event.media[0].name}" style="object-position: {position(event)}; aspect-ratio=1.7778;">
|
||||||
|
</picture>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<strong>{event.title}</strong>
|
<strong>{event.title}</strong>
|
||||||
|
|||||||
Reference in New Issue
Block a user