[mega] settings, timezone
This commit is contained in:
@@ -1,14 +1,29 @@
|
|||||||
@background: #222C32;
|
@home_background: #222C32;
|
||||||
|
@background: white;
|
||||||
@success: #c7ffbc;
|
@success: #c7ffbc;
|
||||||
// @info
|
|
||||||
|
#__nuxt, #__layout {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#home {
|
||||||
|
background-color: @home_background;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
background-color: @background !important;
|
background-color: @background;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-family: BlinkMacSystemFont,-apple-system,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,Helvetica,Arial,sans-serif !important;
|
font-family: BlinkMacSystemFont,-apple-system,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,Helvetica,Arial,sans-serif !important;
|
||||||
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -18,14 +33,11 @@ html, body {
|
|||||||
.el-form-item {
|
.el-form-item {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
// .el-divider__text {
|
|
||||||
// background-color: @background;
|
|
||||||
// color: white;
|
|
||||||
// border-radius: 5px;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
.el-main,
|
||||||
.el-card {
|
.el-card {
|
||||||
max-width: 660px;
|
max-width: 1000px;
|
||||||
|
border-radius: 0px;
|
||||||
margin: 30px auto;
|
margin: 30px auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +66,7 @@ html, body {
|
|||||||
.page-enter, .page-leave-active {
|
.page-enter, .page-leave-active {
|
||||||
transition: opacity .3s, transform .2s;
|
transition: opacity .3s, transform .2s;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
// transform: translateY(30px);
|
transform: translateX(30px);
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
@@ -69,12 +81,20 @@ pre {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
@media only screen and (max-width: 768px) {
|
||||||
|
html {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.el-card {
|
.el-card {
|
||||||
margin-top: 0px !important;
|
margin-top: 0px !important;
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-main{
|
||||||
|
padding: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
padding: 0px 17px;
|
padding: 0px 17px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
"content": "Abbiamo ricevuto la richiesta di registrazione. La confermeremo quanto prima.\n Ciao"
|
"content": "Abbiamo ricevuto la richiesta di registrazione. La confermeremo quanto prima.\n Ciao"
|
||||||
},
|
},
|
||||||
"confirm": {
|
"confirm": {
|
||||||
|
"subject": "Puoi iniziare a pubblicare eventi",
|
||||||
|
"content": "Ciao, il tuo account su <a href='{{config.baseurl}}'>{{config.title}}</a> è stato creato."
|
||||||
|
},
|
||||||
|
"user_confirm": {
|
||||||
"subject": "Puoi iniziare a pubblicare eventi",
|
"subject": "Puoi iniziare a pubblicare eventi",
|
||||||
"content": "Ciao, il tuo account su <a href='{{config.baseurl}}'>{{config.title}}</a> è stato creato. <a href='{{config.baseurl}}/user_confirm/{{user.recover_code}}'>Confermalo</a>."
|
"content": "Ciao, il tuo account su <a href='{{config.baseurl}}'>{{config.title}}</a> è stato creato. <a href='{{config.baseurl}}/user_confirm/{{user.recover_code}}'>Confermalo</a>."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
"less": "^3.10.3",
|
"less": "^3.10.3",
|
||||||
"lodash": "^4.17.14",
|
"lodash": "^4.17.14",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
|
"moment-timezone": "^0.5.26",
|
||||||
"morgan": "^1.9.1",
|
"morgan": "^1.9.1",
|
||||||
"multer": "^1.4.2",
|
"multer": "^1.4.2",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
el-card
|
el-main
|
||||||
nuxt-link.float-right(to='/')
|
nuxt-link.float-right(to='/')
|
||||||
el-button(circle icon='el-icon-close' type='danger' size='small' plain)
|
el-button(circle icon='el-icon-close' type='danger' size='small' plain)
|
||||||
|
|
||||||
@@ -390,8 +390,8 @@ export default {
|
|||||||
formData.append('place_address', this.event.place.address)
|
formData.append('place_address', this.event.place.address)
|
||||||
formData.append('description', this.event.description)
|
formData.append('description', this.event.description)
|
||||||
formData.append('multidate', this.event.type === 'multidate')
|
formData.append('multidate', this.event.type === 'multidate')
|
||||||
formData.append('start_datetime', start_datetime.utc(true).unix())
|
formData.append('start_datetime', start_datetime.unix())
|
||||||
formData.append('end_datetime', end_datetime.utc(true).unix())
|
formData.append('end_datetime', end_datetime.unix())
|
||||||
|
|
||||||
if (this.edit) {
|
if (this.edit) {
|
||||||
formData.append('id', this.event.id)
|
formData.append('id', this.event.id)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
el-table-column(:label='$t("common.name")' width='300')
|
el-table-column(:label='$t("common.name")' width='300')
|
||||||
template(slot-scope='data') {{data.row.title}}
|
template(slot-scope='data') {{data.row.title}}
|
||||||
el-table-column(:label='$t("common.where")' width='250')
|
el-table-column(:label='$t("common.where")' width='250')
|
||||||
template(slot-scope='data') {{dperPageata.row.place.name}}
|
template(slot-scope='data') {{data.row.place.name}}
|
||||||
el-table-column(:label='$t("common.confirm")' width='250')
|
el-table-column(:label='$t("common.confirm")' width='250')
|
||||||
template(slot-scope='data')
|
template(slot-scope='data')
|
||||||
el-button(type='primary' @click='confirm(data.row.id)' size='mini') {{$t('common.confirm')}}
|
el-button(type='primary' @click='confirm(data.row.id)' size='mini') {{$t('common.confirm')}}
|
||||||
|
|||||||
@@ -7,11 +7,18 @@
|
|||||||
<script>
|
<script>
|
||||||
import Home from '~/components/Home.vue'
|
import Home from '~/components/Home.vue'
|
||||||
import Nav from '~/components/Nav.vue'
|
import Nav from '~/components/Nav.vue'
|
||||||
|
import moment from 'moment-timezone'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Index',
|
name: 'Index',
|
||||||
|
computed: mapState(['settings']),
|
||||||
|
mounted (ctx) {
|
||||||
|
moment.tz.setDefault(this.settings.instance_timezone)
|
||||||
|
},
|
||||||
async fetch ({ store, $axios }) {
|
async fetch ({ store, $axios }) {
|
||||||
try {
|
try {
|
||||||
|
moment.tz.setDefault(store.state.settings.instance_timezone)
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const events = await $axios.$get(`/event/${now.getMonth()}/${now.getFullYear()}`)
|
const events = await $axios.$get(`/event/${now.getMonth()}/${now.getFullYear()}`)
|
||||||
store.commit('setEvents', events)
|
store.commit('setEvents', events)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
el-card
|
el-main
|
||||||
nuxt-link.float-right(to='/')
|
nuxt-link.float-right(to='/')
|
||||||
el-button(circle icon='el-icon-close' type='danger' size='small' plain)
|
el-button(circle icon='el-icon-close' type='danger' size='small' plain)
|
||||||
h5 {{$t('common.settings')}}
|
h5 {{$t('common.settings')}}
|
||||||
|
|||||||
@@ -3,27 +3,52 @@
|
|||||||
nuxt-link.float-right(to='/')
|
nuxt-link.float-right(to='/')
|
||||||
el-button(circle icon='el-icon-close' type='danger' size='small' plain)
|
el-button(circle icon='el-icon-close' type='danger' size='small' plain)
|
||||||
|
|
||||||
h5 <img src='/favicon.ico'/> {{$t('confirm.title')}}
|
h5 <img src='/favicon.ico'/> {{$t('common.set_password')}}
|
||||||
p(v-if='valid' v-html='$t("confirm.valid")')
|
div(v-if='valid')
|
||||||
p(v-else) {{$t('confirm.not_valid')}}
|
el-form
|
||||||
|
el-form-item {{$t('common.new_password')}}
|
||||||
|
el-input(type='password', v-model='new_password')
|
||||||
|
el-button(plain type="success" icon='el-icon-send'
|
||||||
|
:disabled='!new_password' @click='change_password') {{$t('common.send')}}
|
||||||
|
|
||||||
|
div(v-else) {{$t('recover.not_valid_code')}}
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { Message } from 'element-ui'
|
import { Message } from 'element-ui'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Confirm',
|
name: 'Recover',
|
||||||
data () {
|
data () {
|
||||||
return { valid: true }
|
return { new_password: '' }
|
||||||
},
|
},
|
||||||
async asyncData ({ params, $axios }) {
|
async asyncData ({ params, $axios }) {
|
||||||
const recover_code = params.code
|
const code = params.code
|
||||||
try {
|
try {
|
||||||
const valid = await $axios.$post('/user/check_recover_code', { recover_code })
|
const valid = await $axios.$post('/user/check_recover_code', { recover_code: code })
|
||||||
return { valid }
|
return { valid, code }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return { valid: false }
|
return { valid: false }
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async change_password () {
|
||||||
|
try {
|
||||||
|
const res = await this.$axios.$post('/user/recover_password', { recover_code: this.code, password: this.new_password })
|
||||||
|
Message({
|
||||||
|
showClose: true,
|
||||||
|
type: 'success',
|
||||||
|
message: this.$t('common.password_updated')
|
||||||
|
})
|
||||||
|
this.$router.replace('/login')
|
||||||
|
} catch (e) {
|
||||||
|
Message({
|
||||||
|
showClose: true,
|
||||||
|
type: 'warning',
|
||||||
|
message: e
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
53
pages/user_confirm_pwd/_code.vue
Normal file
53
pages/user_confirm_pwd/_code.vue
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
el-card
|
||||||
|
nuxt-link.float-right(to='/')
|
||||||
|
el-button(circle icon='el-icon-close' type='danger' size='small' plain)
|
||||||
|
|
||||||
|
h5 <img src='/favicon.ico'/> {{$t('common.set_password')}}
|
||||||
|
div(v-if='valid')
|
||||||
|
el-form
|
||||||
|
el-form-item {{$t('common.new_password')}}
|
||||||
|
el-input(type='password', v-model='new_password')
|
||||||
|
el-button(plain type="success" icon='el-icon-send', @click='change_password') {{$t('common.send')}}
|
||||||
|
|
||||||
|
div(v-else) {{$t('recover.not_valid_code')}}
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { Message } from 'element-ui'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Recover',
|
||||||
|
data () {
|
||||||
|
return { new_password: '' }
|
||||||
|
},
|
||||||
|
async asyncData ({ params, $axios }) {
|
||||||
|
const code = params.code
|
||||||
|
try {
|
||||||
|
const valid = await $axios.$post('/user/check_recover_code', { recover_code: code })
|
||||||
|
return { valid, code }
|
||||||
|
} catch (e) {
|
||||||
|
return { valid: false }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async change_password () {
|
||||||
|
try {
|
||||||
|
const res = await this.$axios.$post('/user/recover_password', { recover_code: this.code, password: this.new_password })
|
||||||
|
Message({
|
||||||
|
showClose: true,
|
||||||
|
type: 'success',
|
||||||
|
message: this.$t('common.password_updated')
|
||||||
|
})
|
||||||
|
this.$router.replace('/login')
|
||||||
|
} catch (e) {
|
||||||
|
Message({
|
||||||
|
showClose: true,
|
||||||
|
type: 'warning',
|
||||||
|
message: e
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { Button, Select, Tag, Option, Table, FormItem, Card, Row, Col, Upload, Checkbox, RadioButton, RadioGroup,
|
import { Button, Select, Tag, Option, Table, FormItem, Card, Row, Col, Upload, Checkbox, RadioButton, RadioGroup,
|
||||||
Form, Tabs, TabPane, Switch, Input, Loading, TimeSelect, Badge, ButtonGroup, Divider, Step, Steps, Radio,
|
Form, Tabs, TabPane, Switch, Input, Loading, TimeSelect, Badge, ButtonGroup, Divider, Step, Steps, Radio, Main,
|
||||||
TableColumn, ColorPicker, Pagination, Popover, Tooltip, Dialog, Image, Backtop, Collapse, CollapseItem,
|
TableColumn, ColorPicker, Pagination, Popover, Tooltip, Dialog, Image, Backtop, Collapse, CollapseItem, Link,
|
||||||
|
Dropdown, DropdownMenu, DropdownItem, Submenu, PageHeader, Header,
|
||||||
Container, Footer, Timeline, TimelineItem, Menu, MenuItem } from 'element-ui'
|
Container, Footer, Timeline, TimelineItem, Menu, MenuItem } from 'element-ui'
|
||||||
import locale from 'element-ui/lib/locale'
|
import locale from 'element-ui/lib/locale'
|
||||||
|
|
||||||
@@ -14,6 +15,14 @@ const locales = {
|
|||||||
export default ({ app, store }) => {
|
export default ({ app, store }) => {
|
||||||
locale.use(locales[store.state.locale])
|
locale.use(locales[store.state.locale])
|
||||||
Vue.use(Button)
|
Vue.use(Button)
|
||||||
|
Vue.use(Dropdown)
|
||||||
|
Vue.use(Header)
|
||||||
|
Vue.use(PageHeader)
|
||||||
|
Vue.use(Submenu)
|
||||||
|
Vue.use(DropdownItem)
|
||||||
|
Vue.use(DropdownMenu)
|
||||||
|
Vue.use(Main)
|
||||||
|
Vue.use(Link)
|
||||||
Vue.use(RadioButton)
|
Vue.use(RadioButton)
|
||||||
Vue.use(RadioGroup)
|
Vue.use(RadioGroup)
|
||||||
Vue.use(Radio)
|
Vue.use(Radio)
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import moment from 'moment'
|
import moment from 'moment-timezone'
|
||||||
// import 'dayjs/locale/it'
|
|
||||||
// import 'dayjs/locale/es'
|
|
||||||
|
|
||||||
export default ({ app, store }) => {
|
export default ({ app, store }) => {
|
||||||
|
|
||||||
|
// set timezone to instance_timezone!!
|
||||||
|
// to show local time relative to event's place
|
||||||
|
// not where in the worlds I'm looking at the page from
|
||||||
|
moment.tz.setDefault(store.state.settings.instance_timezone)
|
||||||
|
|
||||||
// replace links with anchors
|
// replace links with anchors
|
||||||
// TODO: remove fb tracking id
|
// TODO: remove fb tracking id
|
||||||
Vue.filter('linkify', value => value.replace(/(https?:\/\/[^\s]+)/g, '<a href="$1">$1</a>'))
|
Vue.filter('linkify', value => value.replace(/(https?:\/\/([^\s]+))/g, '<a href="$1">$2</a>'))
|
||||||
|
|
||||||
Vue.filter('url2host', url => url.match(/^https?:\/\/(.[^/:]+)/i)[1])
|
Vue.filter('url2host', url => url.match(/^https?:\/\/(.[^/:]+)/i)[1])
|
||||||
Vue.filter('datetime', value => moment(value).utc(false).locale(store.state.locale).format('ddd, D MMMM HH:mm'))
|
Vue.filter('datetime', value => moment(value).locale(store.state.locale).format('ddd, D MMMM HH:mm'))
|
||||||
// Vue.filter('short_datetime', value => moment(value).locale(store.state.locale).format('D/MM HH:mm'))
|
|
||||||
// Vue.filter('hour', value => moment(value).locale(store.state.locale).format('HH:mm'))
|
|
||||||
|
|
||||||
// shown in mobile homepage
|
// shown in mobile homepage
|
||||||
Vue.filter('day', value => moment.unix(value).utc(false).locale(store.state.locale).format('dddd, D MMM'))
|
Vue.filter('day', value => moment.unix(value).locale(store.state.locale).format('dddd, D MMM'))
|
||||||
// Vue.filter('month', value => moment(value).locale(store.state.locale).format('MMM'))
|
|
||||||
|
|
||||||
|
Vue.filter('to', value => moment().to(value.start_datetime*1000))
|
||||||
// format event start/end datetime based on page
|
// format event start/end datetime based on page
|
||||||
Vue.filter('when', (event, where) => {
|
Vue.filter('when', (event, where) => {
|
||||||
moment.locale(store.state.locale)
|
moment.locale(store.state.locale)
|
||||||
|
|
||||||
// show local time relative to event's place
|
const start = moment.unix(event.start_datetime)
|
||||||
// (not where in the worlds I'm looking at the page from)
|
const end = moment.unix(event.end_datetime)
|
||||||
const start = moment.unix(event.start_datetime).utc(false)
|
|
||||||
const end = moment.unix(event.end_datetime).utc(false)
|
|
||||||
|
|
||||||
const normal = `${start.format('dddd, D MMMM (HH:mm-')}${end.format('HH:mm)')}`
|
|
||||||
|
|
||||||
|
const normal = `${start.format('dddd, D MMMM (HH:mm-')}${end.format('HH:mm) z Z ')}`
|
||||||
// recurrent event
|
// recurrent event
|
||||||
if (event.recurrent && where !== 'home') {
|
if (event.recurrent && where !== 'home') {
|
||||||
const { frequency, days, type } = JSON.parse(event.recurrent)
|
const { frequency, days, type } = JSON.parse(event.recurrent)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import 'vue-awesome/icons/envelope'
|
|||||||
import 'vue-awesome/icons/calendar-day'
|
import 'vue-awesome/icons/calendar-day'
|
||||||
import 'vue-awesome/icons/calendar-week'
|
import 'vue-awesome/icons/calendar-week'
|
||||||
import 'vue-awesome/icons/calendar-alt'
|
import 'vue-awesome/icons/calendar-alt'
|
||||||
import 'vue-awesome/icons/circle-notch'
|
import 'vue-awesome/icons/network-wired'
|
||||||
|
|
||||||
import Icon from 'vue-awesome/components/Icon'
|
import Icon from 'vue-awesome/components/Icon'
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const moment = require('moment')
|
const moment = require('moment-timezone')
|
||||||
const { Op } = require('sequelize')
|
const { Op } = require('sequelize')
|
||||||
const lodash = require('lodash')
|
const lodash = require('lodash')
|
||||||
const { event: Event, comment: Comment, tag: Tag, place: Place,
|
const { event: Event, comment: Comment, tag: Tag, place: Place,
|
||||||
user: User, notification: Notification, event_notification: EventNotification } = require('../models')
|
user: User, notification: Notification, event_notification: EventNotification } = require('../models')
|
||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize')
|
||||||
|
const exportController = require('./export')
|
||||||
const debug = require('debug')('controller:event')
|
const debug = require('debug')('controller:event')
|
||||||
|
|
||||||
const eventController = {
|
const eventController = {
|
||||||
@@ -90,6 +91,7 @@ const eventController = {
|
|||||||
// TODO retrieve next/prev event also
|
// TODO retrieve next/prev event also
|
||||||
// select id, start_datetime, title from events where start_datetime > (select start_datetime from events where id=89) order by start_datetime limit 20;
|
// select id, start_datetime, title from events where start_datetime > (select start_datetime from events where id=89) order by start_datetime limit 20;
|
||||||
async get (req, res) {
|
async get (req, res) {
|
||||||
|
const format = req.params.format || 'json'
|
||||||
const is_admin = req.user && req.user.is_admin
|
const is_admin = req.user && req.user.is_admin
|
||||||
const id = req.params.event_id
|
const id = req.params.event_id
|
||||||
const event = await Event.findByPk(id, {
|
const event = await Event.findByPk(id, {
|
||||||
@@ -107,7 +109,11 @@ const eventController = {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (event && (event.is_visible || is_admin)) {
|
if (event && (event.is_visible || is_admin)) {
|
||||||
res.json(event)
|
if (format === 'json') {
|
||||||
|
res.json(event)
|
||||||
|
} else if (format === 'ics') {
|
||||||
|
exportController.ics(req, res, [event])
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
res.sendStatus(404)
|
res.sendStatus(404)
|
||||||
}
|
}
|
||||||
@@ -190,13 +196,11 @@ const eventController = {
|
|||||||
.month(req.params.month)
|
.month(req.params.month)
|
||||||
.startOf('month')
|
.startOf('month')
|
||||||
.startOf('week')
|
.startOf('week')
|
||||||
.utc(false)
|
|
||||||
|
|
||||||
let end = moment()
|
let end = moment()
|
||||||
.year(req.params.year)
|
.year(req.params.year)
|
||||||
.month(req.params.month)
|
.month(req.params.month)
|
||||||
.endOf('month')
|
.endOf('month')
|
||||||
.utc(false)
|
|
||||||
|
|
||||||
const shownDays = end.diff(start, 'days')
|
const shownDays = end.diff(start, 'days')
|
||||||
if (shownDays <= 35) { end = end.add(1, 'week') }
|
if (shownDays <= 35) { end = end.add(1, 'week') }
|
||||||
@@ -235,7 +239,7 @@ const eventController = {
|
|||||||
if (!recurrent.frequency) { return false }
|
if (!recurrent.frequency) { return false }
|
||||||
|
|
||||||
let cursor = moment(start).startOf('week')
|
let cursor = moment(start).startOf('week')
|
||||||
const start_date = moment.unix(e.start_datetime).utc(false)
|
const start_date = moment.unix(e.start_datetime)
|
||||||
const duration = moment.unix(e.end_datetime).diff(start_date, 's')
|
const duration = moment.unix(e.end_datetime).diff(start_date, 's')
|
||||||
const frequency = recurrent.frequency
|
const frequency = recurrent.frequency
|
||||||
const days = recurrent.days
|
const days = recurrent.days
|
||||||
@@ -280,7 +284,7 @@ const eventController = {
|
|||||||
cursor.day(d - 1)
|
cursor.day(d - 1)
|
||||||
}
|
}
|
||||||
if (cursor.isAfter(dueTo) || cursor.isBefore(start)) { return }
|
if (cursor.isAfter(dueTo) || cursor.isBefore(start)) { return }
|
||||||
e.start_datetime = cursor.utc(true).unix()
|
e.start_datetime = cursor.unix()
|
||||||
e.end_datetime = e.start_datetime + duration
|
e.end_datetime = e.start_datetime + duration
|
||||||
events.push(Object.assign({}, e))
|
events.push(Object.assign({}, e))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
const { event: Event, place: Place, tag: Tag } = require('../models')
|
const { event: Event, place: Place, tag: Tag } = require('../models')
|
||||||
const { Op } = require('sequelize')
|
const { Op } = require('sequelize')
|
||||||
const moment = require('moment')
|
const moment = require('moment-timezone')
|
||||||
const config = require('config')
|
|
||||||
const ics = require('ics')
|
const ics = require('ics')
|
||||||
|
|
||||||
const exportController = {
|
const exportController = {
|
||||||
@@ -36,31 +35,38 @@ const exportController = {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 'rss':
|
case 'rss':
|
||||||
case 'feed':
|
case 'feed':
|
||||||
return exportController.feed(res, events.slice(0, 20))
|
return exportController.feed(req, res, events.slice(0, 20))
|
||||||
case 'ics':
|
case 'ics':
|
||||||
return exportController.ics(res, events)
|
return exportController.ics(req, res, events)
|
||||||
case 'json':
|
case 'json':
|
||||||
return res.json(events)
|
return res.json(events)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
feed (res, events) {
|
feed (req, res, events) {
|
||||||
res.type('application/rss+xml; charset=UTF-8')
|
res.type('application/rss+xml; charset=UTF-8')
|
||||||
res.render('feed/rss.pug', { events, config, moment })
|
res.render('feed/rss.pug', { events, settings: req.settings, moment })
|
||||||
},
|
},
|
||||||
|
|
||||||
ics (res, events) {
|
ics (req, res, events) {
|
||||||
const eventsMap = events.map(e => {
|
const eventsMap = events.map(e => {
|
||||||
const tmpStart = moment.unix(e.start_datetime).utc(false)
|
const tmpStart = moment.unix(e.start_datetime)
|
||||||
const tmpEnd = moment.unix(e.end_datetime).utc(false)
|
const tmpEnd = moment.unix(e.end_datetime)
|
||||||
const start = [tmpStart.year(), tmpStart.month() + 1, tmpStart.date(), tmpStart.hour(), tmpStart.minute()]
|
const start = tmpStart.utc(true).format('YYYY-M-D-H-m').split('-')
|
||||||
const end = [tmpEnd.year(), tmpEnd.month() + 1, tmpEnd.date(), tmpEnd.hour(), tmpEnd.minute()]
|
const end = tmpEnd.utc(true).format('YYYY-M-D-H-m').split('-')
|
||||||
return {
|
return {
|
||||||
start,
|
start,
|
||||||
|
// startOutputType: 'utc',
|
||||||
end,
|
end,
|
||||||
title: e.title,
|
// endOutputType: 'utc',
|
||||||
|
title: `[1${req.settings.title}] ${e.title}`,
|
||||||
description: e.description,
|
description: e.description,
|
||||||
location: e.place.name + ' ' + e.place.address
|
location: `${e.place.name} - ${e.place.address}`,
|
||||||
|
url: `${req.settings.baseurl}/event/${e.id}`,
|
||||||
|
alarms: [{
|
||||||
|
action: 'display',
|
||||||
|
trigger: {hours: 1, before: true}
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
res.type('text/calendar; charset=UTF-8')
|
res.type('text/calendar; charset=UTF-8')
|
||||||
|
|||||||
@@ -249,8 +249,10 @@ const userController = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.body.recover_code = crypto.randomBytes(16).toString('hex')
|
req.body.recover_code = crypto.randomBytes(16).toString('hex')
|
||||||
|
debug('Register user ', req.body.email)
|
||||||
const user = await User.create(req.body)
|
const user = await User.create(req.body)
|
||||||
try {
|
try {
|
||||||
|
debug(`Sending registration email to ${user.email}`)
|
||||||
mail.send(user.email, 'register', { user, config })
|
mail.send(user.email, 'register', { user, config })
|
||||||
mail.send(config.admin_email, 'admin_register', { user, config })
|
mail.send(config.admin_email, 'admin_register', { user, config })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -24,14 +24,6 @@ api.use(bodyParser.json())
|
|||||||
const jwt = expressJwt({
|
const jwt = expressJwt({
|
||||||
secret: config.secret,
|
secret: config.secret,
|
||||||
credentialsRequired: false,
|
credentialsRequired: false,
|
||||||
// getToken: function fromHeaderOrQuerystring (req) {
|
|
||||||
// if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
|
|
||||||
// return req.headers.authorization.split(' ')[1]
|
|
||||||
// } else if (req.cookies && req.cookies['auth._token.local']) {
|
|
||||||
// const [ prefix, token ] = req.cookies['auth._token.local'].split(' ')
|
|
||||||
// if (prefix === 'Bearer') { return token }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// api.use(jwt)
|
// api.use(jwt)
|
||||||
@@ -95,7 +87,7 @@ api.get('/event/confirm/:event_id', isAuth, isAdmin, eventController.confirm)
|
|||||||
api.get('/event/unconfirm/:event_id', isAuth, isAdmin, eventController.unconfirm)
|
api.get('/event/unconfirm/:event_id', isAuth, isAdmin, eventController.unconfirm)
|
||||||
|
|
||||||
// get event
|
// get event
|
||||||
api.get('/event/:event_id', fillUser, eventController.get)
|
api.get('/event/:event_id.:format?', fillUser, eventController.get)
|
||||||
|
|
||||||
// export events (rss/ics)
|
// export events (rss/ics)
|
||||||
api.get('/export/:type', exportController.export)
|
api.get('/export/:type', exportController.export)
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const mail = {
|
|||||||
...locals,
|
...locals,
|
||||||
locale: 'it', // TOFIX
|
locale: 'it', // TOFIX
|
||||||
config: { title: config.title, baseurl: config.baseurl, description: config.description },
|
config: { title: config.title, baseurl: config.baseurl, description: config.description },
|
||||||
datetime: datetime => moment.unix(datetime).utc(false).format('ddd, D MMMM HH:mm')
|
datetime: datetime => moment.unix(datetime).format('ddd, D MMMM HH:mm')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return email.send(msg)
|
return email.send(msg)
|
||||||
|
|||||||
@@ -37,11 +37,14 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
event.prototype.toAP = function (username, follower = []) {
|
event.prototype.toAP = function (username, follower = []) {
|
||||||
const tags = this.tags && this.tags.map(t => `<a href='/tags/${t.tag}' class='mention hashtag' rel='tag'>#${t.tag}</a>`).join(' ')
|
const tags = this.tags && this.tags.map(t => {
|
||||||
|
const tag = t.tag.replace(/[ #]/g, '_')
|
||||||
|
return `<a href='/tags/${t.tag}' class='mention hashtag status-link' rel='tag'><span>#${t.tag}</span></a>`
|
||||||
|
}).join(' ')
|
||||||
|
|
||||||
const content = `<a href='${config.baseurl}/event/${this.id}'>${this.title}</a><br/>
|
const content = `<a href='${config.baseurl}/event/${this.id}'>${this.title}</a><br/>
|
||||||
📍${this.place.name}<br/>
|
📍${this.place.name}<br/>
|
||||||
⏰ ${moment.unix(this.start_datetime).utc(false).format('dddd, D MMMM (HH:mm)')}<br/><br/>
|
⏰ ${moment.unix(this.start_datetime).format('dddd, D MMMM (HH:mm)')}<br/><br/>
|
||||||
${this.description.length > 200 ? this.description.substr(0, 200) + '...' : this.description}<br/>
|
${this.description.length > 200 ? this.description.substr(0, 200) + '...' : this.description}<br/>
|
||||||
${tags} <br/>`
|
${tags} <br/>`
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
extends ../layout.pug
|
extends ../layout.pug
|
||||||
block content
|
block content
|
||||||
p !{t('confirm.content', { config, user })}
|
p !{t('user_confirm.content', { config, user })}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
| [#{config.title}] #{t('confirm.subject')}
|
| [#{config.title}] #{t('user_confirm.subject')}
|
||||||
@@ -1 +1 @@
|
|||||||
p !{t('confirm.content', { config, user })}
|
p !{t('user_confirm.content', { config, user })}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ const settingsController = require('./api/controller/settings')
|
|||||||
const acceptLanguage = require('accept-language')
|
const acceptLanguage = require('accept-language')
|
||||||
const expressJwt = require('express-jwt')
|
const expressJwt = require('express-jwt')
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
|
const moment = require('moment-timezone')
|
||||||
const config = require('config')
|
const config = require('config')
|
||||||
const package = require('../package.json')
|
const package = require('../package.json')
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ module.exports = {
|
|||||||
acceptLanguage.languages(supportedLanguages)
|
acceptLanguage.languages(supportedLanguages)
|
||||||
req.settings.locale = acceptLanguage.get(acceptedLanguages)
|
req.settings.locale = acceptLanguage.get(acceptedLanguages)
|
||||||
req.settings.user_locale = settingsController.user_locale[req.settings.locale]
|
req.settings.user_locale = settingsController.user_locale[req.settings.locale]
|
||||||
|
moment.locale(req.settings.locale)
|
||||||
|
|
||||||
// auth
|
// auth
|
||||||
jwt(req, res, () => {
|
jwt(req, res, () => {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export const state = () => ({
|
|||||||
tags: [],
|
tags: [],
|
||||||
places: [],
|
places: [],
|
||||||
settings: {
|
settings: {
|
||||||
|
instance_timezone: 'Europe/Rome',
|
||||||
allow_registration: true,
|
allow_registration: true,
|
||||||
allow_anon_event: true,
|
allow_anon_event: true,
|
||||||
allow_recurrent_event: true,
|
allow_recurrent_event: true,
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
doctype xml
|
doctype xml
|
||||||
rss(version='2.0' xmlns:atom="http://www.w3.org/2005/Atom")
|
rss(version='2.0' xmlns:atom="http://www.w3.org/2005/Atom")
|
||||||
channel
|
channel
|
||||||
atom:link(href="#{config.baseurl}/feed/rss" rel="self" type="application/rss+xml")
|
atom:link(href="#{settings.baseurl}/feed/rss" rel="self" type="application/rss+xml")
|
||||||
title #{config.title}
|
title #{settings.title}
|
||||||
link #{config.baseurl}
|
link #{settings.baseurl}
|
||||||
description #{config.description}
|
description #{settings.description}
|
||||||
each event in events
|
each event in events
|
||||||
item
|
item
|
||||||
title [#{moment.unix(event.start_datetime).utc(false).format("YY-MM-DD")}] #{event.title} @#{event.place.name}
|
title [#{moment.unix(event.start_datetime).format("YY-MM-DD")}] #{event.title} @#{event.place.name}
|
||||||
link #{config.baseurl}/event/#{event.id}
|
link #{settings.baseurl}/event/#{event.id}
|
||||||
description
|
description
|
||||||
| <![CDATA[
|
| <![CDATA[
|
||||||
| <h4>#{event.title}</h4>
|
| <h4>#{event.title}</h4>
|
||||||
| <strong>#{event.place.name} - #{event.place.address}</strong>
|
| <strong>#{event.place.name} - #{event.place.address}</strong>
|
||||||
| <small>(#{moment.unix(event.start_datetime).utc(false).format("dddd, D MMMM HH:mm")})</small><br/>
|
| <small>(#{moment.unix(event.start_datetime).format("dddd, D MMMM HH:mm")})</small><br/>
|
||||||
if (event.image_path)
|
if (event.image_path)
|
||||||
| <img src="#{config.apiurl}/media/#{event.image_path}"/>
|
| <img src="#{settings.baseurl}/media/#{event.image_path}"/>
|
||||||
| <pre>!{event.description}</pre>
|
| <pre>!{event.description}</pre>
|
||||||
| ]]>
|
| ]]>
|
||||||
pubDate= new Date(event.createdAt).toUTCString()
|
pubDate= new Date(event.createdAt).toUTCString()
|
||||||
guid(isPermaLink='false') #{config.baseurl}/event/#{event.id}
|
guid(isPermaLink='false') #{settings.baseurl}/event/#{event.id}
|
||||||
|
|||||||
Reference in New Issue
Block a user