@@ -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
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user