feat(export): implement collection export for ics/rss/widget

This commit is contained in:
lesion 2023-11-03 23:03:53 +01:00
parent c333430ee6
commit a0de5547c7
No known key found for this signature in database
GPG key ID: 352918250B012177
4 changed files with 426 additions and 412 deletions

View file

@ -1,7 +1,6 @@
<template lang="pug"> <template lang="pug">
v-row v-row
v-col(cols=12) v-col(sm=3 cols=12)
span {{ filters }} - {{ meta }}
v-switch( v-switch(
v-if='settings.allow_recurrent_event' v-if='settings.allow_recurrent_event'
v-model='show_recurrent' v-model='show_recurrent'
@ -9,13 +8,12 @@ v-row
inset color='primary' inset color='primary'
hide-details hide-details
:label="$t('event.show_recurrent')") :label="$t('event.show_recurrent')")
v-col.mb-4(cols=12) v-col(sm="5" cols=12)
v-autocomplete.p-0( v-autocomplete.p-0(
:disabled='!!collection'
v-model="filters"
outlined outlined
rounded :label='$t("common.filter")'
:label='$t("common.search")'
:filter='filter'
cache-items
hide-details hide-details
color='primary' color='primary'
hide-selected hide-selected
@ -45,6 +43,29 @@ v-row
v-list-item-content v-list-item-content
v-list-item-title(v-text='item.label') v-list-item-title(v-text='item.label')
v-list-item-subtitle(v-if='item.type ==="place"' v-text='item.label !== "online" && item.address') v-list-item-subtitle(v-if='item.type ==="place"' v-text='item.label !== "online" && item.address')
v-col(sm=4 cols=12)
v-autocomplete.p-0(
:disabled='!!filters.length'
v-model="collection"
outlined
:label='$t("common.collections")'
hide-details
color='primary'
hide-selected
:menu-props="{ maxWidth: '400' }"
:items='collections'
@change='change'
hide-no-data
clearable
:clear-icon='mdiCloseCircle'
item-text='name')
template(v-slot:itsdfems='{ item }')
v-list-item-avatar
v-icon(v-text="item.type === 'place' ? mdiMapMarker : item.type === 'tag' ? mdiTag : mdiCollage")
v-list-item-content
v-list-item-title(v-text='item.label')
v-list-item-subtitle(v-if='item.type ==="place"' v-text='item.label !== "online" && item.address')
</template> </template>
<script> <script>
@ -55,23 +76,23 @@ import debounce from 'lodash/debounce'
export default { export default {
name: 'Search', name: 'Search',
props: { props: {
filters: { type: Object, default: () => ({ }) } value: { type: Object, default: () => ({ }) }
}, },
data () { data () {
return { return {
mdiTag, mdiMapMarker, mdiCloseCircle, mdiCollage, mdiTag, mdiMapMarker, mdiCloseCircle, mdiCollage,
// meta: [],
items: [], items: [],
show_recurrent: this.filters.show_recurrent || false filters: [],
collection: null,
collections: [],
show_recurrent: this.value.show_recurrent || false
} }
}, },
async fetch () {
this.collections = await this.$axios.$get('/collections')
},
computed: { computed: {
...mapState(['settings']), ...mapState(['settings']),
meta: {
get () {
return this.filters
}
}
}, },
methods: { methods: {
filter (item, queryText, itemText) { filter (item, queryText, itemText) {
@ -80,27 +101,31 @@ export default {
}, },
search: debounce(async function(search) { search: debounce(async function(search) {
this.items = await this.$axios.$get(`/event/meta?search=${search.target.value}`) this.items = await this.$axios.$get(`/event/meta?search=${search.target.value}`)
console.error('items ', this.items.length)
}, 100), }, 100),
remove (item) { remove (item) {
console.error(item) // const filters = {
// tags: this.filters.filter(t => t.type === 'tag' && t.label !== item.label).map(t => t.label),
// places: this.filters.filter(p => p.type === 'place' && p.id !== item.id).map(p => p.id),
// show_recurrent: this.show_recurrent
// }
this.filters = this.filters.filter(m => m.type !== item.type || m.type === 'place' ? m.id !== item.id : m.label !== item.label) this.filters = this.filters.filter(m => m.type !== item.type || m.type === 'place' ? m.id !== item.id : m.label !== item.label)
this.$emit('update', filters) // this.$emit('input', filters)
// this.change() this.change()
}, },
change (v, i) { change () {
console.error(v, i) if (this.collection) {
if (!v) return this.filters = []
const collection = v.find(c => c.type === 'collection') this.$emit('input', { collection: this.collection, places: [], tags: [], show_recurrent: this.show_recurrent })
if (collection) { } else {
this.$emit('update', { collection: collection.label, places: [], tags: [] })
return
}
const filters = { const filters = {
tags: v.filter(t => t.type === 'tag').map(t => t.label), tags: this.filters.filter(t => t.type === 'tag').map(t => t.label),
places: v.filter(p => p.type === 'place').map(p => p.id), places: this.filters.filter(p => p.type === 'place').map(p => p.id),
show_recurrent: this.show_recurrent show_recurrent: this.show_recurrent
} }
this.$emit('update', filters) this.$emit('input', filters)
}
} }
} }
} }

View file

@ -125,7 +125,8 @@
"insert_your_address": "Enter your e-mail address", "insert_your_address": "Enter your e-mail address",
"feed_description": "To follow updates from a computer or smartphone without the need to periodically open this site, use RSS feeds. </p>\n\n<p> With RSS feeds you use a special app to receive updates from sites that interest you. It's a good way to follow many sites quickly, without the need to create an account or other complications. </p>\n\n<li> If you have Android, we recommend <a href=\"https://f-droid.org/en/packages/net.frju.flym/\">Flym</a> or Feeder </li>\n<li> For iPhone / iPad you can use <a href=\"https://itunes.apple.com/ua/app/feeds4u/id1038456442?mt=8\"> Feed4U </a> </li>\n<li> For desktop / laptop we recommend Feedbro, to be installed on <a href=\"https://addons.mozilla.org/en-GB/firefox/addon/feedbroreader/\"> Firefox </a> or <a href=\"https://chrome.google.com/webstore/detail/feedbro/mefgmmbdailogpfhfblcnnjfmnpnmdfa\"> Chrome </a>. </li>\n<br/>\nAdding this link to your RSS feed reader will keep you up to date.", "feed_description": "To follow updates from a computer or smartphone without the need to periodically open this site, use RSS feeds. </p>\n\n<p> With RSS feeds you use a special app to receive updates from sites that interest you. It's a good way to follow many sites quickly, without the need to create an account or other complications. </p>\n\n<li> If you have Android, we recommend <a href=\"https://f-droid.org/en/packages/net.frju.flym/\">Flym</a> or Feeder </li>\n<li> For iPhone / iPad you can use <a href=\"https://itunes.apple.com/ua/app/feeds4u/id1038456442?mt=8\"> Feed4U </a> </li>\n<li> For desktop / laptop we recommend Feedbro, to be installed on <a href=\"https://addons.mozilla.org/en-GB/firefox/addon/feedbroreader/\"> Firefox </a> or <a href=\"https://chrome.google.com/webstore/detail/feedbro/mefgmmbdailogpfhfblcnnjfmnpnmdfa\"> Chrome </a>. </li>\n<br/>\nAdding this link to your RSS feed reader will keep you up to date.",
"ical_description": "Computers and smartphones are commonly equipped with a calendar app capable of importing a remote calendar.", "ical_description": "Computers and smartphones are commonly equipped with a calendar app capable of importing a remote calendar.",
"list_description": "If you have a website and want to show a list of events, use the following code" "list_description": "If you have a website and want to show a list of events, use the following code",
"filter_description": "You can filter your export here by tags and place or by a preset collection"
}, },
"register": { "register": {
"description": "Social movements should organize and self-finance.<br/>\n<br/>Before you can publish, <strong> the account must be approved</strong>, consider that <strong> behind this site you will find real people</strong>, so write two lines to let us know what events you would like to publish.", "description": "Social movements should organize and self-finance.<br/>\n<br/>Before you can publish, <strong> the account must be approved</strong>, consider that <strong> behind this site you will find real people</strong>, so write two lines to let us know what events you would like to publish.",

View file

@ -4,13 +4,11 @@ v-container.pa-0.pa-md-3
v-card-title {{$t('common.share')}} v-card-title {{$t('common.share')}}
v-card-text v-card-text
p.text-body-1 {{$t('export.intro')}} p.text-body-1 {{$t('export.intro')}}
v-row v-alert.blue-grey.darken-4.text-body-1.lime--text.text--lighten-3
v-col(:md='2' :cols='12') v-card-title {{$t('common.filter')}}
v-card-title.py-0 {{$t('common.filter')}} v-card-subtitle {{$t('export.filter_description')}}
v-col v-card-text
Search( Search(v-model='filters')
:filters='filters'
@update='f => filters = f')
v-tabs(v-model='type' show-arrows :next-icon='mdiChevronRight' :prev-icon='mdiChevronLeft') v-tabs(v-model='type' show-arrows :next-icon='mdiChevronRight' :prev-icon='mdiChevronLeft')
//- TOFIX //- TOFIX
@ -52,7 +50,7 @@ v-container.pa-0.pa-md-3
v-col.col-12.col-lg-4 v-col.col-12.col-lg-4
v-text-field(v-model='list.title' :label='$t("common.title")') v-text-field(v-model='list.title' :label='$t("common.title")')
v-text-field(v-model='list.maxEvents' type='number' min='1' :label='$t("common.max_events")') v-text-field(v-model='list.maxEvents' type='number' min='1' :label='$t("common.max_events")')
v-switch(v-model='list.theme' inset true-value='dark' false-value='light' :label="$t('admin.is_dark')") v-switch(v-model='list.theme' hide-details inset true-value='dark' false-value='light' :label="$t('admin.is_dark')")
v-switch(v-model='list.sidebar' inset true-value='true' false-value='false' :label="$t('admin.widget')") v-switch(v-model='list.sidebar' inset true-value='true' false-value='false' :label="$t('admin.widget')")
v-col.col-12.col-lg-8 v-col.col-12.col-lg-8
gancio-events(:baseurl='settings.baseurl' gancio-events(:baseurl='settings.baseurl'

View file

@ -75,13 +75,6 @@ const eventController = {
raw: true raw: true
}) })
const collections = await Collection.findAll({
where: {
name: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), 'LIKE', '%' + search + '%'),
},
attributes: [['name', 'label'], 'id'],
raw: true
})
const ret = places.map(p => { const ret = places.map(p => {
p.type = 'place' p.type = 'place'
@ -89,10 +82,7 @@ const eventController = {
}).concat(tags.map(t => { }).concat(tags.map(t => {
t.type = 'tag' t.type = 'tag'
return t return t
}).concat(collections.map(c => { })).sort((a, b) => b.w - a.w).slice(0, 10)
c.type = 'collection'
return c
}))).sort((a, b) => b.w - a.w).slice(0, 10)
return res.json(ret) return res.json(ret)
}, },