fix #27, fix #25, fix #26, fix #20, fix #19

This commit is contained in:
lesion
2019-03-18 01:42:42 +01:00
parent b93cf91dbd
commit 7111b4578b
31 changed files with 270 additions and 70 deletions

View File

@@ -1,3 +1,6 @@
module.exports = {
'extends': 'standard'
'extends': 'standard',
"rules": {
"camelcase": 0
}
}

View File

@@ -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 })
}

View 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>

View File

@@ -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: {

View File

@@ -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) {
}
}
}
}

View File

@@ -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("/")
}
}
}

View File

@@ -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'

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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.`,

View File

@@ -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)

View File

@@ -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 }
}
]
})

View File

@@ -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
})