parent
b93cf91dbd
commit
7111b4578b
31 changed files with 270 additions and 70 deletions
|
@ -61,6 +61,7 @@ api.get('/event/:event_id', eventController.get)
|
|||
|
||||
// confirm event
|
||||
api.get('/event/confirm/:event_id', isAuth, isAdmin, eventController.confirm)
|
||||
api.get('/event/unconfirm/:event_id', isAuth, isAdmin, eventController.unconfirm)
|
||||
|
||||
// export events (rss/ics)
|
||||
api.get('/export/:type', exportController.export)
|
||||
|
|
|
@ -82,6 +82,18 @@ const eventController = {
|
|||
}
|
||||
},
|
||||
|
||||
async unconfirm (req, res) {
|
||||
const id = req.params.event_id
|
||||
const event = await Event.findByPk(id)
|
||||
|
||||
try {
|
||||
await event.update({ is_visible: false })
|
||||
res.send(200)
|
||||
} catch (e) {
|
||||
res.send(404)
|
||||
}
|
||||
},
|
||||
|
||||
async getUnconfirmed (req, res) {
|
||||
const events = await Event.findAll({
|
||||
where: {
|
||||
|
|
|
@ -198,6 +198,9 @@ const userController = {
|
|||
async update (req, res) {
|
||||
const user = await User.findByPk(req.body.id)
|
||||
if (user) {
|
||||
if (!user.is_active && req.body.is_active) {
|
||||
await mail.send(user.email, 'confirm', { user, config })
|
||||
}
|
||||
await user.update(req.body)
|
||||
res.json(user)
|
||||
} else {
|
||||
|
@ -209,7 +212,7 @@ const userController = {
|
|||
const n_users = await User.count()
|
||||
try {
|
||||
if (n_users === 0) {
|
||||
// admin will be the first registered user
|
||||
// the first registered user will be an active admin
|
||||
req.body.is_active = req.body.is_admin = true
|
||||
} else {
|
||||
req.body.is_active = false
|
||||
|
|
19
app/cron.js
19
app/cron.js
|
@ -14,7 +14,7 @@ async function sendNotification (notification, event, eventNotification) {
|
|||
const p = mail.send(notification.email, 'event', { event })
|
||||
promises.push(p)
|
||||
break
|
||||
case 'mail_admin':
|
||||
case 'admin_email':
|
||||
const admins = await User.findAll({ where: { is_admin: true } })
|
||||
promises.push(admins.map(admin =>
|
||||
mail.send(admin.email, 'event', { event, to_confirm: true, notification })))
|
||||
|
@ -26,7 +26,7 @@ async function sendNotification (notification, event, eventNotification) {
|
|||
promises.push(b)
|
||||
}
|
||||
// user publish
|
||||
if (event.user && event.user.mastodon_auth) {
|
||||
if (event.user && event.user.mastodon_auth && event.user.mastodon_auth.access_token) {
|
||||
const b = bot.post(event.user.mastodon_auth, event).then(ret => {
|
||||
event.activitypub_id = ret.id
|
||||
return event.save()
|
||||
|
@ -45,17 +45,24 @@ async function sendNotification (notification, event, eventNotification) {
|
|||
async function loop () {
|
||||
settings = await settingsController.settings()
|
||||
// get all event notification in queue
|
||||
const eventNotifications = await EventNotification.findAll()
|
||||
const eventNotifications = await EventNotification.findAll({ where: { status: 'new' } })
|
||||
const promises = eventNotifications.map(async e => {
|
||||
const event = await Event.findByPk(e.eventId, { include: [User, Place, Tag] })
|
||||
if (!event.place) return
|
||||
const notification = await Notification.findByPk(e.notificationId)
|
||||
await sendNotification(notification, event, e)
|
||||
e.destroy()
|
||||
try {
|
||||
await sendNotification(notification, event, e)
|
||||
e.status = 'sent'
|
||||
e.save()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
e.status = 'error'
|
||||
return e.save()
|
||||
}
|
||||
})
|
||||
|
||||
return Promise.all(promises)
|
||||
}
|
||||
|
||||
setInterval(loop, 20000)
|
||||
setInterval(loop, 260000)
|
||||
loop()
|
||||
|
|
4
app/emails/confirm/html.pug
Normal file
4
app/emails/confirm/html.pug
Normal file
|
@ -0,0 +1,4 @@
|
|||
p= t('confirm_email')
|
||||
|
||||
hr
|
||||
small #{config.baseurl}
|
|
@ -1,6 +1,4 @@
|
|||
h4 Gancio
|
||||
|
||||
p= t('registration_email')
|
||||
|
||||
small --
|
||||
small https://cisti.org
|
||||
hr
|
||||
small #{config.baseurl}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"registration_email": "Ciao, la tua registrazione sarà confermata nei prossimi giorni. Riceverai una conferma non temere."
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"registration_email": "registration_email"
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"registration_email": "Ciao, la tua registrazione sarà confermata nei prossimi giorni. Riceverai una conferma non temere."
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"registration_email": "registration_email"
|
||||
}
|
26
app/migrations/20190316230454-notification_status.js
Normal file
26
app/migrations/20190316230454-notification_status.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
up: (queryInterface, Sequelize) => {
|
||||
/*
|
||||
Add altering commands here.
|
||||
Return a promise to correctly handle asynchronicity.
|
||||
|
||||
Example:
|
||||
return queryInterface.createTable('users', { id: Sequelize.INTEGER });
|
||||
*/
|
||||
return queryInterface.addColumn('EventNotifications', 'status',
|
||||
{ type: Sequelize.ENUM, values: ['new', 'sent', 'error'], index: true, defaultValue: 'new' })
|
||||
},
|
||||
|
||||
down: (queryInterface, Sequelize) => {
|
||||
/*
|
||||
Add reverting commands here.
|
||||
Return a promise to correctly handle asynchronicity.
|
||||
|
||||
Example:
|
||||
return queryInterface.dropTable('users');
|
||||
*/
|
||||
return queryInterface.removeColumn('EventNotifications', 'status')
|
||||
}
|
||||
};
|
|
@ -48,7 +48,15 @@ Event.hasMany(Comment)
|
|||
Event.belongsToMany(Tag, { through: 'tagEvent' })
|
||||
Tag.belongsToMany(Event, { through: 'tagEvent' })
|
||||
|
||||
const EventNotification = db.define('EventNotification')
|
||||
const EventNotification = db.define('EventNotification', {
|
||||
status: {
|
||||
type: Sequelize.ENUM,
|
||||
values: ['new', 'sent', 'error'],
|
||||
defaultValue: 'new',
|
||||
index: true
|
||||
}
|
||||
})
|
||||
|
||||
Event.belongsToMany(Notification, { through: EventNotification })
|
||||
Notification.belongsToMany(Event, { through: EventNotification })
|
||||
|
||||
|
|
37
app/models/index.js
Normal file
37
app/models/index.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const Sequelize = require('sequelize');
|
||||
const basename = path.basename(__filename);
|
||||
const env = process.env.NODE_ENV || 'development';
|
||||
const config = require(__dirname + '/../config/config.json')[env];
|
||||
const db = {};
|
||||
|
||||
let sequelize;
|
||||
if (config.use_env_variable) {
|
||||
sequelize = new Sequelize(process.env[config.use_env_variable], config);
|
||||
} else {
|
||||
sequelize = new Sequelize(config.database, config.username, config.password, config);
|
||||
}
|
||||
|
||||
fs
|
||||
.readdirSync(__dirname)
|
||||
.filter(file => {
|
||||
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
|
||||
})
|
||||
.forEach(file => {
|
||||
const model = sequelize['import'](path.join(__dirname, file));
|
||||
db[model.name] = model;
|
||||
});
|
||||
|
||||
Object.keys(db).forEach(modelName => {
|
||||
if (db[modelName].associate) {
|
||||
db[modelName].associate(db);
|
||||
}
|
||||
});
|
||||
|
||||
db.sequelize = sequelize;
|
||||
db.Sequelize = Sequelize;
|
||||
|
||||
module.exports = db;
|
|
@ -1,3 +1,6 @@
|
|||
module.exports = {
|
||||
'extends': 'standard'
|
||||
'extends': 'standard',
|
||||
"rules": {
|
||||
"camelcase": 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ function get (path) {
|
|||
store.commit('logout')
|
||||
return false
|
||||
}
|
||||
throw e.response && e.response.data &&
|
||||
e.response.data.errors && e.response.data.errors[0].message
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -29,6 +31,8 @@ function post (path, data) {
|
|||
store.commit('logout')
|
||||
return false
|
||||
}
|
||||
throw e.response && e.response.data &&
|
||||
e.response.data.errors && e.response.data.errors[0].message
|
||||
})
|
||||
}
|
||||
function put (path, data) {
|
||||
|
@ -43,12 +47,18 @@ function del (path) {
|
|||
export default {
|
||||
login: (email, password) => post('/login', { email, password }),
|
||||
register: user => post('/user', user),
|
||||
|
||||
getAllEvents: (month, year) => get(`/event/${year}/${month}/`),
|
||||
getUnconfirmedEvents: () => get('/event/unconfirmed'),
|
||||
|
||||
confirmEvent: id => get(`/event/confirm/${id}`),
|
||||
unconfirmEvent: id => get(`/event/unconfirm/${id}`),
|
||||
|
||||
addNotification: notification => post('/event/notification', notification),
|
||||
|
||||
addEvent: event => post('/user/event', event),
|
||||
updateEvent: event => put('/user/event', event),
|
||||
|
||||
updatePlace: place => put('/place', place),
|
||||
delEvent: eventId => del(`/user/event/${eventId}`),
|
||||
getEvent: eventId => get(`/event/${eventId}`),
|
||||
|
@ -59,8 +69,6 @@ export default {
|
|||
updateUser: user => put('/user', user),
|
||||
getAuthURL: mastodonInstance => post('/user/getauthurl', mastodonInstance),
|
||||
setCode: code => post('/user/code', code),
|
||||
getKnowLocations: () => get('/locations'),
|
||||
getKnowTags: () => get('/tags'),
|
||||
getAdminSettings: () => get('/settings')
|
||||
// setAdminSetting: (key, value) => post('/settings', { key, value })
|
||||
}
|
||||
|
|
25
client/src/components/About.vue
Normal file
25
client/src/components/About.vue
Normal file
|
@ -0,0 +1,25 @@
|
|||
<template lang="pug">
|
||||
b-modal(hide-footer @hidden='$router.replace("/")' :title='$t("About")'
|
||||
:visible='true' size='lg')
|
||||
h5 Chi siamo
|
||||
p.
|
||||
Gancio e' un progetto dell'<a href='https://autistici.org/underscore'>underscore hacklab</a> e uno dei
|
||||
servizi di <a href='https://cisti.org'>cisti.org</a>.
|
||||
|
||||
h5 Ok, ma cosa vuol dire?
|
||||
blockquote.
|
||||
Se vieni a Torino e dici: "ehi, ci diamo un gancio alle 8?" nessuno si presenterà con i guantoni per fare a mazzate.
|
||||
Darsi un gancio vuol dire beccarsi alle ore X in un posto Y
|
||||
p
|
||||
small A: a che ora è il gancio in radio per andare al presidio?
|
||||
p
|
||||
small B: non so ma domani non posso venire, ho gia' un gancio per caricare il bar.
|
||||
|
||||
|
||||
h5 Contatti
|
||||
p.
|
||||
Hai scritto una nuova interfaccia per gancio? Vuoi aprire un nuovo nodo di gancio nella tua città?
|
||||
C'è qualcosa che vorresti migliorare? Aiuti e suggerimenti sono sempre benvenuti, puoi scriverci
|
||||
su underscore chicciola autistici.org
|
||||
|
||||
</template>
|
|
@ -1,16 +1,26 @@
|
|||
<template lang="pug">
|
||||
b-modal(hide-footer @hidden='$router.replace("/")' :title='$t("Admin")' :visible='true' size='lg')
|
||||
b-modal(hide-footer @hidden='$router.replace("/")' :title='$t("Admin")'
|
||||
:visible='true' size='lg')
|
||||
el-tabs(tabPosition='left' v-model='tab')
|
||||
|
||||
//- USERS
|
||||
el-tab-pane.pt-1
|
||||
template(slot='label')
|
||||
v-icon(name='users')
|
||||
span.ml-1 {{$t('Users')}}
|
||||
b-table(:items='users' :fields='userFields' striped small hover
|
||||
:per-page='5' :current-page='userPage')
|
||||
template(slot='action' slot-scope='data')
|
||||
el-button.mr-1(size='mini' :type='data.item.is_active?"warning":"success"' @click='toggle(data.item)') {{data.item.is_active?$t('Deactivate'):$t('Activate')}}
|
||||
el-button(size='mini' :type='data.item.is_admin?"danger":"warning"' @click='toggleAdmin(data.item)') {{data.item.is_admin?$t('Remove Admin'):$t('Admin')}}
|
||||
el-table(:data='paginatedUsers' small)
|
||||
el-table-column(label='Email')
|
||||
template(slot-scope='data')
|
||||
el-popover(trigger='hover' :content='data.row.description' width='400')
|
||||
span(slot='reference') {{data.row.email}}
|
||||
el-table-column(label='Azioni')
|
||||
template(slot-scope='data')
|
||||
el-button.mr-1(size='mini'
|
||||
:type='data.row.is_active?"warning":"success"'
|
||||
@click='toggle(data.row)') {{data.row.is_active?$t('Deactivate'):$t('Activate')}}
|
||||
el-button(size='mini'
|
||||
:type='data.row.is_admin?"danger":"warning"'
|
||||
@click='toggleAdmin(data.row)') {{data.row.is_admin?$t('Remove Admin'):$t('Admin')}}
|
||||
el-pagination(:page-size='perPage' :currentPage.sync='userPage' :total='users.length')
|
||||
|
||||
//- PLACES
|
||||
|
@ -124,8 +134,12 @@ export default {
|
|||
this.eventPage * this.perPage)
|
||||
},
|
||||
paginatedTags () {
|
||||
return this.tags.slice((this.tagPage-1) * this.perPage,
|
||||
return this.tags.slice((this.tagPage-1) * this.perPage,
|
||||
this.tagPage * this.perPage)
|
||||
},
|
||||
paginatedUsers () {
|
||||
return this.users.slice((this.userPage-1) * this.perPage,
|
||||
this.userPage * this.perPage)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
size='mini' :key='tag.tag') {{tag.tag}}
|
||||
.ml-auto(v-if='mine')
|
||||
hr
|
||||
el-button(v-if='event.is_visible' plain type='warning' @click.prevents='toggle' icon='el-icon-remove') {{$t('Unconfirm')}}
|
||||
el-button(v-else plain type='success' @click.prevents='toggle' icon='el-icon-remove') {{$t('Confirm')}}
|
||||
el-button(plain type='danger' @click.prevent='remove' icon='el-icon-remove') {{$t('Remove')}}
|
||||
el-button(plain type='primary' @click='$router.replace("/edit/"+event.id)') <v-icon color='orange' name='edit'/> {{$t('Edit')}}
|
||||
|
||||
|
@ -75,6 +77,20 @@ export default {
|
|||
await api.delEvent(this.event.id)
|
||||
this.delEvent(this.event.id)
|
||||
this.$refs.eventDetail.hide()
|
||||
},
|
||||
async toggle () {
|
||||
try {
|
||||
if (this.event.is_visible) {
|
||||
|
||||
await api.unconfirmEvent(this.id)
|
||||
this.event.is_visible = false
|
||||
} else {
|
||||
await api.confirmEvent(this.id)
|
||||
this.event.is_visible = true
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
<script>
|
||||
import api from '@/api'
|
||||
import { mapActions } from 'vuex'
|
||||
import { log } from 'util';
|
||||
import { Message } from 'element-ui'
|
||||
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
|
@ -29,13 +30,19 @@ export default {
|
|||
...mapActions(['login']),
|
||||
async submit (e) {
|
||||
e.preventDefault()
|
||||
const user = await api.login(this.email, this.password)
|
||||
if (!user) {
|
||||
return;
|
||||
try {
|
||||
const user = await api.login(this.email, this.password)
|
||||
if (!user) {
|
||||
Message({ message: this.$t('login error'), type: 'error' })
|
||||
return;
|
||||
}
|
||||
this.login(user)
|
||||
Message({ message: this.$t('Logged'), type: 'success' })
|
||||
} catch (e) {
|
||||
Message({ message: this.$t('login error'), type: 'error' })
|
||||
}
|
||||
this.login(user)
|
||||
this.email = this.password = ''
|
||||
this.$router.go(-1)
|
||||
this.$router.replace("/")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,12 @@
|
|||
span.d-md-none {{$t('Admin')}}
|
||||
b-nav-item(to='/export' v-b-tooltip :title='$t("Export")') <v-icon name='file-export' color='yellow'/>
|
||||
span.d-md-none {{$t('Export')}}
|
||||
b-nav-item(v-if='logged' variant='danger' @click='logout' v-b-tooltip :title='$t("Logout")') <v-icon color='red' name='sign-out-alt'/>
|
||||
b-nav-item(v-if='logged' @click='logout' v-b-tooltip :title='$t("Logout")') <v-icon color='red' name='sign-out-alt'/>
|
||||
span.d-md-none {{$t('Logout')}}
|
||||
b-navbar-nav.ml-auto
|
||||
b-nav-item(to='/about')
|
||||
span {{$t('Info')}} <v-icon color='#ff9fc4' name='question-circle'/>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import {mapState, mapActions} from 'vuex'
|
||||
|
|
|
@ -35,8 +35,8 @@ export default {
|
|||
async register () {
|
||||
try {
|
||||
const user = await api.register(this.user)
|
||||
this.$refs.modal.hide()
|
||||
if (!user.is_admin) {
|
||||
this.$refs.modal.hide()
|
||||
Message({
|
||||
message: this.$t('registration_complete'),
|
||||
type: 'success'
|
||||
|
@ -48,6 +48,10 @@ export default {
|
|||
})
|
||||
}
|
||||
} catch (e) {
|
||||
Message({
|
||||
message: e,
|
||||
type: 'error'
|
||||
})
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template lang="pug">
|
||||
b-modal(:title="$t('Settings')" hide-footer @hide='$router.go(-1)' :visible='true')
|
||||
b-modal(:title="$t('Settings')" hide-footer @hidden='$router.replace("/")' :visible='true')
|
||||
el-form(inline)
|
||||
el-input(v-model="mastodon_instance" type='success')
|
||||
span(slot='prepend') Mastodon instance
|
||||
|
|
|
@ -1,35 +1,40 @@
|
|||
<template lang="pug">
|
||||
b-modal(ref='modal' @hidden='$router.replace("/")' size='md' :visible='true'
|
||||
b-modal(ref='modal' @hidden='$router.replace("/")' size='lg' :visible='true'
|
||||
:title="edit?$t('Edit event'):$t('New event')" hide-footer)
|
||||
b-container
|
||||
el-tabs.mb-2(v-model='activeTab' v-loading='sending' @tab-click.native='changeTab')
|
||||
|
||||
//- NOT LOGGED EVENT
|
||||
el-tab-pane(v-show='!user')
|
||||
span(slot='label') {{$t('anon_newevent')}} <v-icon name='user-secret'/>
|
||||
p(v-html="$t('anon_newevent_explanation')")
|
||||
el-button.float-right(@click='next' :disabled='!couldProceed') Mi sento in colpa
|
||||
|
||||
//- WHERE
|
||||
el-tab-pane
|
||||
span(slot='label') {{$t('Where')}} <v-icon name='map-marker-alt'/>
|
||||
p {{$t('where_explanation')}}
|
||||
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' :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')}}
|
||||
div {{$t('where_explanation')}}
|
||||
el-select.mb-3(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' :key='place.id')
|
||||
div {{$t("Address")}}
|
||||
el-input.mb-3(ref='address' v-model='event.place.address' @keydown.native.enter='next')
|
||||
el-button.float-right(@click='next' :disabled='!couldProceed') {{$t('Next')}}
|
||||
|
||||
//- WHEN
|
||||
el-tab-pane
|
||||
span(slot='label') {{$t('When')}} <v-icon name='clock'/>
|
||||
el-form(label-width='120px')
|
||||
span {{event.multidate ? $t('dates_explanation') : $t('date_explanation')}}
|
||||
span {{event.multidate ? $t('dates_explanation') : $t('date_explanation')}}
|
||||
el-switch.float-right(v-model='event.multidate' :active-text="$t('multidate_explanation')")
|
||||
v-date-picker.mb-3(:mode='event.multidate ? "range" : "single"' v-model='date' is-inline
|
||||
is-expanded :min-date='new Date()' @input='date ? $refs.time_start.focus() : false')
|
||||
el-form-item(:label="$t('time_start_explanation')")
|
||||
el-time-select(ref='time_start'
|
||||
v-model="time.start"
|
||||
:picker-options="{ start: '00:00', step: '00:30', end: '24:00'}")
|
||||
el-form-item(:label="$t('time_end_explanation')")
|
||||
el-time-select(v-model='time.end'
|
||||
:picker-options="{start: '00:00', step: '00:30', end: '24:00'}")
|
||||
el-button.float-right(@click='next' :disabled='!couldProceed') {{$t('Next')}}
|
||||
v-date-picker.mb-3(:mode='event.multidate ? "range" : "single"' v-model='date' is-inline
|
||||
is-expanded :min-date='new Date()' @input='date ? $refs.time_start.focus() : false')
|
||||
div {{$t('time_start_explanation')}}
|
||||
el-time-select.mb-3(ref='time_start'
|
||||
v-model="time.start"
|
||||
:picker-options="{ start: '00:00', step: '00:30', end: '24:00'}")
|
||||
div {{$t('time_end_explanation')}}
|
||||
el-time-select(v-model='time.end'
|
||||
:picker-options="{start: '00:00', step: '00:30', end: '24:00'}")
|
||||
el-button.float-right(@click='next' :disabled='!couldProceed') {{$t('Next')}}
|
||||
|
||||
el-tab-pane
|
||||
span(slot='label') {{$t('What')}} <v-icon name='file-alt'/>
|
||||
|
@ -111,20 +116,23 @@ export default {
|
|||
...mapState({
|
||||
tags: state => state.tags.map(t => t.tag ),
|
||||
places_name: state => state.places.map(p => p.name ),
|
||||
places: state => state.places
|
||||
places: state => state.places,
|
||||
user: state => state.user
|
||||
}),
|
||||
couldProceed () {
|
||||
switch(Number(this.activeTab)) {
|
||||
case 0:
|
||||
return true
|
||||
case 1:
|
||||
return this.event.place.name.length>0 &&
|
||||
this.event.place.address.length>0
|
||||
case 1:
|
||||
case 2:
|
||||
if (this.date && this.time.start) return true
|
||||
break
|
||||
case 2:
|
||||
case 3:
|
||||
return this.event.title.length>0
|
||||
break
|
||||
case 3:
|
||||
case 4:
|
||||
return true
|
||||
break
|
||||
}
|
||||
|
|
|
@ -77,6 +77,8 @@ const it = {
|
|||
'admin_place_explanation': 'Puoi modificare i luoghi inseriti',
|
||||
'Edit event': 'Modifica evento',
|
||||
'New event': 'Nuovo evento',
|
||||
anon_newevent: 'Evento senza autore',
|
||||
anon_newevent_explanation: `Puoi inserire un evento senza registrarti o fare il login, ma in questo caso dovrai aspettare che qualcuno lo legga confermando che si tratta di un evento adatto a questo spazio, delegando questa scelta.<br/><br/>Ti consigliamo quindi di fare il <a href="/login">login</a> o di <a href="/register">registrarti</a>, ma se vuoi continuare fai pure (ti devi sentire un po' in colpa però).`,
|
||||
'Insert your address': 'Inserisci il tuo indirizzo',
|
||||
registration_complete: 'Controlla la tua posta (anche la cartella spam)',
|
||||
registration_email: `Ciao, la tua registrazione sarà confermata nei prossimi giorni. Riceverai una conferma non temere.`,
|
||||
|
|
|
@ -19,6 +19,8 @@ import 'vue-awesome/icons/users'
|
|||
import 'vue-awesome/icons/calendar'
|
||||
import 'vue-awesome/icons/edit'
|
||||
import 'vue-awesome/icons/envelope-open-text'
|
||||
import 'vue-awesome/icons/user-secret'
|
||||
import 'vue-awesome/icons/question-circle'
|
||||
|
||||
import Icon from 'vue-awesome/components/Icon'
|
||||
|
||||
|
@ -30,7 +32,7 @@ import 'bootstrap-vue/dist/bootstrap-vue.css'
|
|||
|
||||
import { Button, Select, Tag, Option, Table, FormItem, Card,
|
||||
Form, Tabs, TabPane, Switch, Input, Loading, TimeSelect,
|
||||
TableColumn, ColorPicker, Pagination } from 'element-ui'
|
||||
TableColumn, ColorPicker, Pagination, Popover } from 'element-ui'
|
||||
import ElementLocale from 'element-ui/lib/locale'
|
||||
import MagicGrid from 'vue-magic-grid'
|
||||
|
||||
|
@ -49,6 +51,7 @@ import itLocale from '@/locale/it'
|
|||
import enLocale from '@/locale/en'
|
||||
|
||||
Vue.use(Button)
|
||||
Vue.use(Popover)
|
||||
Vue.use(Card)
|
||||
Vue.use(Select)
|
||||
Vue.use(Tag)
|
||||
|
|
|
@ -8,6 +8,7 @@ import Login from './components/Login'
|
|||
import Register from './components/Register'
|
||||
import Export from './components/Export'
|
||||
import Admin from './components/Admin'
|
||||
import About from './components/About'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
|
@ -50,6 +51,10 @@ export default new Router({
|
|||
{
|
||||
path: '/admin/oauth',
|
||||
components: { modal: Admin }
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
components: { modal: About }
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
|
@ -17,7 +17,8 @@ export default new Vuex.Store({
|
|||
token: state => state.token,
|
||||
filteredEvents: state => {
|
||||
const events = state.events.map(e => {
|
||||
const past = (moment().diff(e.start_datetime, 'minutes') > 0)
|
||||
const end_datetime = e.end_datetime || moment(e.start_datetime).add('3', 'hour')
|
||||
const past = (moment().diff(end_datetime, 'minutes') > 0)
|
||||
e.past = past
|
||||
return e
|
||||
})
|
||||
|
|
4
locales/en.json
Normal file
4
locales/en.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"registration_email": "Ciao, la tua registrazione sarà confermata nei prossimi giorni. Riceverai una conferma non temere.",
|
||||
"confirm_email": "confirm_email"
|
||||
}
|
4
locales/es.json
Normal file
4
locales/es.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"registration_email": "registration_email",
|
||||
"confirm_email": "confirm_email"
|
||||
}
|
4
locales/it.json
Normal file
4
locales/it.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"registration_email": "Ciao, la tua registrazione sarà confermata nei prossimi giorni. Riceverai una conferma non temere.",
|
||||
"confirm_email": "Ti abbiamo attivato il tuo utente su gancio. Ora puoi aggiungere eventi."
|
||||
}
|
4
locales/zh.json
Normal file
4
locales/zh.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"registration_email": "registration_email",
|
||||
"confirm_email": "confirm_email"
|
||||
}
|
Loading…
Reference in a new issue