diff --git a/.dockerignore b/.dockerignore
index cf709889..3f05250c 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1 +1,2 @@
-**/node_modules
+client/node_modules
+node_modules
diff --git a/.env b/.env
index 45a8838d..87485af9 100644
--- a/.env
+++ b/.env
@@ -1,5 +1,8 @@
BASE_URL=http://localhost:12300
+TITLE=Gancio
+DESCRIPTION=diocane
+
ADMIN_EMAIL=admin@example.com
SMTP_HOST=mail.example.com
diff --git a/Dockerfile b/Dockerfile
index 790a72cb..0c140f99 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,7 +6,7 @@ WORKDIR /usr/src/app
COPY package.json .
# install backend dependencies
-RUN yarn install
+RUN yarn
# copy source
COPY . .
diff --git a/app/api.js b/app/api.js
index c77ed637..c6fa75e3 100644
--- a/app/api.js
+++ b/app/api.js
@@ -1,6 +1,5 @@
const express = require('express')
-const { isAuth, isAdmin } = require('./auth')
-
+const { fillUser, isAuth, isAdmin } = require('./auth')
const eventController = require('./controller/event')
const exportController = require('./controller/export')
// const botController = require('./controller/bot')
@@ -12,8 +11,7 @@ const api = express.Router()
// USER API
const userController = require('./controller/user')
-api.route('/login')
- .post(userController.login)
+api.post('/login', userController.login)
api.route('/user')
.post(userController.register)
@@ -25,23 +23,22 @@ api.put('/tag', isAuth, isAdmin, eventController.updateTag)
api.put('/place', isAuth, isAdmin, eventController.updatePlace)
api.route('/user/event')
- .post(isAuth, upload.single('image'), userController.addEvent)
+ .post(fillUser, upload.single('image'), userController.addEvent)
.get(isAuth, userController.getMyEvents)
.put(isAuth, upload.single('image'), userController.updateEvent)
-api.route('/user/event/:id')
- .delete(isAuth, userController.delEvent)
+api.delete('/user/event/:id', isAuth, userController.delEvent)
api.get('/event/meta', eventController.getMeta)
-api.route('/event/:event_id')
- .get(eventController.get)
+api.get('/event/unconfirmed', isAuth, isAdmin, eventController.getUnconfirmed)
+api.post('/event/reminder', eventController.addReminder)
+
+api.get('/event/:event_id', eventController.get)
+api.get('/event/confirm/:event_id', isAuth, isAdmin, eventController.confirm)
-// api.get('/export/feed', exportController.feed)
-// api.get('/export/ics', exportController.ics)
api.get('/export/:type', exportController.export)
-api.route('/event/:year/:month')
- .get(eventController.getAll)
+api.get('/event/:year/:month', eventController.getAll)
api.post('/user/getauthurl', isAuth, userController.getAuthURL)
api.post('/user/code', isAuth, userController.code)
diff --git a/app/auth.js b/app/auth.js
index efb45bc3..71396057 100644
--- a/app/auth.js
+++ b/app/auth.js
@@ -3,6 +3,16 @@ const config = require('./config')
const User = require('./models/user')
const Auth = {
+ async fillUser (req, res, next) {
+ const token = req.body.token || req.params.token || req.headers['x-access-token']
+ console.log('[AUTH] ', token)
+ if (!token) next()
+ jwt.verify(token, config.secret, async (err, decoded) => {
+ if (err) next()
+ req.user = await User.findOne({ where: { email: decoded.email, is_active: true } })
+ next()
+ })
+ },
async isAuth (req, res, next) {
const token = req.body.token || req.params.token || req.headers['x-access-token']
console.log('[AUTH] ', token)
diff --git a/app/config.js b/app/config.js
index 0a020d38..355c9a94 100644
--- a/app/config.js
+++ b/app/config.js
@@ -1,4 +1,7 @@
+/* backend configuration */
let db = {}
+let apiurl
+
if (process.env.NODE_ENV === 'production') {
db = {
host: process.env.DB_HOST,
@@ -7,11 +10,13 @@ if (process.env.NODE_ENV === 'production') {
database: process.env.DB_NAME,
dialect: 'postgres'
}
+ apiurl = process.env.BASE_URL + '/api'
} else {
db = {
dialect: 'sqlite',
storage: './db.sqlite'
}
+ apiurl = 'http://localhost:9000'
}
module.exports = {
@@ -21,7 +26,7 @@ module.exports = {
description: process.env.DESCRIPTION || 'A calendar for radical communities',
baseurl: process.env.BASE_URL || 'http://localhost:8080',
- apiurl: process.env.API_URL || 'http://localhost:9000',
+ apiurl,
db,
admin: process.env.ADMIN_EMAIL,
diff --git a/app/controller/bot.js b/app/controller/bot.js
index 885a91d2..d2c0104e 100644
--- a/app/controller/bot.js
+++ b/app/controller/bot.js
@@ -7,64 +7,65 @@ const moment = require('moment')
moment.locale('it')
const botController = {
bots: [],
- async initialize () {
- console.log('initialize bots')
- const botUsers = await User.findAll({ where: { mastodon_auth: { [Op.ne]: null } } })
- console.log(botUsers)
- botController.bots = botUsers.map(user => {
- console.log('initialize bot ', user.name)
- console.log('.. ', user.mastodon_auth)
- const { client_id, client_secret, access_token } = user.mastodon_auth
- const bot = new Mastodon({ access_token, api_url: `https://${user.mastodon_instance}/api/v1/` })
- const listener = bot.stream('streaming/direct')
- listener.on('message', botController.message)
- listener.on('error', botController.error)
- return { email: user.email, bot }
- })
- console.log(botController.bots)
- },
- add (user, token) {
- const bot = new Mastodon({ access_token: user.mastodon_auth.access_token, api_url: `https://${user.mastodon_instance}/api/v1/` })
- const listener = bot.stream('streaming/direct')
- listener.on('message', botController.message)
- listener.on('error', botController.error)
- botController.bots.push({ email: user.email, bot })
- },
+ // async initialize () {
+ // console.log('initialize bots')
+ // const botUsers = await User.findAll({ where: { mastodon_auth: { [Op.ne]: null } } })
+ // console.log(botUsers)
+ // botController.bots = botUsers.map(user => {
+ // console.log('initialize bot ', user.name)
+ // console.log('.. ', user.mastodon_auth)
+ // const { client_id, client_secret, access_token } = user.mastodon_auth
+ // const bot = new Mastodon({ access_token, api_url: `https://${user.mastodon_instance}/api/v1/` })
+ // const listener = bot.stream('streaming/direct')
+ // listener.on('message', botController.message)
+ // listener.on('error', botController.error)
+ // return { email: user.email, bot }
+ // })
+ // console.log(botController.bots)
+ // },
+ // add (user, token) {
+ // const bot = new Mastodon({ access_token: user.mastodon_auth.access_token, api_url: `https://${user.mastodon_instance}/api/v1/` })
+ // const listener = bot.stream('streaming/direct')
+ // listener.on('message', botController.message)
+ // listener.on('error', botController.error)
+ // botController.bots.push({ email: user.email, bot })
+ // },
post (user, event) {
- const { bot } = botController.bots.filter(b => b.email === user.email)[0]
+ const { client_id, client_secret, access_token } = user.mastodon_auth
+ const bot = new Mastodon({ access_token, api_url: `https://${user.mastodon_instance}/api/v1/` })
const status = `${event.title} @ ${event.place.name} ${moment(event.start_datetime).format('ddd, D MMMM HH:mm')} -
${event.description} - ${event.tags.map(t => '#' + t.tag).join(' ')} ${config.baseurl}/event/${event.id}`
return bot.post('/statuses', { status, visibility: 'private' })
- },
- async message (msg) {
- console.log(msg)
- console.log(msg.data.accounts)
- const replyid = msg.data.in_reply_to_id || msg.data.last_status.in_reply_to_id
- if (!replyid) return
- // const event = await Event.findOne({ where: { activitypub_id: replyid } })
- // if (!event) {
- // check for comment..
- // const comment = await Comment.findOne( {where: { }})
- // }
- // const comment = await Comment.create({activitypub_id: msg.data.last_status.id, text: msg.data.last_status.content, author: msg.data.accounts[0].username })
- // event.addComment(comment)
- // console.log(event)
- // const comment = await Comment.findOne( { where: {activitypub_id: msg.data.in_reply_to}} )
- // console.log('dentro message ', data)
-
- // add comment to specified event
- // let comment
- // if (!event) {
- // const comment = await Comment.findOne({where: {activitypub_id: req.body.id}, include: Event})
- // event = comment.event
- // }
- // const comment = new Comment(req.body)
- // event.addComment(comment)
- },
- error (err) {
- console.log('error ', err)
}
+ // async message (msg) {
+ // console.log(msg)
+ // console.log(msg.data.accounts)
+ // const replyid = msg.data.in_reply_to_id || msg.data.last_status.in_reply_to_id
+ // if (!replyid) return
+ // const event = await Event.findOne({ where: { activitypub_id: replyid } })
+ // if (!event) {
+ // check for comment..
+ // const comment = await Comment.findOne( {where: { }})
+ // }
+ // const comment = await Comment.create({activitypub_id: msg.data.last_status.id, text: msg.data.last_status.content, author: msg.data.accounts[0].username })
+ // event.addComment(comment)
+ // console.log(event)
+ // const comment = await Comment.findOne( { where: {activitypub_id: msg.data.in_reply_to}} )
+ // console.log('dentro message ', data)
+
+ // add comment to specified event
+ // let comment
+ // if (!event) {
+ // const comment = await Comment.findOne({where: {activitypub_id: req.body.id}, include: Event})
+ // event = comment.event
+ // }
+ // const comment = new Comment(req.body)
+ // event.addComment(comment)
+ // },
+ // error (err) {
+ // console.log('error ', err)
+ // }
}
-setTimeout(botController.initialize, 2000)
+// setTimeout(botController.initialize, 2000)
module.exports = botController
diff --git a/app/controller/event.js b/app/controller/event.js
index 397b66e4..5a89d33e 100644
--- a/app/controller/event.js
+++ b/app/controller/event.js
@@ -1,4 +1,4 @@
-const { User, Event, Comment, Tag, Place } = require('../model')
+const { User, Event, Comment, Tag, Place, MailReminder } = require('../model')
const moment = require('moment')
const Sequelize = require('sequelize')
@@ -32,22 +32,51 @@ const eventController = {
res.send(404)
}
},
+
async updatePlace (req, res) {
const place = await Place.findByPk(req.body.id)
await place.update(req.body)
res.json(place)
},
+
async get (req, res) {
const id = req.params.event_id
const event = await Event.findByPk(id, { include: [User, Tag, Comment, Place] })
res.json(event)
},
+ async confirm (req, res) {
+ const id = req.params.event_id
+ const event = await Event.findByPk(id)
+ try {
+ await event.update({ is_visible: true })
+ res.send(200)
+ } catch (e) {
+ res.send(404)
+ }
+ },
+
+ async getUnconfirmed (req, res) {
+ const events = await Event.findAll({
+ where: {
+ is_visible: false
+ },
+ order: [['start_datetime', 'ASC']],
+ include: [Tag, Place]
+ })
+ res.json(events)
+ },
+
+ async addReminder (req, res) {
+ await MailReminder.create(req.body.reminder)
+ res.json(200)
+ },
async getAll (req, res) {
const start = moment().year(req.params.year).month(req.params.month).startOf('month').subtract(1, 'week')
const end = moment().year(req.params.year).month(req.params.month).endOf('month').add(1, 'week')
const events = await Event.findAll({
where: {
+ is_visible: true,
[Sequelize.Op.and]: [
{ start_datetime: { [Sequelize.Op.gte]: start } },
{ start_datetime: { [Sequelize.Op.lte]: end } }
diff --git a/app/controller/user.js b/app/controller/user.js
index 9241229c..9c2d0008 100644
--- a/app/controller/user.js
+++ b/app/controller/user.js
@@ -15,10 +15,9 @@ const userController = {
res.status(404).json({ success: false, message: 'AUTH_FAIL' })
} else if (user) {
if (!user.is_active) {
- res.status(403).json({ success: false, message: 'NOT)CONFIRMED' })
- }
+ res.status(403).json({ success: false, message: 'NOT_CONFIRMED' })
// check if password matches
- else if (!await user.comparePassword(req.body.password)) {
+ } else if (!await user.comparePassword(req.body.password)) {
res.status(403).json({ success: false, message: 'AUTH_FAIL' })
} else {
// if user is found and password is right
@@ -48,21 +47,26 @@ const userController = {
await event.destroy()
res.sendStatus(200)
} else {
- res.sendStatus(404)
+ res.sendStatus(403)
}
},
+ // ADD EVENT
async addEvent (req, res) {
const body = req.body
+
+ // remove description tag and create anchor tag
const description = body.description
.replace(/(<([^>]+)>)/ig, '')
.replace(/(https?:\/\/[^\s]+)/g, '$1')
+
const eventDetails = {
title: body.title,
description,
multidate: body.multidate,
start_datetime: body.start_datetime,
- end_datetime: body.end_datetime
+ end_datetime: body.end_datetime,
+ is_visible: req.user ? true : false
}
if (req.file) {
@@ -88,14 +92,18 @@ const userController = {
const tags = await Tag.findAll({ where: { tag: body.tags } })
await event.addTags(tags)
}
- await req.user.addEvent(event)
+ if (req.user) await req.user.addEvent(event)
event = await Event.findByPk(event.id, { include: [User, Tag, Place] })
+
// check if bot exists
- if (req.user.mastodon_auth) {
+ if (req.user && req.user.mastodon_auth) {
const post = await bot.post(req.user, event)
event.activitypub_id = post.id
event.save()
}
+
+ mail.send(config.admin, 'event', { event })
+
return res.json(event)
},
diff --git a/app/model.js b/app/model.js
index c1d20a91..8948a26b 100644
--- a/app/model.js
+++ b/app/model.js
@@ -1,4 +1,4 @@
const User = require('./models/user')
-const { Event, Comment, Tag, Place } = require('./models/event')
+const { Event, Comment, Tag, Place, MailReminder } = require('./models/event')
-module.exports = { User, Event, Comment, Tag, Place }
+module.exports = { User, Event, Comment, Tag, Place, MailReminder }
diff --git a/app/models/event.js b/app/models/event.js
index 411006d6..ccb45d25 100644
--- a/app/models/event.js
+++ b/app/models/event.js
@@ -4,12 +4,13 @@ const User = require('./user')
const Event = db.define('event', {
title: Sequelize.STRING,
- description: Sequelize.STRING,
+ description: Sequelize.TEXT,
multidate: Sequelize.BOOLEAN,
start_datetime: { type: Sequelize.DATE, index: true },
end_datetime: { type: Sequelize.DATE, index: true },
image_path: Sequelize.STRING,
- activitypub_id: { type: Sequelize.INTEGER, index: true }
+ activitypub_id: { type: Sequelize.INTEGER, index: true },
+ is_visible: Sequelize.BOOLEAN
})
const Tag = db.define('tag', {
@@ -23,11 +24,11 @@ const Comment = db.define('comment', {
text: Sequelize.STRING
})
-const MailSubscription = db.define('subscription', {
+const MailReminder = db.define('reminder', {
filters: Sequelize.JSON,
- mail: Sequelize.TEXT,
+ mail: Sequelize.STRING,
send_on_add: Sequelize.BOOLEAN,
- send_reminder: Sequelize.INTEGER
+ send_reminder: Sequelize.BOOLEAN
})
const Place = db.define('place', {
@@ -47,4 +48,4 @@ Event.belongsTo(Place)
User.hasMany(Event)
Place.hasMany(Event)
-module.exports = { Event, Comment, Tag, Place, MailSubscription }
+module.exports = { Event, Comment, Tag, Place, MailReminder }
diff --git a/client/.env b/client/.env
deleted file mode 100644
index c4e197cc..00000000
--- a/client/.env
+++ /dev/null
@@ -1,3 +0,0 @@
-VUE_BASE_URL=https://localhost:8080/
-VUE_INSTANCE_API=https://localhost:9000/
-VUE_APP_TITLE=Eventi
diff --git a/client/README.md b/client/README.md
index 7b957bd1..aa6102de 100644
--- a/client/README.md
+++ b/client/README.md
@@ -1,4 +1,17 @@
# Gancio
+an event manager for local communities
+
+##Install
+We provide a docker way to run **gancio**.
+
+```
+git clone
+```
+
+##Development
+```
+```
+
## Project setup
```
@@ -13,9 +26,4 @@ yarn run serve
### Compiles and minifies for production
```
yarn run build
-```
-
-### Lints and fixes files
-```
-yarn run lint
-```
+```
\ No newline at end of file
diff --git a/client/src/App.vue b/client/src/App.vue
index f0b34e4f..e53ba9a2 100644
--- a/client/src/App.vue
+++ b/client/src/App.vue
@@ -5,6 +5,7 @@
transition(name="fade" mode="out-in")
router-view(name='modal')
+
+// export default {
+// components: {event},
+// computed: mapState(['events', 'logged'])
+// }
+//
diff --git a/client/src/components/Typeahead.vue b/client/src/components/Typeahead.vue
deleted file mode 100644
index dc3a1410..00000000
--- a/client/src/components/Typeahead.vue
+++ /dev/null
@@ -1,240 +0,0 @@
-
- div(style="position: relative")
-
- b-input-group
- input.form-control(type="search"
- ref="input"
- :placeholder="placeholder"
- v-model="search"
- @input="update"
- autocomplete="off"
- @keydown.backspace="backspace"
- @keydown.up.prevent="up"
- @keydown.down.prevent="down"
- @keydown.enter="hit"
- @keydown.esc="reset(true)"
- @blur="focus = false"
- @focus="focus = true")
-
- div
- b-badge.mr-1(@click="removeSelected(sel)"
- v-for="sel in selectedLabel"
- :key="sel") {{sel}}
-
- b-list-group.groupMenu(v-show='showDropdown')
- b-list-group-item(:key="$index" v-for="(item, $index) in matched"
- href='#'
- :class="{'active': isActive($index)}"
- @mousedown.prevent="hit"
- @mousemove="setActive($index)")
- slot(:name="templateName") {{textField ? item[textField] : item}}
-
-
-
-
-
-
diff --git a/client/src/components/newEvent.vue b/client/src/components/newEvent.vue
index 63e075ad..213df357 100644
--- a/client/src/components/newEvent.vue
+++ b/client/src/components/newEvent.vue
@@ -1,5 +1,4 @@
- //- el-dialog(@close='$router.replace("/")' :title="edit?$t('Edit event'):$t('New event')" center :close-on-press-escape='false' :visible='true')
b-modal(@hidden='$router.replace("/")' :title="edit?$t('Edit event'):$t('New event')" size='md' :visible='true' hide-footer)
b-container
el-tabs.mb-2(v-model='activeTab' v-loading='sending')
@@ -10,7 +9,7 @@
el-form(label-width='120px')
el-form-item(:label='$t("Where")')
el-select(v-model='event.place.name' @change='placeChoosed' filterable allow-create default-first-option)
- el-option(v-for='place in places_name' :label='place' :value='place')
+ el-option(v-for='place in places_name' :label='place' :value='place' :key='place.id')
el-form-item(:label='$t("Address")')
el-input(ref='address' v-model='event.place.address' @keydown.native.enter='next')
el-button.float-right(@click='next' :disabled='!couldProceed') {{$t('Next')}}
@@ -39,10 +38,9 @@
el-input.mb-3(v-model='event.description' type='textarea' :rows='3')
span {{$t('tag_explanation')}}
br
- //- typeahead(v-model="event.tags" :data='tags' multiple)
el-select(v-model='event.tags' multiple filterable allow-create
default-first-option placeholder='Tag')
- el-option(v-for='tag in tags' :key='tag'
+ el-option(v-for='tag in tags' :key='tag.tag'
:label='tag' :value='tag')
el-button.float-right(@click='next' :disabled='!couldProceed') {{$t('Next')}}
@@ -80,6 +78,12 @@ export default {
}
},
name: 'newEvent',
+ watch: {
+ 'time.start' (value) {
+ let [h, m] = value.split(':')
+ this.time.end = (Number(h)+1) + ':' + m
+ }
+ },
async mounted () {
if (this.$route.params.id) {
this.id = this.$route.params.id
diff --git a/client/src/locale/it.js b/client/src/locale/it.js
index 09e3d13e..411468db 100644
--- a/client/src/locale/it.js
+++ b/client/src/locale/it.js
@@ -53,18 +53,25 @@ const it = {
Places: 'Luoghi',
Tags: 'Etichette',
Name: 'Nome',
+ Preview: 'Visualizza',
Save: 'Salva',
Address: 'Indirizzo',
Remove: 'Elimina',
Password: 'Password',
Email: 'Email',
User: 'Utente',
+ Confirm: 'Conferma',
+ Events: 'Eventi',
+ Color: 'Colore',
Edit: 'Modifica',
Admin: 'Amministra',
Today: 'Oggi',
Export: 'Esporta',
send_reminder: 'Ricordamelo il giorno prima',
+ event_confirmed: 'Evento confermato!',
notify_on_insert: `Notifica all'inserimento`,
+ 'event_confirm_explanation': 'Puoi approvare gli eventi inseriti da utenti non registrati',
+ 'admin_place_explanation': 'Puoi modificare i luoghi inseriti',
'Edit event': 'Modifica evento',
'New event': 'Nuovo evento',
'Insert your address': 'Inserisci il tuo indirizzo',
diff --git a/client/src/main.js b/client/src/main.js
index 91ee5ddf..15f657eb 100644
--- a/client/src/main.js
+++ b/client/src/main.js
@@ -5,13 +5,12 @@ import VCalendar from 'v-calendar'
import 'vue-awesome/icons'
import Icon from 'vue-awesome/components/Icon'
-import Typeahead from '@/components/Typeahead'
import VueClipboard from 'vue-clipboard2'
import 'v-calendar/lib/v-calendar.min.css'
import 'bootstrap/dist/css/bootstrap.css'
-import 'bootstrap-vue/dist/bootstrap-vue.css'
+// import 'bootstrap-vue/dist/bootstrap-vue.css'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
@@ -35,7 +34,6 @@ Vue.use(VCalendar, {
Vue.use(BootstrapVue)
Vue.use(VueI18n)
Vue.use(VueClipboard)
-Vue.component('typeahead', Typeahead)
Vue.component('v-icon', Icon)
const messages = {
diff --git a/client/src/store.js b/client/src/store.js
index feaef55a..b9d7e49a 100644
--- a/client/src/store.js
+++ b/client/src/store.js
@@ -113,7 +113,9 @@ export default new Vuex.Store({
},
async addEvent ({ commit }, formData) {
const event = await api.addEvent(formData)
- commit('addEvent', event)
+ if (this.state.logged) {
+ commit('addEvent', event)
+ }
},
async updateEvent ({ commit }, formData) {
const event = await api.updateEvent(formData)
diff --git a/client/vue.config.js b/client/vue.config.js
index 35322208..12df22d9 100644
--- a/client/vue.config.js
+++ b/client/vue.config.js
@@ -1,4 +1,9 @@
+process.env.VUE_APP_API = process.env.NODE_ENV === 'production' ? process.env.BASE_URL || 'http://localhost:9000' : 'http://localhost:9000'
+process.env.VUE_APP_TITLE = process.env.TITLE || 'Gancio'
+process.env.VUE_APP_DESCRIPTION = process.env.DESCRIPTION || 'Event manager for radical movements'
+
module.exports = {
+ publicPath: process.env.BASE_URL,
devServer: {
disableHostCheck: true
},
diff --git a/client/yarn.lock b/client/yarn.lock
index 877bcffc..4aaba37a 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -64,16 +64,17 @@
"@babel/traverse" "^7.1.0"
"@babel/types" "^7.0.0"
-"@babel/helper-create-class-features-plugin@^7.2.3":
- version "7.2.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.2.3.tgz#f6e719abb90cb7f4a69591e35fd5eb89047c4a7c"
- integrity sha512-xO/3Gn+2C7/eOUeb0VRnSP1+yvWHNxlpAot1eMhtoKDCN7POsyQP5excuT5UsV5daHxMWBeIIOeI5cmB8vMRgQ==
+"@babel/helper-create-class-features-plugin@^7.3.0", "@babel/helper-create-class-features-plugin@^7.3.4":
+ version "7.3.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.4.tgz#092711a7a3ad8ea34de3e541644c2ce6af1f6f0c"
+ integrity sha512-uFpzw6L2omjibjxa8VGZsJUPL5wJH0zzGKpoz0ccBkzIa6C8kWNUbiBmQ0rgOKWlHJ6qzmfa6lTiGchiV8SC+g==
dependencies:
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-member-expression-to-functions" "^7.0.0"
"@babel/helper-optimise-call-expression" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-replace-supers" "^7.2.3"
+ "@babel/helper-replace-supers" "^7.3.4"
+ "@babel/helper-split-export-declaration" "^7.0.0"
"@babel/helper-define-map@^7.1.0":
version "7.1.0"
diff --git a/docker-compose.yml b/docker-compose.yml
index a868bc09..e9c2a7ec 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -16,6 +16,8 @@ services:
build: .
ports:
- '12300:12300'
+ volumes:
+ - ./uploads:/usr/src/app/uploads
env_file: .env
environment:
diff --git a/package.json b/package.json
index b77bf446..cf4ca957 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"pg": "^7.8.1",
"pug": "^2.0.3",
"sequelize": "^4.41.0",
+ "sharp": "^0.21.3",
"sqlite3": "^4.0.3"
},
"devDependencies": {
diff --git a/views/feed/rss.pug b/views/feed/rss.pug
index 1528be4b..8a0ed94c 100644
--- a/views/feed/rss.pug
+++ b/views/feed/rss.pug
@@ -3,7 +3,7 @@ rss(version='2.0', xmlns:atom='#{config.baseurl}
- atom:link(href='#{config.apiurl}/export/feed/rss', rel='self', type='application/rss+xml')
+
description #{config.description}
language #{config.locale}
//- if events.length
@@ -17,6 +17,7 @@ rss(version='2.0', xmlns:atom='
+ |
| !{event.description}
| ]]>
pubDate= new Date(event.createdAt).toUTCString()