diff --git a/components/Event.vue b/components/Event.vue
index 867549db..e6cf69ee 100644
--- a/components/Event.vue
+++ b/components/Event.vue
@@ -8,12 +8,12 @@ v-card.h-event.event.d-flex(itemscope itemtype="https://schema.org/Event")
v-card-text.body.pt-0.pb-0
time.dt-start.subtitle-1(:datetime='event.start_datetime | unixFormat("YYYY-MM-DD HH:mm")' itemprop="startDate" :content="event.start_datetime | unixFormat('YYYY-MM-DDTHH:mm')") {{ event | when }}
.d-none.dt-end(itemprop="endDate" :content="event.end_datetime | unixFormat('YYYY-MM-DDTHH:mm')") {{ event.end_datetime | unixFormat('YYYY-MM-DD HH:mm') }}
- nuxt-link.place.d-block.p-location.pl-0(text color='primary' :to='`/place/${event.place.name}`' itemprop="location" itemscope itemtype="https://schema.org/Place") {{ event.place.name }}
+ nuxt-link.place.d-block.p-location.pl-0(text color='primary' :to='`/place/${encodeURIComponent(event.place.name)}`' itemprop="location" itemscope itemtype="https://schema.org/Place") {{ event.place.name }}
.d-none(itemprop='address') {{ event.place.address }}
v-card-actions.pt-0.actions.justify-space-between
.tags
- v-chip.ml-1.mt-1(v-for='tag in event.tags.slice(0, 6)' small :to='`/tag/${tag}`'
+ v-chip.ml-1.mt-1(v-for='tag in event.tags.slice(0, 6)' small :to='`/tag/${encodeURIComponent(tag)}`'
:key='tag' outlined color='primary') {{ tag }}
diff --git a/components/WhereInput.vue b/components/WhereInput.vue
index c4542cff..cc744cdd 100644
--- a/components/WhereInput.vue
+++ b/components/WhereInput.vue
@@ -10,6 +10,7 @@ v-row
hide-no-data
@input.native='search'
persistent-hint
+ :value='value'
:items="places"
item-text='name'
@focus='search'
@@ -83,13 +84,13 @@ export default {
selectPlace (p) {
if (!p) { return }
if (typeof p === 'object' && !p.create) {
- this.place.name = p.name.trim()
+ this.place.name = p.name
this.place.address = p.address
this.place.id = p.id
this.disableAddress = true
} else { // this is a new place
- this.place.name = p.name || p
- const tmpPlace = this.place.name.trim().toLocaleLowerCase()
+ this.place.name = (p.name || p).trim()
+ const tmpPlace = this.place.name.toLocaleLowerCase()
// search for a place with the same name
const place = this.places.find(p => !p.create && p.name.trim().toLocaleLowerCase() === tmpPlace)
if (place) {
@@ -99,7 +100,6 @@ export default {
this.disableAddress = true
} else {
delete this.place.id
- this.place.name = tmpPlace
this.place.address = ''
this.disableAddress = false
this.$refs.place.blur()
diff --git a/pages/place/_place.vue b/pages/place/_place.vue
index a1e1f500..43738ab9 100644
--- a/pages/place/_place.vue
+++ b/pages/place/_place.vue
@@ -33,7 +33,7 @@ export default {
asyncData({ $axios, params, error }) {
try {
const place = params.place
- return $axios.$get(`/place/${place}`)
+ return $axios.$get(`/place/${encodeURIComponent(place)}`)
} catch (e) {
error({ statusCode: 400, message: 'Error!' })
}
diff --git a/server/api/controller/event.js b/server/api/controller/event.js
index 8ad33537..063dc6cb 100644
--- a/server/api/controller/event.js
+++ b/server/api/controller/event.js
@@ -23,6 +23,30 @@ const log = require('../../log')
const eventController = {
+ async _findOrCreatePlace (body) {
+ if (body.place_id) {
+ const place = await Place.findByPk(body.place_id)
+ if (!place) {
+ throw new Error(`Place not found`)
+ }
+ return place
+ }
+
+ const place_name = body.place_name && body.place_name.trim()
+ const place_address = body.place_address && body.place_address.trim()
+ if (!place_address || !place_name) {
+ throw new Error(`place_id or place_name and place_address are required`)
+ }
+ let place = await Place.findOne({ where: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), Sequelize.Op.eq, place_name.toLocaleLowerCase()) })
+ if (!place) {
+ place = await Place.create({
+ name: place_name,
+ address: place_address
+ })
+ }
+ return place
+ },
+
async searchMeta(req, res) {
const search = req.query.search
@@ -389,29 +413,18 @@ const eventController = {
// find or create the place
let place
- if (body.place_id) {
- place = await Place.findByPk(body.place_id)
+ try {
+ place = await eventController._findOrCreatePlace(body)
if (!place) {
return res.status(400).send(`Place not found`)
}
- } else {
- if (!body.place_name) {
- return res.status(400).send(`Place not found`)
- }
- place = await Place.findOne({ where: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), Op.eq, body.place_name.trim().toLocaleLowerCase()) })
- if (!place) {
- if (!body.place_address || !body.place_name) {
- return res.status(400).send(`place_id or place_name and place_address required`)
- }
- place = await Place.create({
- name: body.place_name,
- address: body.place_address
- })
- }
+ } catch (e) {
+ return res.status(400).send(e.message)
}
+
const eventDetails = {
- title: body.title,
+ title: body.title.trim(),
// sanitize and linkify html
description: helpers.sanitizeHTML(linkifyHtml(body.description || '')),
multidate: body.multidate,
@@ -543,27 +556,14 @@ const eventController = {
// find or create the place
let place
- if (body.place_id) {
- place = await Place.findByPk(body.place_id)
+ try {
+ place = await eventController._findOrCreatePlace(body)
if (!place) {
return res.status(400).send(`Place not found`)
}
- } else {
- if (!body.place_name) {
- return res.status(400).send(`Place not found`)
- }
- place = await Place.findOne({ where: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), Op.eq, body.place_name.trim().toLocaleLowerCase()) })
- if (!place) {
- if (!body.place_address || !body.place_name) {
- return res.status(400).send(`place_id or place_name and place_address required`)
- }
- place = await Place.create({
- name: body.place_name,
- address: body.place_address
- })
- }
+ } catch (e) {
+ return res.status(400).send(e.message)
}
-
await event.setPlace(place)
// create/assign tags
diff --git a/tests/app.test.js b/tests/app.test.js
index b4dcfd6c..8c1e8a9f 100644
--- a/tests/app.test.js
+++ b/tests/app.test.js
@@ -155,7 +155,7 @@ describe('Events', () => {
const required_fields = {
'title': {},
'start_datetime': { title: 'test title' },
- 'place_id or place_name and place_address': { title: 'test title', start_datetime: dayjs().unix() + 1000, place_name: 'test place name' },
+ 'place_id or place_name and place_address are': { title: 'test title', start_datetime: dayjs().unix() + 1000, place_name: 'test place name' },
}
const promises = Object.keys(required_fields).map(async field => {
@@ -200,9 +200,9 @@ describe('Events', () => {
})
- test('should trim tags', async () => {
+ test('should trim tags and title', async () => {
const event = {
- title: 'test title 4',
+ title: ' test title 4 ',
place_id: places[0],
start_datetime: dayjs().unix() + 1000,
tags: [' test tag ']
@@ -213,6 +213,7 @@ describe('Events', () => {
.expect(200)
.expect('Content-Type', /json/)
+ expect(response.body.title).toBe('test title 4')
expect(response.body.tags[0]).toBe('test tag')
})
})
@@ -300,6 +301,17 @@ describe('Place', () => {
expect(response.body.length).toBe(2)
})
+ test('should trim place\'s name and address', async () => {
+ const ret = await request(app).post('/api/event')
+ .send({ title: 'test trimming', place_name: ' test place with white Space ',
+ place_address: ' address with Space ', start_datetime: dayjs().unix() + 1000 })
+ .auth(token.access_token, { type: 'bearer' })
+ .expect(200)
+
+ expect(ret.body.place.name).toBe('test place with white Space')
+ expect(ret.body.place.address).toBe('address with Space')
+ })
+
})
let collections = []
@@ -382,20 +394,14 @@ describe('Collection', () => {
})
test('shoud filter for tags', async () => {
- let response = await request(app)
+ await request(app)
.post('/api/filter')
.send({ collectionId: collections[0], tags: ['test'] })
.auth(token.access_token, { type: 'bearer' })
.expect(200)
- // response = await request(app)
- // .get(`/api/filter/${response.body.id}`)
- // .auth(token.access_token, { type: 'bearer' })
- // .expect(200)
- // expect(response.body.length).toBe(1)
-
- response = await request(app)
+ const response = await request(app)
.get(`/api/collections/test collection`)
.expect(200)