working on ssr

This commit is contained in:
lesion 2019-04-05 00:10:19 +02:00
parent 88b43f9bb1
commit 35fa25c060
7 changed files with 271 additions and 30 deletions

View file

@ -16,6 +16,7 @@
"@nuxtjs/axios": "^5.3.6",
"axios": "^0.18.0",
"bcrypt": "^3.0.5",
"body-parser": "^1.18.3",
"bootstrap-vue": "^2.0.0-rc.16",
"cors": "^2.8.5",
"cross-env": "^5.2.0",

34
pages/about.vue Normal file
View file

@ -0,0 +1,34 @@
<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 Cos'è gancio?
p.
Uno strumento di condivisione di eventi per comunità radicali.
Dentro gancio puoi trovare e inserire eventi.
Gancio, come tutto <a href='https://cisti.org'>cisti.org</a> è uno strumento
antisessista, antirazzista, antifascista e anticapitalista, riflettici quando
pubblichi un evento.
h5 Ok, ma cosa vuol dire gancio?
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? Per contribuire i sorgenti sono liberi e disponibili
<a href='https://git.lattuga.net/cisti/gancio'>qui</a>. Aiuti e suggerimenti sono sempre benvenuti, puoi scriverci
su underscore chicciola autistici.org
</template>

196
pages/admin.vue Normal file
View file

@ -0,0 +1,196 @@
<template lang="pug">
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')}}
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
el-tab-pane.pt-1
template(slot='label')
v-icon(name='map-marker-alt')
span.ml-1 {{$t('Places')}}
p {{$t('admin_place_explanation')}}
el-form.mb-2(:inline='true' label-width='120px')
el-form-item(:label="$t('Name')")
el-input.mr-1(:placeholder='$t("Name")' v-model='place.name')
el-form-item(:label="$t('Address')")
el-input.mr-1(:placeholder='$t("Address")' v-model='place.address')
el-button(variant='primary' @click='savePlace') {{$t('Save')}}
b-table(selectable :items='places' :fields='placeFields' striped hover
small selectedVariant='success' primary-key='id'
select-mode="single" @row-selected='placeSelected'
:per-page='perPage' :current-page='placePage')
el-pagination(:page-size='perPage' :currentPage.sync='placePage' :total='places.length')
//- EVENTS
el-tab-pane.pt-1
template(slot='label')
v-icon(name='calendar')
span.ml-1 {{$t('Events')}}
p {{$t('event_confirm_explanation')}}
el-table(:data='paginatedEvents' small primary-key='id' v-loading='loading')
el-table-column(:label='$t("Name")')
template(slot-scope='data') {{data.row.title}}
el-table-column(:label='$t("Where")')
template(slot-scope='data') {{data.row.place.name}}
el-table-column(:label='$t("Confirm")')
template(slot-scope='data')
el-button(type='primary' @click='confirm(data.row.id)' size='mini') {{$t('Confirm')}}
el-button(type='success' @click='preview(data.row.id)' size='mini') {{$t('Preview')}}
el-pagination(:page-size='perPage' :currentPage.sync='eventPage' :total='events.length')
//- TAGS
el-tab-pane.pt-1
template(slot='label')
v-icon(name='tag')
span {{$t('Tags')}}
p {{$t('admin_tag_explanation')}}
el-tag(v-if='tag.tag' :color='tag.color || "grey"' size='mini') {{tag.tag}}
el-form(:inline='true' label-width='120px')
el-form-item(:label="$t('Color')")
el-color-picker(v-model='tag.color' @change='updateColor')
el-table(:data='paginatedTags' striped small hover
highlight-current-row @current-change="tagSelected")
el-table-column(label='Tag')
template(slot-scope='data')
el-tag(:color='data.row.color || "grey"' size='mini') {{data.row.tag}}
el-pagination(:page-size='perPage' :currentPage.sync='tagPage' :total='tags.length')
//- SETTINGS
el-tab-pane.pt-1
template(slot='label')
v-icon(name='tools')
span {{$t('Settings')}}
el-form(inline)
span {{$t('admin_mastodon_explanation')}}
el-input(v-model="mastodon_instance")
span(slot='prepend') {{$t('Mastodon instance')}}
el-button(slot='append' @click='associate' variant='success' type='success') {{$t('Associate')}}
</template>
<script>
import { mapState } from 'vuex'
import api from '@/plugins/api'
import { Message } from 'element-ui'
export default {
name: 'Admin',
data () {
return {
perPage: 10,
users: [],
userFields: ['email', 'action'],
placeFields: ['name', 'address'],
placePage: 1,
userPage: 1,
eventPage: 1,
tagPage: 1,
tagFields: ['tag', 'color'],
description: '',
place: {name: '', address: '' },
tag: {name: '', color: ''},
events: [],
loading: false,
mastodon_instance: '',
settings: {},
tab: "0",
}
},
async mounted () {
const code = this.$route.query.code
if (code) {
this.tab = "4"
const instance = await api.setCode({code, is_admin: true})
}
// this.users = await api.getUsers()
// this.events = await api.getUnconfirmedEvents()
// this.settings = await api.getAdminSettings()
this.mastodon_instance = this.settings.mastodon_auth && this.settings.mastodon_auth.instance
},
computed: {
...mapState(['tags', 'places']),
paginatedEvents () {
return this.events.slice((this.eventPage-1) * this.perPage,
this.eventPage * this.perPage)
},
paginatedTags () {
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: {
placeSelected (items) {
if (items.length === 0 ) {
this.place.name = this.place.address = ''
return
}
const item = items[0]
this.place.name = item.name
this.place.address = item.address
this.place.id = item.id
},
tagSelected (tag) {
this.tag = tag
},
async savePlace () {
const place = await api.updatePlace(this.place)
},
async toggle(user) {
user.is_active = !user.is_active
const newuser = await api.updateUser(user)
},
async toggleAdmin(user) {
user.is_admin = !user.is_admin
const newuser = await api.updateUser(user)
},
async updateColor () {
const newTag = await api.updateTag(this.tag)
},
preview (id) {
this.$router.push(`/event/${id}`)
},
async associate () {
if (!this.mastodon_instance) return
const url = await api.getAuthURL({instance: this.mastodon_instance, admin: true})
setTimeout( () => window.location.href=url, 100);
},
async confirm (id) {
try {
this.loading = true
await api.confirmEvent(id)
this.loading = false
Message({
message: this.$t('event_confirmed'),
type: 'success'
})
this.events = this.events.filter(e => e.id !== id)
} catch (e) {
}
}
}
}
</script>

View file

@ -18,8 +18,8 @@
</template>
<script>
import api from '~/plugins/api'
import { mapActions } from 'vuex';
import api from '@/plugins/api'
import { mapActions } from 'vuex'
import { Message } from 'element-ui'
export default {

View file

@ -55,7 +55,7 @@ export default {
checkRecoverCode: recover_code => post('/user/check_recover_code', { recover_code }),
recoverPassword: (recover_code, password) => post('/user/recover_password', { recover_code, password }),
getAllEvents: (month, year) => get(`/event/${year}/${month}/`),
getAllEvents: (month, year) => get(`/event/${year}/${month}`),
getUnconfirmedEvents: () => get('/event/unconfirmed'),
confirmEvent: id => get(`/event/confirm/${id}`),

View file

@ -1,21 +1,21 @@
const jwt = require('jsonwebtoken')
const Mastodon = require('mastodon-api')
const User = require('../models/user')
const { Event, Tag, Place } = require('../models/event')
const settingsController = require('./settings')
const eventController = require('./event')
const config = require('../config')
const mail = require('../mail')
const { Op } = require('sequelize')
const fs = require('fs')
const path = require('path')
const crypto = require('crypto')
const jwt = require('jsonwebtoken')
const Mastodon = require('mastodon-api')
const { Op } = require('sequelize')
const User = require('../models/user')
const config = require('../config')
const mail = require('../mail')
const { Event, Tag, Place } = require('../models/event')
const settingsController = require('./settings')
const eventController = require('./event')
const userController = {
async login(req, res) {
// find the user
const user = await User.findOne({ where: { email: { [Op.eq]: req.body.email } } })
const user = await User.findOne({ where: { email: { [Op.eq]: req.body && req.body.email } } })
if (!user) {
res.status(404).json({ success: false, message: 'AUTH_FAIL' })
} else if (user) {
@ -28,7 +28,7 @@ const userController = {
// if user is found and password is right
// create a token
const payload = { email: user.email }
var token = jwt.sign(payload, config.secret)
const token = jwt.sign(payload, config.secret)
res.json({
success: true,
message: 'Enjoy your token!',
@ -257,6 +257,7 @@ const userController = {
},
async register(req, res) {
console.error('register !!', req)
const n_users = await User.count()
try {
if (n_users === 0) {

View file

@ -1,8 +1,13 @@
const express = require('express')
const consola = require('consola')
const bodyParser = require('body-parser')
const { Nuxt, Builder } = require('nuxt')
const app = express()
const cors = require('cors')
const corsConfig = {
allowedHeaders: ['Authorization'],
exposeHeaders: ['Authorization']
}
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
@ -23,7 +28,11 @@ async function start() {
}
// Give nuxt middleware to express
app.use(cors())
app.use(cors(corsConfig))
// app.use(morgan('dev'))
// app.set('views', path.join)
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(nuxt.render)
// Listen the server