mirror of
https://framagit.org/les/gancio.git
synced 2025-01-31 16:42:22 +01:00
keep migrating to vuetify
This commit is contained in:
parent
539c0fa933
commit
3abb39f62b
24 changed files with 1382 additions and 1389 deletions
|
@ -1,6 +1,7 @@
|
|||
html, body {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: orange;
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
li {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
v-calendar(
|
||||
title-position='left'
|
||||
:is-dark="settings['theme.is_dark']"
|
||||
:columns="$screens({ default: 1, md: 2 })"
|
||||
:columns="2"
|
||||
@update:from-page='updatePage'
|
||||
:locale='$i18n.locale'
|
||||
:attributes='attributes'
|
||||
|
@ -21,7 +21,7 @@ import { take, get } from 'lodash'
|
|||
export default {
|
||||
name: 'Calendar',
|
||||
props: {
|
||||
events: { type: Array, default: [] }
|
||||
events: { type: Array, default: () => [] }
|
||||
},
|
||||
data () {
|
||||
const month = dayjs().month() + 1
|
||||
|
@ -35,13 +35,14 @@ export default {
|
|||
|
||||
// TODO: could be better
|
||||
attributes () {
|
||||
return []
|
||||
const colors = ['blue', 'orange', 'yellow', 'teal', 'indigo', 'green', 'red', 'purple', 'pink', 'gray']
|
||||
const tags = take(this.tags, 10).map(t => t.tag)
|
||||
let attributes = []
|
||||
attributes.push({ key: 'today', dates: new Date(), highlight: { color: 'green', fillMode: 'outline' } })
|
||||
|
||||
function getColor (event) {
|
||||
const color = { class: 'vc-rounded-full', color: 'blue', fillMode: 'outline' }
|
||||
const color = { class: 'vc-rounded-full', color: 'blue', fillMode: 'normal' }
|
||||
const tag = get(event, 'tags[0]')
|
||||
if (!tag) { return color }
|
||||
const idx = tags.indexOf(tag)
|
||||
|
|
|
@ -1,78 +1,83 @@
|
|||
<template lang="pug">
|
||||
<template lang="pug" functional>
|
||||
v-card.h-event.event.mt-1
|
||||
nuxt-link(:to='`/event/${event.id}`')
|
||||
v-img.align-end.white--text(:src="`/media/thumb/${event.image_path}`"
|
||||
gradient="to bottom, rgba(0,0,0,.1), rgba(0,0,0,.7), rgba(0,0,0,.9)"
|
||||
height="250" position="top top")
|
||||
v-card-title.text-h5 {{event.title}}
|
||||
template(v-if='props.show')
|
||||
nuxt-link(:to='`/event/${props.event.id}`')
|
||||
v-img.align-end.white--text(:src="`/media/thumb/${props.event.image_path}`"
|
||||
gradient="to bottom, rgba(0,0,0,.1), rgba(0,0,0,.7), rgba(0,0,0,.9)"
|
||||
height="250" position="top top")
|
||||
v-card-title.text-h5.p-name {{props.event.title}}
|
||||
|
||||
v-card-text
|
||||
v-card-text
|
||||
v-icon.float-right(v-if='props.event.parentId' color='success') mdi-repeat
|
||||
//- time.text-h6.dt-start(:datetime='props.event.start_datetime|unixFormat("YYYY-MM-DD HH:mm")') <v-icon>mdi-event</v-icon> {{ event|when }}
|
||||
.d-none.dt-end {{props.event.end_datetime|unixFormat('YYYY-MM-DD HH:mm')}}
|
||||
v-btn.d-block.text-h6.p-location(text color='primary' big @click="$emit('placeclick', props.event.place.id)") <v-icon>mdi-map-marker</v-icon> {{props.event.place.name}}
|
||||
|
||||
time.text-h6(:datetime='event.start_datetime|unixFormat("YYYY-MM-DD HH:mm")') <v-icon>mdi-event</v-icon> {{ event|when }}
|
||||
v-btn.d-block.text-h6(text color='primary' big @click="$emit('placeclick', event.place.id)") <v-icon>mdi-map-marker</v-icon> {{event.place.name}}
|
||||
v-card-actions
|
||||
v-chip.ml-1(v-for='tag in props.event.tags' link
|
||||
:key='tag' outlined color='primary' @click="$emit('tagclick',tag)") {{tag}}
|
||||
v-spacer
|
||||
|
||||
v-card-actions
|
||||
v-chip.ml-1(v-for='tag in event.tags' link
|
||||
:key='tag' outlined color='primary' @click="$emit('tagclick',tag)") {{tag}}
|
||||
v-spacer
|
||||
v-menu(offset-y)
|
||||
template(v-slot:activator="{on}")
|
||||
v-btn(icon v-on='on' color='primary')
|
||||
v-icon mdi-dots-vertical
|
||||
v-list(dense)
|
||||
v-list-item-group
|
||||
v-list-item(v-clipboard:success='copyLink'
|
||||
v-clipboard:copy='`${parent.settings.baseurl}/event/${props.event.id}`')
|
||||
v-list-item-icon
|
||||
v-icon mdi-content-copy
|
||||
v-list-item-content
|
||||
v-list-item-title {{parent.$t('common.copy_link')}}
|
||||
v-list-item(:href='`/api/event/${props.event.id}.ics`')
|
||||
v-list-item-icon
|
||||
v-icon mdi-calendar-export
|
||||
v-list-item-content
|
||||
v-list-item-title {{parent.$t('common.add_to_calendar')}}
|
||||
|
||||
v-menu(offset-y)
|
||||
template(v-slot:activator="{on}")
|
||||
v-btn(icon v-on='on' color='primary')
|
||||
v-icon mdi-dots-vertical
|
||||
v-list(dense)
|
||||
v-list-item-group
|
||||
v-list-item(v-clipboard:success='copyLink'
|
||||
v-clipboard:copy='`${settings.baseurl}/event/${event.id}`')
|
||||
v-list-item-icon
|
||||
v-icon mdi-content-copy
|
||||
v-list-item-content
|
||||
v-list-item-title {{$t('common.copy_link')}}
|
||||
v-list-item(:href='`/api/event/${event.id}.ics`')
|
||||
v-list-item-icon
|
||||
v-icon mdi-calendar-export
|
||||
v-list-item-content
|
||||
v-list-item-title {{$t('common.add_to_calendar')}}
|
||||
</template>
|
||||
<script>
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
// import { mapState, mapActions } from 'vuex'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
event: { type: Object, default: () => ({}) }
|
||||
},
|
||||
computed: {
|
||||
...mapState(['settings']),
|
||||
show_footer () {
|
||||
return (this.event.tags.length || this.event.resources.length)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['setSearchTags', 'setSearchPlaces']),
|
||||
copyLink () {
|
||||
this.$root.$message('common.copied', { color: 'success' })
|
||||
},
|
||||
addTag (tag) {
|
||||
if (this.filters.tags.includes(tag)) {
|
||||
this.setSearchTags(this.filters.tags.filter(t => t !== tag))
|
||||
} else {
|
||||
this.setSearchTags(this.filters.tags.concat([tag]))
|
||||
}
|
||||
},
|
||||
addPlace () {
|
||||
const place = this.event.place.id
|
||||
if (this.filters.places.includes(place)) {
|
||||
this.setSearchPlaces(this.filters.places.filter(p => p !== place))
|
||||
} else {
|
||||
this.setSearchPlaces(this.filters.places.concat(place))
|
||||
}
|
||||
}
|
||||
event: { type: Object, default: () => ({}) },
|
||||
show: { type: Boolean }
|
||||
}
|
||||
// computed: {
|
||||
// ...mapState(['settings']),
|
||||
// show_footer () {
|
||||
// return (this.event.tags.length || this.event.resources.length)
|
||||
// }
|
||||
// },
|
||||
// methods: {
|
||||
// ...mapActions(['setSearchTags', 'setSearchPlaces']),
|
||||
// copyLink () {
|
||||
// this.$root.$message('common.copied', { color: 'success' })
|
||||
// },
|
||||
// addTag (tag) {
|
||||
// if (this.filters.tags.includes(tag)) {
|
||||
// this.setSearchTags(this.filters.tags.filter(t => t !== tag))
|
||||
// } else {
|
||||
// this.setSearchTags(this.filters.tags.concat([tag]))
|
||||
// }
|
||||
// },
|
||||
// addPlace () {
|
||||
// const place = this.event.place.id
|
||||
// if (this.filters.places.includes(place)) {
|
||||
// this.setSearchPlaces(this.filters.places.filter(p => p !== place))
|
||||
// } else {
|
||||
// this.setSearchPlaces(this.filters.places.concat(place))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
<style lang="less">
|
||||
.event {
|
||||
width: 330px;
|
||||
height: 370px;
|
||||
max-width: 450px;
|
||||
flex-grow: 1;
|
||||
margin: .2em;
|
||||
|
|
|
@ -22,24 +22,10 @@
|
|||
v-btn(icon nuxt to='/export' v-on='on')
|
||||
v-icon mdi-share-variant
|
||||
|
||||
//- v-menu(v-if='settings.enable_trusted_instances && settings.trusted_instances && settings.trusted_instances.length'
|
||||
offset-y bottom open-on-hover transition="slide-y-transition")
|
||||
template(v-slot:activator="{ on, attrs }")
|
||||
v-btn(icon v-bind='attrs' v-on='on')
|
||||
v-icon mdi-map-marker-path
|
||||
v-list
|
||||
v-list-item(v-for='instance in settings.trusted_instances'
|
||||
:key='instance.name'
|
||||
:href='instance.url'
|
||||
two-line)
|
||||
v-list-item-avatar
|
||||
v-img(:src='`${instance.url}/favicon.ico`')
|
||||
v-list-item-content
|
||||
v-list-item-title {{instance.name}}
|
||||
v-list-item-subtitle {{instance.label}}
|
||||
|
||||
v-btn(v-if='!$auth.loggedIn' icon nuxt to='/login')
|
||||
v-icon mdi-login
|
||||
v-tooltip(v-if='!$auth.loggedIn' bottom) {{$t('common.login')}}
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn(icon nuxt to='/login' v-on='on')
|
||||
v-icon mdi-login
|
||||
|
||||
v-menu(v-else
|
||||
offset-y bottom open-on-hover transition="slide-y-transition")
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
v-container
|
||||
v-switch.mt-0(
|
||||
v-if='recurrentFilter && settings.allow_recurrent_event'
|
||||
v-model='filters.show_recurrent'
|
||||
inset color='primary'
|
||||
:label="$t('event.show_recurrent')"
|
||||
@change="v => $emit('showrecurrent', v)")
|
||||
@change="toggleShowRecurrent")
|
||||
|
||||
v-autocomplete.mt-0(
|
||||
:label='$t("common.search")'
|
||||
|
@ -37,7 +38,6 @@ import { mapState } from 'vuex'
|
|||
export default {
|
||||
name: 'Search',
|
||||
props: {
|
||||
pastFilter: { type: Boolean, default: true },
|
||||
recurrentFilter: { type: Boolean, default: true },
|
||||
filters: { type: Object, default: () => {} }
|
||||
},
|
||||
|
@ -67,14 +67,24 @@ export default {
|
|||
remove (item) {
|
||||
const filters = {
|
||||
tags: item.type === 'tag' ? this.filters.tags.filter(f => f !== item.id) : this.filters.tags,
|
||||
places: item.type === 'place' ? this.filters.places.filter(f => f !== item.id) : this.filters.places
|
||||
places: item.type === 'place' ? this.filters.places.filter(f => f !== item.id) : this.filters.places,
|
||||
show_recurrent: this.filters.show_recurrent
|
||||
}
|
||||
this.$emit('update', filters)
|
||||
},
|
||||
toggleShowRecurrent (v) {
|
||||
const filters = {
|
||||
tags: this.filters.tags,
|
||||
places: this.filters.places,
|
||||
show_recurrent: v
|
||||
}
|
||||
this.$emit('update', filters)
|
||||
},
|
||||
change (filters) {
|
||||
filters = {
|
||||
tags: filters.filter(t => t.type === 'tag').map(t => t.id),
|
||||
places: filters.filter(p => p.type === 'place').map(p => p.id)
|
||||
places: filters.filter(p => p.type === 'place').map(p => p.id),
|
||||
show_recurrent: this.filters.show_recurrent
|
||||
}
|
||||
this.$emit('update', filters)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ export default {
|
|||
ca: 'Català',
|
||||
pl: 'Polski',
|
||||
eu: 'Euskara',
|
||||
nb_NO: 'Norwegian Bokmål',
|
||||
no: 'Norwegian Bokmål',
|
||||
fr: 'Francais',
|
||||
de: 'Deutsch'
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ module.exports = {
|
|||
ca: 'Català',
|
||||
pl: 'Polski',
|
||||
eu: 'Euskara',
|
||||
nb_NO: 'Norwegian Bokmål',
|
||||
no: 'Norwegian Bokmål',
|
||||
fr: 'Francais',
|
||||
de: 'Deutsch'
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@
|
|||
"embed": "Incorpora",
|
||||
"embed_title": "Mostra questo evento sul tuo sito web",
|
||||
"embed_help": "Copiando il seguente codice sul tuo sito web l'evento verrà incluso come qui di lato",
|
||||
"feed": "Flusso RSS",
|
||||
"feed_url_copied": "URL copiato, incollalo nel tuo lettore di flusso RSS",
|
||||
"feed": "Feed RSS",
|
||||
"feed_url_copied": "URL copiato, incollalo nel tuo lettore di Feed RSS",
|
||||
"follow_me_title": "Segui gli aggiornamenti dal fediverso",
|
||||
"follow": "Segui",
|
||||
"n_resources": "nessuna risorsa|una risorsa|{n} risorse",
|
||||
|
@ -122,7 +122,7 @@
|
|||
"media_description": "Puoi aggiungere un volantino (opzionale)",
|
||||
"added": "Evento aggiunto",
|
||||
"added_anon": "Evento aggiunto, verrà confermato quanto prima.",
|
||||
"where_description": "Dov'è il gancio? Se il posto non è presente, scrivilo e <b>premi invio</b>. ",
|
||||
"where_description": "Dov'è il gancio? Se il posto non è presente potrai crearlo. ",
|
||||
"confirmed": "Evento confermato",
|
||||
"not_found": "Evento non trovato",
|
||||
"remove_confirmation": "Sei sicuro/a di voler eliminare questo evento?",
|
||||
|
@ -153,7 +153,8 @@
|
|||
"interact_with_me_at": "Seguimi nel fediverso su",
|
||||
"import_ICS": "Importa da ICS",
|
||||
"import_URL": "Importa da URL",
|
||||
"ics": "ICS"
|
||||
"ics": "ICS",
|
||||
"import_description": "Puoi importare eventi da altre piattaforme e da altre istanze attraverso i formati standard (ics e h-event)"
|
||||
},
|
||||
"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).",
|
||||
|
|
32
package.json
32
package.json
|
@ -28,9 +28,9 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@nuxtjs/auth": "^4.9.1",
|
||||
"@nuxtjs/axios": "^5.12.3",
|
||||
"@nuxtjs/axios": "^5.12.4",
|
||||
"accept-language": "^3.0.18",
|
||||
"axios": "^0.21.0",
|
||||
"axios": "^0.21.1",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"body-parser": "^1.18.3",
|
||||
"config": "^3.3.3",
|
||||
|
@ -40,7 +40,7 @@
|
|||
"cross-env": "^7.0.3",
|
||||
"date-fns": "^2.16.1",
|
||||
"dayjs": "^1.9.6",
|
||||
"dompurify": "^2.2.2",
|
||||
"dompurify": "^2.2.6",
|
||||
"email-templates": "^8.0.2",
|
||||
"express": "^4.17.1",
|
||||
"express-oauth-server": "^2.0.0",
|
||||
|
@ -51,7 +51,7 @@
|
|||
"inquirer": "^7.3.3",
|
||||
"jsdom": "^16.4.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"less": "^3.12.2",
|
||||
"less": "^4.0.0",
|
||||
"linkifyjs": "^2.1.9",
|
||||
"lodash": "^4.17.20",
|
||||
"microformat-node": "^2.0.1",
|
||||
|
@ -59,18 +59,18 @@
|
|||
"moment-timezone": "^0.5.32",
|
||||
"morgan": "^1.10.0",
|
||||
"multer": "^1.4.2",
|
||||
"nuxt": "^2.14.9",
|
||||
"nuxt": "^2.14.12",
|
||||
"nuxt-express-module": "^0.0.11",
|
||||
"pg": "^8.5.1",
|
||||
"sequelize": "^6.3.5",
|
||||
"sequelize-cli": "^6.2.0",
|
||||
"sharp": "^0.26.3",
|
||||
"sharp": "^0.27.0",
|
||||
"sqlite3": "^5.0.0",
|
||||
"tiptap": "^1.30.0",
|
||||
"tiptap-extensions": "^1.33.2",
|
||||
"to-ico": "^1.1.5",
|
||||
"url": "^0.11.0",
|
||||
"v-calendar": "^2.1.1",
|
||||
"v-calendar": "^2.1.3",
|
||||
"vue-clipboard2": "^0.3.1",
|
||||
"vue-i18n": "^8.22.2",
|
||||
"yargs": "^16.1.1"
|
||||
|
@ -80,29 +80,29 @@
|
|||
"@nuxtjs/eslint-config": "^5.0.0",
|
||||
"@nuxtjs/vuetify": "^1.11.2",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^7.14.0",
|
||||
"eslint-config-prettier": "^6.15.0",
|
||||
"eslint": "^7.16.0",
|
||||
"eslint-config-prettier": "^7.1.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-loader": "^4.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": ">=11.1.0",
|
||||
"eslint-plugin-nuxt": "^2.0.0",
|
||||
"eslint-plugin-prettier": "^3.2.0",
|
||||
"eslint-plugin-prettier": "^3.3.0",
|
||||
"eslint-plugin-promise": ">=4.0.1",
|
||||
"eslint-plugin-standard": "^5.0.0",
|
||||
"eslint-plugin-vue": "^7.2.0",
|
||||
"less-loader": "^7.1.0",
|
||||
"eslint-plugin-vue": "^7.3.0",
|
||||
"less-loader": "^7.2.0",
|
||||
"nodemon": "^2.0.6",
|
||||
"prettier": "^2.2.1",
|
||||
"pug-plain-loader": "^1.0.0",
|
||||
"sass": "^1.29.0",
|
||||
"pug-plain-loader": "^1.1.0",
|
||||
"sass": "^1.30.0",
|
||||
"sass-loader": "^10.1.0",
|
||||
"vue-cli-plugin-vuetify": "~2.0.8",
|
||||
"vuetify-loader": "^1.3.0",
|
||||
"webpack-cli": "^4.2.0"
|
||||
"webpack-cli": "^4.3.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"prosemirror-model": "1.12.0"
|
||||
"prosemirror-model": "1.13.1"
|
||||
},
|
||||
"bin": {
|
||||
"gancio": "server/cli.js"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template lang="pug">
|
||||
v-container
|
||||
v-card
|
||||
v-tabs
|
||||
v-tabs(v-model='selectedTab')
|
||||
|
||||
//- SETTINGS
|
||||
v-tab {{$t('common.settings')}}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
v-row
|
||||
v-date-picker.col-md-6(
|
||||
mode='dateTime'
|
||||
is24hr
|
||||
:input-debounce="200"
|
||||
:min='today'
|
||||
:minute-increment="5"
|
||||
|
@ -15,7 +16,6 @@ v-row
|
|||
:value='inputValue'
|
||||
:label="$t('event.from')"
|
||||
:rules="[$validators.required('common.when')]"
|
||||
:hint="$t(`event.description`)"
|
||||
ref='date'
|
||||
prepend-icon='mdi-calendar'
|
||||
persistent-hint
|
||||
|
@ -24,6 +24,7 @@ v-row
|
|||
|
||||
v-date-picker.col-md-4(
|
||||
mode='dateTime'
|
||||
is24hr
|
||||
:minute-increment="5"
|
||||
:input-debounce="200"
|
||||
:min='today'
|
||||
|
@ -35,8 +36,7 @@ v-row
|
|||
template(v-slot="{ inputValue, inputEvents }")
|
||||
v-text-field(
|
||||
:value='inputValue'
|
||||
:label="$t('event.from')"
|
||||
:hint="$t(`event.description`)"
|
||||
:label="$t('event.due')"
|
||||
ref='date'
|
||||
prepend-icon='mdi-calendar'
|
||||
persistent-hint
|
||||
|
@ -60,20 +60,19 @@ v-row
|
|||
//- v-btn-toggle.col-md-4(@change='changeType' color='primary' :value='value.type')
|
||||
//- v-btn(value='normal') {{$t('event.normal')}}
|
||||
//- v-btn(value='multidate') {{$t('event.multidate')}}
|
||||
v-switch.col-md-2(v-model='is_recurrent' :label="$t('event.recurrent')" inset)
|
||||
v-menu(v-if='settings.allow_recurrent_event && is_recurrent' offset-y open-on-hover)
|
||||
template(v-slot:activator="{ on, attrs }")
|
||||
v-btn.col-md-2.mt-2(color='primary' value='recurrent' v-on='on') {{$t('event.recurrent')}}
|
||||
v-list
|
||||
v-list-item-group(color='primary' v-model='frequency')
|
||||
v-list-item(v-for='f in frequencies' :key='f.value'
|
||||
@click='selectFrequency(f.value)') {{f.text}}
|
||||
v-switch.col-md-2(:input-value='isRecurrent' :label="$t('event.recurrent')" inset @change='updateRecurrent')
|
||||
//- v-menu(v-if='settings.allow_recurrent_event && isRecurrent' offset-y open-on-hover)
|
||||
//- template(v-slot:activator="{ on, attrs }")
|
||||
//- v-btn.col-md-2.mt-2(color='primary' value='recurrent' v-on='on') {{$t('event.recurrent')}}
|
||||
//- v-btn-group(v-if='settings.allow_recurrent_event && isRecurrent')
|
||||
v-btn-toggle.col-md-12(dense group text link v-if='isRecurrent' color='primary' v-model='value.recurrent.frequency')
|
||||
v-btn(text link v-for='f in frequencies' :key='f.value' :value='f.value'
|
||||
@click='selectFrequency(f.value)') {{f.text}}
|
||||
|
||||
//- div.text-center.mb-2(v-if='value.type === "recurrent"')
|
||||
//- span(v-if='value.recurrent.frequency !== "1m" && value.recurrent.frequency !== "2m"') {{whenPatterns}}
|
||||
//- v-btn-toggle.mt-1(v-else v-model='value.recurrent.type' color='primary')
|
||||
//- v-btn(v-for='whenPattern in whenPatterns' :value='whenPattern.key' :key='whenPatterns.key' small)
|
||||
//- span {{whenPattern.label}}
|
||||
div.col-md-12(v-if='isRecurrent')
|
||||
p(v-if='value.recurrent.frequency !== "1m" && value.recurrent.frequency !== "2m"') 🡲 {{whenPatterns}}
|
||||
v-btn-toggle(v-else dense group v-model='value.recurrent.type' color='primary')
|
||||
v-btn(text link v-for='whenPattern in whenPatterns' :value='whenPattern.key' :key='whenPatterns.key') {{whenPattern.label}}
|
||||
|
||||
//- List(v-if='type==="normal" && todayEvents.length' :events='todayEvents' :title='$t("event.same_day")')
|
||||
|
||||
|
@ -91,7 +90,6 @@ export default {
|
|||
},
|
||||
data () {
|
||||
return {
|
||||
is_recurrent: false,
|
||||
today: dayjs().format('YYYY-MM-DD'),
|
||||
frequency: '',
|
||||
frequencies: [
|
||||
|
@ -103,17 +101,19 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
...mapState(['settings', 'events']),
|
||||
isRecurrent () {
|
||||
return !!this.value.recurrent
|
||||
},
|
||||
whenPatterns () {
|
||||
if (!this.value.date) { return }
|
||||
const date = dayjs(this.value.date)
|
||||
if (!this.value.from) { return }
|
||||
const date = dayjs(this.value.from)
|
||||
|
||||
const freq = this.value.recurrent.frequency
|
||||
const weekDay = date.format('dddd')
|
||||
if (freq === '1w' || freq === '2w') {
|
||||
return this.$t(`event.recurrent_${freq}_days`, { days: weekDay })
|
||||
return this.$t(`event.recurrent_${freq}_days`, { days: weekDay }).toUpperCase()
|
||||
} else if (freq === '1m' || freq === '2m') {
|
||||
const monthDay = date.format('D')
|
||||
|
||||
const n = Math.floor((monthDay - 1) / 7) + 1
|
||||
|
||||
const patterns = [
|
||||
|
@ -150,19 +150,16 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
updateRecurrent (value) {
|
||||
this.$emit('input', { ...this.value, recurrent: value ? {} : null })
|
||||
},
|
||||
change (what, date) {
|
||||
const v = this.value
|
||||
v[what] = date
|
||||
this.$emit('input', v)
|
||||
},
|
||||
changeType (type) {
|
||||
this.$emit('input', { date: null, recurrent: {} })
|
||||
if (type !== 'recurrent') {
|
||||
this.frequency = ''
|
||||
}
|
||||
},
|
||||
selectFrequency (f) {
|
||||
this.$emit('input', { recurrent: { frequency: f }, date: null })
|
||||
this.$emit('input', { recurrent: { frequency: f }, from: this.value.from, due: this.value.due })
|
||||
}
|
||||
// pick (date) {
|
||||
// if (this.value.type === 'normal' || this.value.type === 'recurrent' || (this.value.date && this.value.date.length === 2)) {
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
v-card(color='secondary')
|
||||
v-card-title {{$t('common.import')}}
|
||||
v-card-text
|
||||
v-form(v-model='valid' ref='form' lazy-validation)
|
||||
p(v-html="$t('event.import_description')")
|
||||
v-form(v-model='valid' ref='form' lazy-validation @submit.prevent='importGeneric')
|
||||
v-text-field(v-model='URL'
|
||||
:label="$t('common.url')"
|
||||
:hint="$t('event.import_URL')"
|
||||
|
@ -18,7 +19,7 @@
|
|||
persistent-hint
|
||||
)
|
||||
|
||||
p {{event}}
|
||||
p {{events}}
|
||||
v-card-actions
|
||||
v-spacer
|
||||
v-btn(@click='$emit("close")' color='warning') {{$t('common.cancel')}}
|
||||
|
@ -39,7 +40,7 @@ export default {
|
|||
loading: false,
|
||||
valid: false,
|
||||
URL: '',
|
||||
event: {}
|
||||
events: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -54,8 +55,7 @@ export default {
|
|||
const reader = new FileReader()
|
||||
reader.readAsText(this.file)
|
||||
reader.onload = () => {
|
||||
const data = reader.result
|
||||
const event = ical.parse(data)
|
||||
const event = ical.parse(reader.result)
|
||||
this.event = {
|
||||
title: event.name
|
||||
}
|
||||
|
@ -73,9 +73,9 @@ export default {
|
|||
|
||||
try {
|
||||
const ret = await this.$axios.$get('/event/import', { params: { URL: this.URL } })
|
||||
this.event = ret
|
||||
this.events = ret
|
||||
// check if contain an h-event
|
||||
this.$emit('imported', ret)
|
||||
// this.$emit('imported', ret)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
this.error = true
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
@change='v => event.title = v'
|
||||
:value = 'event.title'
|
||||
:rules="[$validators.required('common.title')]"
|
||||
:hint="$t('event.what_description')"
|
||||
prepend-icon='mdi-format-title'
|
||||
:label="$t('common.title')"
|
||||
autofocus
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
v-container
|
||||
//- EVENT PAGE
|
||||
//- gancio supports microformats (http://microformats.org/wiki/h-event)
|
||||
v-card.h-event(v-on:keyup="$router.push(`/event/${event.next}`)")
|
||||
v-card.h-event
|
||||
v-card-text
|
||||
|
||||
//- admin controls
|
||||
|
@ -32,7 +32,8 @@ v-container
|
|||
time.dt-start.text-h5(:datetime='event.start_datetime|unixFormat("YYYY-MM-DD HH:mm")')
|
||||
v-icon mdi-calendar
|
||||
b.ml-2 {{event|when}}
|
||||
p.subtitle-1 {{event.start_datetime|from}}
|
||||
div.subtitle-1 {{event.start_datetime|from}}
|
||||
small(v-if='event.parentId') ({{event|recurrentDetail}})
|
||||
|
||||
.text-h5.p-location
|
||||
v-icon mdi-map-marker
|
||||
|
|
|
@ -2,11 +2,16 @@
|
|||
v-card(color='secondary')
|
||||
v-card-title(v-text="$t('common.embed_title')")
|
||||
v-card-text
|
||||
v-row(:gutter='10')
|
||||
v-col(:span='12' :xs='24')
|
||||
v-row
|
||||
v-col.col-12
|
||||
v-alert.mb-1.mt-1(type='info' show-icon) {{$t('common.embed_help')}}
|
||||
v-text-field(v-model='code')
|
||||
v-col.mt-2(:span='12' :xs='24' v-html='code')
|
||||
v-btn(slot='prepend' plain text color='primary'
|
||||
v-clipboard:copy='code'
|
||||
v-clipboard:success='copyLink') {{$t("common.copy")}}
|
||||
v-icon.ml-1 mdi-content-copy
|
||||
|
||||
v-col.mt-2(v-html='code')
|
||||
v-card-actions
|
||||
v-spacer
|
||||
v-btn(color='warning' @click="$emit('close')") {{$t("common.cancel")}}
|
||||
|
|
|
@ -6,10 +6,7 @@ div
|
|||
v-btn(text color='primary' v-if='!event.parentId' @click='remove(false)') {{$t('common.remove')}}
|
||||
|
||||
template(v-if='event.parentId')
|
||||
v-divider {{$t('event.recurrent')}}
|
||||
p.text-secondary
|
||||
i.el-icon-refresh
|
||||
small {{event|recurrentDetail}}
|
||||
//- v-divider {{$t('event.recurrent')}}
|
||||
v-btn(text color='primary' v-if='event.parent.is_visible' @click='toggle(true)') {{$t('common.pause')}}
|
||||
v-btn(text color='primary' v-else @click='toggle(true)') {{$t('common.start')}}
|
||||
v-btn(text color='primary' @click='$router.push(`/add/${event.parentId}`)') {{$t('common.edit')}}
|
||||
|
|
|
@ -29,10 +29,6 @@
|
|||
v-clipboard:success='copyLink') {{$t("common.copy")}}
|
||||
v-icon.ml-1 mdi-content-copy
|
||||
|
||||
v-tab(v-if='settings.enable_federation') {{$t('common.fediverse')}}
|
||||
v-tab-item
|
||||
FollowMe
|
||||
|
||||
v-tab ics/ical
|
||||
v-tab-item
|
||||
v-card
|
||||
|
@ -62,6 +58,9 @@
|
|||
color='primary' v-clipboard:copy='listScript' v-clipboard:success='copyLink') {{$t('common.copy')}}
|
||||
v-icon.ml-1 mdi-content-copy
|
||||
|
||||
v-tab(v-if='settings.enable_federation') {{$t('common.fediverse')}}
|
||||
v-tab-item(v-if='settings.enable_federation')
|
||||
FollowMe
|
||||
//- TOFIX
|
||||
//- v-tab.pt-1(label='calendar' name='calendar')
|
||||
//- v-tab-item
|
||||
|
@ -125,6 +124,7 @@ export default {
|
|||
return `<iframe style='border: 0px; width: 100%;' src="${this.settings.baseurl}/embed/list?${params.join('&')}"></iframe>`
|
||||
},
|
||||
link () {
|
||||
const typeMap = ['rss', 'ics', 'list']
|
||||
const tags = this.filters.tags.join(',')
|
||||
const places = this.filters.places.join(',')
|
||||
let query = ''
|
||||
|
@ -138,7 +138,7 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
return `${this.settings.baseurl}/feed/${this.type}${query}`
|
||||
return `${this.settings.baseurl}/feed/${typeMap[this.type]}${query}`
|
||||
},
|
||||
showLink () {
|
||||
return (['rss', 'ics'].includes(this.type))
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
//- Calendar and search bar
|
||||
v-row#calbarmb-2
|
||||
.col-xl-5.col-lg-5.col-md-6.col-sm-12.col-xs-12
|
||||
.col-xl-5.col-lg-5.col-md-7.col-sm-12.col-xs-12
|
||||
//- this is needed as v-calendar does not support SSR
|
||||
//- https://github.com/nathanreyes/v-calendar/issues/336
|
||||
client-only
|
||||
|
@ -14,12 +14,11 @@
|
|||
|
||||
.col
|
||||
Search(:filters='filters' @update='updateFilters')
|
||||
v-chip(v-if='selectedDay' close @click:close='dayChange(selectedDay)') {{selectedDay}}
|
||||
v-chip(v-if='selectedDay' close @click:close='dayChange({ date: selectedDay})') {{selectedDay}}
|
||||
|
||||
//- Events
|
||||
#events
|
||||
Event(v-for='event in events'
|
||||
:key='event.id' :event='event'
|
||||
Event(v-for='(event, idx) in events' :key='event.id' :event='event' :show='idx>=firstVisibleItem && idx<=lastVisibleItem'
|
||||
@tagclick='tagClick' @placeclick='placeClick')
|
||||
|
||||
</template>
|
||||
|
@ -35,33 +34,68 @@ import Calendar from '@/components/Calendar'
|
|||
export default {
|
||||
name: 'Index',
|
||||
components: { Event, Search, Announcement, Calendar },
|
||||
async asyncData ({ params, $api }) {
|
||||
async asyncData ({ params, $api, store }) {
|
||||
const events = await $api.getEvents({
|
||||
start: dayjs().unix()
|
||||
start: dayjs().unix(),
|
||||
end: null,
|
||||
filters: { show_recurrent: store.state.settings.allow_recurrent_event && store.state.settings.recurrent_event_visible }
|
||||
})
|
||||
return { events }
|
||||
},
|
||||
data () {
|
||||
data ({ $store }) {
|
||||
return {
|
||||
date: dayjs().format('YYYY-MM-DD'),
|
||||
events: [],
|
||||
start: dayjs().unix(),
|
||||
end: null,
|
||||
filters: { tags: [], places: [] },
|
||||
selectedDay: null
|
||||
filters: { tags: [], places: [], show_recurrent: $store.state.settings.allow_recurrent_event && $store.state.settings.recurrent_event_visible },
|
||||
selectedDay: null,
|
||||
firstVisibleItem: 0,
|
||||
lastVisibleItem: 20
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['settings', 'announcements']),
|
||||
...mapState(['settings', 'announcements'])
|
||||
},
|
||||
mounted () {
|
||||
let last_known_scroll_position = 0
|
||||
let ticking = false
|
||||
|
||||
document.addEventListener('scroll', e => {
|
||||
last_known_scroll_position = window.scrollY
|
||||
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
this.scroll(last_known_scroll_position)
|
||||
ticking = false
|
||||
})
|
||||
|
||||
ticking = true
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['setFilters']),
|
||||
scroll (y) {
|
||||
const rowHeight = 370
|
||||
const nItems = this.events.length
|
||||
const fullHeight = document.getElementById('events').offsetHeight
|
||||
const nRows = fullHeight / rowHeight
|
||||
const itemPerRow = nItems / nRows
|
||||
const visibleRows = 10
|
||||
this.firstVisibleItem = Math.trunc(((y - 370) / rowHeight) * itemPerRow) - (5 * itemPerRow)
|
||||
this.lastVisibleItem = this.firstVisibleItem + (visibleRows * itemPerRow)
|
||||
|
||||
console.error('Scrolled to ', y, ' nItems', nItems, 'fullHeight', fullHeight, ' itemPerRow', itemPerRow, ' nRow', nRows)
|
||||
console.error('mostro dal ', this.firstVisibleItem, this.lastVisibleItem)
|
||||
},
|
||||
async updateEvents () {
|
||||
this.events = await this.$api.getEvents({
|
||||
start: this.start,
|
||||
end: this.end,
|
||||
places: this.filters.places,
|
||||
tags: this.filters.tags
|
||||
tags: this.filters.tags,
|
||||
show_recurrent: this.filters.show_recurrent
|
||||
})
|
||||
this.setFilters(this.filters)
|
||||
},
|
||||
|
@ -101,18 +135,17 @@ export default {
|
|||
this.updateEvents()
|
||||
},
|
||||
dayChange (day) {
|
||||
if (this.selectedDay === day) {
|
||||
const date = dayjs(day.date).format('YYYY-MM-DD')
|
||||
if (this.selectedDay === date) {
|
||||
this.selectedDay = null
|
||||
this.date = dayjs().format('YYYY-MM-DD')
|
||||
this.start = dayjs().unix() // .startOf('week').unix()
|
||||
this.end = null
|
||||
this.updateEvents()
|
||||
return
|
||||
}
|
||||
this.start = dayjs(day).unix()
|
||||
this.start = dayjs(date).startOf('day').unix()
|
||||
this.end = dayjs(day).endOf('day').unix()
|
||||
this.date = dayjs(day).format('YYYY-MM-DD')
|
||||
this.selectedDay = day
|
||||
this.selectedDay = date
|
||||
this.updateEvents()
|
||||
}
|
||||
},
|
||||
|
|
|
@ -21,10 +21,11 @@ export default ({ $axios, store }, inject) => {
|
|||
start: params.start,
|
||||
end: params.end,
|
||||
places: params.places && params.places.join(','),
|
||||
tags: params.tags && params.tags.join(',')
|
||||
tags: params.tags && params.tags.join(','),
|
||||
show_recurrent: params.show_recurrent
|
||||
}
|
||||
})
|
||||
return events
|
||||
return events.map(e => Object.freeze(e))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return []
|
||||
|
|
|
@ -38,13 +38,13 @@ export default ({ app, store }) => {
|
|||
|
||||
Vue.filter('recurrentDetail', event => {
|
||||
const parent = event.parent
|
||||
const { frequency, days, type } = parent.recurrent
|
||||
const { frequency, type } = parent.recurrent
|
||||
let recurrent
|
||||
if (frequency === '1w' || frequency === '2w') {
|
||||
recurrent = app.i18n.t(`event.recurrent_${frequency}_days`, { days: dayjs.unix(parent.start_datetime).format('dddd') })
|
||||
} else if (frequency === '1m' || frequency === '2m') {
|
||||
const d = type === 'ordinal' ? days : days.map(d => dayjs().day(d - 1).format('dddd'))
|
||||
recurrent = app.i18n.tc(`event.recurrent_${frequency}_${type}`, days.length, { days: d })
|
||||
const d = type === 'ordinal' ? dayjs.unix(parent.start_datetime).date() : dayjs.unix(parent.start_datetime).format('dddd')
|
||||
recurrent = app.i18n.tc(`event.recurrent_${frequency}_${type}`, d)
|
||||
}
|
||||
return recurrent
|
||||
})
|
||||
|
|
|
@ -4,10 +4,11 @@ const config = require('config')
|
|||
const fs = require('fs')
|
||||
const { Op } = require('sequelize')
|
||||
const _ = require('lodash')
|
||||
const helpers = require('../../helpers')
|
||||
const linkifyHtml = require('linkifyjs/html')
|
||||
const Sequelize = require('sequelize')
|
||||
const dayjs = require('dayjs')
|
||||
const helpers = require('../../helpers')
|
||||
const settingsController = require('./settings')
|
||||
|
||||
const Event = require('../models/event')
|
||||
const Resource = require('../models/resource')
|
||||
|
@ -417,19 +418,25 @@ const eventController = {
|
|||
}
|
||||
},
|
||||
|
||||
async _select ({ start, end, tags, places }) {
|
||||
async _select ({ start, end, tags, places, show_recurrent }) {
|
||||
const where = {
|
||||
// do not include parent recurrent event
|
||||
recurrent: null,
|
||||
|
||||
// confirmed event only
|
||||
is_visible: true,
|
||||
|
||||
[Op.or]: {
|
||||
start_datetime: { [Op.gt]: start },
|
||||
end_datetime: { [Op.gt]: start }
|
||||
start_datetime: { [Op.gte]: start },
|
||||
end_datetime: { [Op.gte]: start }
|
||||
}
|
||||
}
|
||||
|
||||
if (!show_recurrent) {
|
||||
where.parentId = null
|
||||
}
|
||||
if (end) {
|
||||
where.start_datetime = { [Op.lt]: end }
|
||||
where.start_datetime = { [Op.lte]: end }
|
||||
}
|
||||
|
||||
if (places) {
|
||||
|
@ -470,9 +477,11 @@ const eventController = {
|
|||
const end = req.query.end
|
||||
const tags = req.query.tags
|
||||
const places = req.query.places
|
||||
const show_recurrent = settingsController.settings.allow_recurrent_event &&
|
||||
(typeof req.query.show_recurrent !== 'undefined' ? req.query.show_recurrent === 'true' : settingsController.settings.recurrent_event_visible)
|
||||
|
||||
res.json(await eventController._select({
|
||||
start, end, places, tags
|
||||
start, end, places, tags, show_recurrent
|
||||
}))
|
||||
},
|
||||
|
||||
|
@ -497,20 +506,37 @@ const eventController = {
|
|||
const frequency = recurrent.frequency
|
||||
const type = recurrent.type
|
||||
|
||||
debug(`NOW IS ${cursor} while event is at ${start_date} (freq: ${frequency})`)
|
||||
|
||||
cursor = cursor.hour(start_date.hour()).minute(start_date.minute()).second(0)
|
||||
debug(`set cursor to correct date and hour => ${cursor}`)
|
||||
|
||||
// each week or 2
|
||||
if (frequency[1] === 'w') {
|
||||
cursor = cursor.day(start_date.day())
|
||||
debug(`Imposto il giorno della settimana ${cursor}`)
|
||||
if (cursor.isBefore(dayjs())) {
|
||||
cursor = cursor.add(7, 'day')
|
||||
}
|
||||
if (frequency[0] === 2) {
|
||||
if (frequency[0] === '2') {
|
||||
cursor = cursor.add(7, 'day')
|
||||
}
|
||||
} else if (frequency === '1m') {
|
||||
if (type === 'ordinal') {
|
||||
cursor = cursor.date(start_date.date())
|
||||
|
||||
if (cursor.isBefore(dayjs())) {
|
||||
cursor = cursor.add(1, 'month')
|
||||
}
|
||||
} else { // weekday
|
||||
const monthDay = start_date.format('D')
|
||||
const n = Math.floor((monthDay - 1) / 7) + 1
|
||||
cursor = cursor.startOf('month')
|
||||
cursor = cursor.add(n, 'week')
|
||||
cursor = cursor.day(start_date.day())
|
||||
if (cursor.isBefore(dayjs())) {
|
||||
cursor = cursor.add(1, 'month')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -529,7 +555,6 @@ const eventController = {
|
|||
include: [{ model: Event, as: 'child', required: false, where: { start_datetime: { [Op.gte]: start_datetime } } }],
|
||||
order: ['start_datetime']
|
||||
})
|
||||
|
||||
// filter events that as no instance in future yet
|
||||
const creations = events
|
||||
.filter(e => e.child.length === 0)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
const ical = require('ical.js')
|
||||
const settingsController = require('./api/controller/settings')
|
||||
const acceptLanguage = require('accept-language')
|
||||
|
||||
|
@ -114,31 +115,56 @@ module.exports = {
|
|||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Import events from url
|
||||
* It does supports ICS and H-EVENT
|
||||
*/
|
||||
async importURL (req, res) {
|
||||
const URL = req.query.URL
|
||||
try {
|
||||
const response = await axios.get(URL)
|
||||
Microformats.get({ html: response.data, filter: ['h-event'] }, (err, data) => {
|
||||
if (err || !data.items.length || !data.items[0].properties) {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
const event = data.items[0].properties
|
||||
return res.json({
|
||||
title: get(event, 'name[0]', ''),
|
||||
description: get(event, 'content[0]', ''),
|
||||
place: get(event, 'location[0].properties.name', ''),
|
||||
address: get(event, 'location[0].properties.street-address'),
|
||||
start: get(event, 'start[0]', ''),
|
||||
end: get(event, 'end[0]', ''),
|
||||
tags: get(event, 'category', []),
|
||||
image: get(event, 'featured[0]')
|
||||
const contentType = response.headers['content-type']
|
||||
|
||||
if (contentType.includes('text/html')) {
|
||||
Microformats.get({ html: response.data, filter: ['h-event'] }, (err, data) => {
|
||||
if (err || !data.items.length || !data.items[0].properties) {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
const events = data.items.map(e => {
|
||||
const props = e.properties
|
||||
return {
|
||||
title: get(props, 'name[0]', ''),
|
||||
description: get(props, 'description[0]', ''),
|
||||
place: get(props, 'location[0].properties.name', ''),
|
||||
address: get(props, 'location[0].properties.street-address'),
|
||||
start: get(props, 'start[0]', ''),
|
||||
end: get(props, 'end[0]', ''),
|
||||
tags: get(props, 'category', []),
|
||||
image: get(props, 'featured[0]')
|
||||
}
|
||||
})
|
||||
return res.json(events)
|
||||
})
|
||||
})
|
||||
} else if (contentType.includes('text/calendar')) {
|
||||
const ret = ical.parse(response.data)
|
||||
const component = new ical.Component(ret)
|
||||
const events = component.getAllSubcomponents('vevent')
|
||||
return res.json(events.map(e => {
|
||||
const event = new ical.Event(e)
|
||||
return {
|
||||
title: get(event, 'summary', ''),
|
||||
description: get(event, 'description', ''),
|
||||
place: get(event, 'location', ''),
|
||||
start: get(event, 'dtstart', ''),
|
||||
end: get(event, 'dtend', '')
|
||||
}
|
||||
}))
|
||||
}
|
||||
// const event = dom.window.document.querySelected(".h-event")
|
||||
// console.error(event)
|
||||
// console.error(response)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
debug(e)
|
||||
}
|
||||
|
||||
// res.json('ok')
|
||||
|
|
|
@ -41,7 +41,6 @@ class Task {
|
|||
|
||||
class TaskManager {
|
||||
constructor () {
|
||||
this.interval = 60 * 1000
|
||||
this.tasks = []
|
||||
}
|
||||
|
||||
|
@ -90,7 +89,7 @@ const TS = new TaskManager()
|
|||
TS.add(new Task({
|
||||
name: 'RECURRENT_EVENT',
|
||||
method: eventController._createRecurrent,
|
||||
repeatEach: 10 // check each 10 minutes
|
||||
repeatEach: 1 // check each 10 minutes
|
||||
}))
|
||||
|
||||
// daily morning notification
|
||||
|
|
Loading…
Reference in a new issue