Encore des commits degeu
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
90de5a105b
commit
63b63d9ee2
5416
js/package-lock.json
generated
5416
js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,7 @@
|
|||||||
"test:e2e": "vue-cli-service test:e2e"
|
"test:e2e": "vue-cli-service test:e2e"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"material-design-icons-iconfont": "^3.0.3",
|
"material-design-icons": "^3.0.1",
|
||||||
"moment": "^2.22.1",
|
"moment": "^2.22.1",
|
||||||
"ngeohash": "^0.6.0",
|
"ngeohash": "^0.6.0",
|
||||||
"register-service-worker": "^1.0.0",
|
"register-service-worker": "^1.0.0",
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
<title>eventos</title>
|
<title>eventos</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<v-avatar size="125px">
|
<v-avatar size="125px">
|
||||||
<img v-if="!account.avatar_url"
|
<img v-if="!account.avatar_url"
|
||||||
class="img-circle elevation-7 mb-1"
|
class="img-circle elevation-7 mb-1"
|
||||||
src="http://lorempixel.com/125/125/"
|
src="https://picsum.photos/125/125/"
|
||||||
>
|
>
|
||||||
<img v-else
|
<img v-else
|
||||||
class="img-circle elevation-7 mb-1"
|
class="img-circle elevation-7 mb-1"
|
||||||
@ -84,7 +84,7 @@
|
|||||||
<v-card-media
|
<v-card-media
|
||||||
class="black--text"
|
class="black--text"
|
||||||
height="200px"
|
height="200px"
|
||||||
src="http://lorempixel.com/400/200/"
|
src="https://picsum.photos/400/200/"
|
||||||
>
|
>
|
||||||
<v-container fill-height fluid>
|
<v-container fill-height fluid>
|
||||||
<v-layout fill-height>
|
<v-layout fill-height>
|
||||||
@ -125,7 +125,7 @@
|
|||||||
<v-card-media
|
<v-card-media
|
||||||
class="black--text"
|
class="black--text"
|
||||||
height="200px"
|
height="200px"
|
||||||
src="http://lorempixel.com/400/200/"
|
src="https://picsum.photos/400/200/"
|
||||||
>
|
>
|
||||||
<v-container fill-height fluid>
|
<v-container fill-height fluid>
|
||||||
<v-layout fill-height>
|
<v-layout fill-height>
|
||||||
|
@ -28,54 +28,63 @@
|
|||||||
</v-list>
|
</v-list>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
|
<v-container grid-list-md text-xs-center>
|
||||||
|
<v-card-media
|
||||||
|
src="https://picsum.photos/600/400/"
|
||||||
|
height="200px"
|
||||||
|
>
|
||||||
|
|
||||||
|
</v-card-media>
|
||||||
|
<v-layout row wrap>
|
||||||
|
<v-flex xs6>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<div class="text-xs-center">
|
<span class="subheading grey--text">{{ event.begins_on | formatDay }}</span>
|
||||||
<v-card-title class="pl-5 pt-5">
|
<h1 class="display-2">{{ event.title }}</h1>
|
||||||
<div class="display-1 pl-5 pt-5">{{ event.title }}</div>
|
<div>
|
||||||
</v-card-title>
|
<router-link :to="{name: 'Account', params: { name: event.organizer.username } }">
|
||||||
|
<v-avatar size="25px">
|
||||||
|
<img class="img-circle elevation-7 mb-1"
|
||||||
|
:src="event.organizer.avatar"
|
||||||
|
>
|
||||||
|
</v-avatar>
|
||||||
|
</router-link>
|
||||||
|
<span v-if="event.organizer">Organisé par {{ event.organizer.display_name }}</span>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<vue-markdown :source="event.description" />
|
||||||
|
</p>
|
||||||
<!--<p><router-link :to="{ name: 'Account', params: {id: event.organizer.id} }"><span class="grey--text">{{ event.organizer.username }}</span></router-link> organises {{ event.title }} <span v-if="event.address.addressLocality">in {{ event.address.addressLocality }}</span> on the {{ event.startDate | formatDate }}.</p>
|
<!--<p><router-link :to="{ name: 'Account', params: {id: event.organizer.id} }"><span class="grey--text">{{ event.organizer.username }}</span></router-link> organises {{ event.title }} <span v-if="event.address.addressLocality">in {{ event.address.addressLocality }}</span> on the {{ event.startDate | formatDate }}.</p>
|
||||||
<v-card-text v-if="event.description"><vue-markdown :source="event.description"></vue-markdown></v-card-text>-->
|
<v-card-text v-if="event.description"><vue-markdown :source="event.description"></vue-markdown></v-card-text>-->
|
||||||
</div>
|
</v-flex>
|
||||||
|
<v-flex xs6>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-btn color="success" v-if="!event.participants.map(participant => participant.id).includes($store.state.user.actor.id)" @click="joinEvent" class="btn btn-primary"><v-icon>check</v-icon> Join</v-btn>
|
||||||
|
<v-btn v-if="event.participants.map(participant => participant.id).includes($store.state.user.actor.id)" @click="leaveEvent" class="btn btn-primary">Leave</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
<v-container fluid grid-list-md>
|
<v-container fluid grid-list-md>
|
||||||
<v-subheader>Membres</v-subheader>
|
<v-subheader>Membres</v-subheader>
|
||||||
<v-layout row>
|
<v-layout row>
|
||||||
<v-flex xs2>
|
<v-flex xs2 v-for="actor in event.participants" :key="actor.uuid">
|
||||||
<router-link :to="{name: 'Account', params: {'id': event.organizer.id}}">
|
<router-link :to="{name: 'Account', params: { name: actor.username }}">
|
||||||
<v-avatar size="75px">
|
<v-avatar size="75px">
|
||||||
<img v-if="!event.organizer.avatar_url"
|
<img v-if="!actor.avatar"
|
||||||
class="img-circle elevation-7 mb-1"
|
class="img-circle elevation-7 mb-1"
|
||||||
src="http://lorempixel.com/125/125/"
|
src="https://picsum.photos/125/125/"
|
||||||
>
|
>
|
||||||
<img v-else
|
<img v-else
|
||||||
class="img-circle elevation-7 mb-1"
|
class="img-circle elevation-7 mb-1"
|
||||||
:src="event.organizer.avatar_url"
|
:src="actor.avatar"
|
||||||
>
|
|
||||||
</v-avatar>
|
|
||||||
</router-link>
|
|
||||||
Organisateur <span>{{ event.organizer.username }}</span>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs2 v-for="actor in event.participants" :key="actor.id">
|
|
||||||
<router-link :to="{name: 'Account', params: {'id': actor.id}}">
|
|
||||||
<v-avatar size="75px">
|
|
||||||
<img v-if="!account.avatar_url"
|
|
||||||
class="img-circle elevation-7 mb-1"
|
|
||||||
src="http://lorempixel.com/125/125/"
|
|
||||||
>
|
|
||||||
<img v-else
|
|
||||||
class="img-circle elevation-7 mb-1"
|
|
||||||
:src="account.avatar_url"
|
|
||||||
>
|
>
|
||||||
</v-avatar>
|
</v-avatar>
|
||||||
</router-link>
|
</router-link>
|
||||||
<span>{{ actor.username }}</span>
|
<span>{{ actor.username }}</span>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
|
<span v-if="event.participants.length === 0">No participants yet.</span>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</v-container>
|
</v-container>
|
||||||
<v-card-actions>
|
|
||||||
<button v-if="!event.participants.map(participant => participant.id).includes($store.state.user.actor.id)" @click="joinEvent" class="btn btn-primary">Join</button>
|
|
||||||
<button v-if="event.participants.map(participant => participant.id).includes($store.state.user.actor.id)" @click="leaveEvent" class="btn btn-primary">Leave</button>
|
|
||||||
<button @click="deleteEvent" class="btn btn-danger">Delete</button>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
@ -97,9 +106,10 @@
|
|||||||
loading: true,
|
loading: true,
|
||||||
error: false,
|
error: false,
|
||||||
event: {
|
event: {
|
||||||
name: this.name,
|
name: '',
|
||||||
slug: this.slug,
|
slug: '',
|
||||||
title: '',
|
title: '',
|
||||||
|
uuid: this.uuid,
|
||||||
description: '',
|
description: '',
|
||||||
organizer: {
|
organizer: {
|
||||||
id: null,
|
id: null,
|
||||||
@ -112,11 +122,11 @@
|
|||||||
methods: {
|
methods: {
|
||||||
deleteEvent() {
|
deleteEvent() {
|
||||||
const router = this.$router;
|
const router = this.$router;
|
||||||
eventFetch(`/events/${this.name}/${this.slug}`, this.$store, { method: 'DELETE' })
|
eventFetch(`/events/${this.uuid}`, this.$store, { method: 'DELETE' })
|
||||||
.then(() => router.push({'name': 'EventList'}));
|
.then(() => router.push({'name': 'EventList'}));
|
||||||
},
|
},
|
||||||
fetchData() {
|
fetchData() {
|
||||||
eventFetch(`/events/${this.name}/${this.slug}`, this.$store)
|
eventFetch(`/events/${this.uuid}`, this.$store)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
@ -130,21 +140,21 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
joinEvent() {
|
joinEvent() {
|
||||||
eventFetch(`/events/${this.name}/${this.slug}/join`, this.$store)
|
eventFetch(`/events/${this.uuid}/join`, this.$store)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
leaveEvent() {
|
leaveEvent() {
|
||||||
eventFetch(`/events/${this.name}/${this.slug}/leave`, this.$store)
|
eventFetch(`/events/${this.uuid}/leave`, this.$store)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
downloadIcsEvent() {
|
downloadIcsEvent() {
|
||||||
eventFetch(`/events/${this.name}/${this.slug}/ics`, this.$store, {responseType: 'arraybuffer'})
|
eventFetch(`/events/${this.uuid}/ics`, this.$store, {responseType: 'arraybuffer'})
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const blob = new Blob([response],{type: 'text/calendar'});
|
const blob = new Blob([response],{type: 'text/calendar'});
|
||||||
@ -158,14 +168,10 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
name: {
|
uuid: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
slug: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.fetchData();
|
this.fetchData();
|
||||||
|
@ -1,35 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container>
|
<v-layout>
|
||||||
|
<v-flex xs12 sm8 offset-sm2>
|
||||||
|
<v-card>
|
||||||
<h1>{{ $t("event.list.title") }}</h1>
|
<h1>{{ $t("event.list.title") }}</h1>
|
||||||
|
|
||||||
<v-progress-circular v-if="loading" indeterminate color="primary"></v-progress-circular>
|
<v-progress-circular v-if="loading" indeterminate color="primary"></v-progress-circular>
|
||||||
<v-chip close v-model="locationChip" label color="pink" text-color="white" v-if="$router.currentRoute.params.location">
|
<v-chip close v-model="locationChip" label color="pink" text-color="white" v-if="$router.currentRoute.params.location">
|
||||||
<v-icon left>location_city</v-icon>{{ locationText }}
|
<v-icon left>location_city</v-icon>{{ locationText }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
<v-layout row wrap justify-space-around>
|
<v-container grid-list-sm fluid>
|
||||||
<v-flex xs12 md3 v-for="event in events" :key="event.id">
|
<v-layout row wrap>
|
||||||
|
<v-flex xs4 v-for="event in events" :key="event.id">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-media v-if="event.image"
|
<v-card-media v-if="!event.image"
|
||||||
class="white--text"
|
class="white--text"
|
||||||
height="200px"
|
height="200px"
|
||||||
src="http://lorempixel.com/400/200/"
|
src="https://picsum.photos/g/400/200/"
|
||||||
>
|
>
|
||||||
<v-container fill-height fluid>
|
<v-container fill-height fluid>
|
||||||
<v-layout fill-height>
|
<v-layout fill-height>
|
||||||
<v-flex xs12 align-end flexbox>
|
<v-flex xs12 align-end flexbox>
|
||||||
<span class="headline">{{ event.title }}</span>
|
<span class="headline black--text">{{ event.title }}</span>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</v-container>
|
</v-container>
|
||||||
</v-card-media>
|
</v-card-media>
|
||||||
<v-card-title v-else primary-title>
|
<v-card-title primary-title>
|
||||||
<div class="headline">{{ event.title }}</div>
|
<div>
|
||||||
</v-card-title>
|
<span class="grey--text">{{ event.begins_on | formatDate }}</span><br>
|
||||||
<v-container>
|
<router-link :to="{name: 'Account', params: { name: event.organizer.username } }">
|
||||||
<!--<span class="grey--text">{{ event.startDate | formatDate }} à <router-link :to="{name: 'EventList', params: {location: geocode(event.address.geo.latitude, event.address.geo.longitude, 10) }}">{{ event.address.addressLocality }}</router-link></span><br>-->
|
<v-avatar size="25px">
|
||||||
<p><vue-markdown>{{ event.description }}</vue-markdown></p>
|
<img class="img-circle elevation-7 mb-1"
|
||||||
<p v-if="event.organizer">Organisé par <router-link :to="{name: 'Account', params: {'name': event.organizer.username}}">{{ event.organizer.username }}</router-link></p>
|
:src="event.organizer.avatar"
|
||||||
</v-container>
|
>
|
||||||
|
</v-avatar>
|
||||||
|
</router-link>
|
||||||
|
<span v-if="event.organizer">Organisé par <router-link :to="{name: 'Account', params: {'name': event.organizer.username}}">{{ event.organizer.username }}</router-link></span>
|
||||||
|
</div>
|
||||||
|
</v-card-title>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-btn flat color="orange" @click="downloadIcsEvent(event)">Share</v-btn>
|
<v-btn flat color="orange" @click="downloadIcsEvent(event)">Share</v-btn>
|
||||||
<v-btn flat color="orange" @click="viewEvent(event)">Explore</v-btn>
|
<v-btn flat color="orange" @click="viewEvent(event)">Explore</v-btn>
|
||||||
@ -38,8 +46,11 @@
|
|||||||
</v-card>
|
</v-card>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
<router-link :to="{ name: 'CreateEvent' }" class="btn btn-default">Create</router-link>
|
<router-link :to="{ name: 'CreateEvent' }" class="btn btn-default">Create</router-link>
|
||||||
</v-container>
|
</v-card>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -96,18 +107,19 @@
|
|||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.events = response.data;
|
this.events = response.data;
|
||||||
|
console.log(this.events);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteEvent(event) {
|
deleteEvent(event) {
|
||||||
const router = this.$router;
|
const router = this.$router;
|
||||||
eventFetch(`/events/${event.organizer.username}/${event.slug}`, this.$store, {'method': 'DELETE'})
|
eventFetch(`/events/${event.uuid}`, this.$store, {'method': 'DELETE'})
|
||||||
.then(() => router.push('/events'));
|
.then(() => router.push('/events'));
|
||||||
},
|
},
|
||||||
viewEvent(event) {
|
viewEvent(event) {
|
||||||
this.$router.push({ name: 'Event', params: { name: event.organizer.username, slug: event.slug } })
|
this.$router.push({ name: 'Event', params: { uuid: event.uuid } })
|
||||||
},
|
},
|
||||||
downloadIcsEvent(event) {
|
downloadIcsEvent(event) {
|
||||||
eventFetch(`/events/${event.organizer.username}/${event.slug}/export`, this.$store, {responseType: 'arraybuffer'})
|
eventFetch(`/events/${event.uuid}/ics`, this.$store, {responseType: 'arraybuffer'})
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const blob = new Blob([response],{type: 'text/calendar'});
|
const blob = new Blob([response],{type: 'text/calendar'});
|
||||||
|
@ -4,37 +4,57 @@
|
|||||||
<v-flex xs12 sm6 offset-sm3>
|
<v-flex xs12 sm6 offset-sm3>
|
||||||
<v-progress-circular v-if="loading" indeterminate color="primary"></v-progress-circular>
|
<v-progress-circular v-if="loading" indeterminate color="primary"></v-progress-circular>
|
||||||
<v-card v-if="!loading">
|
<v-card v-if="!loading">
|
||||||
<v-layout column class="media">
|
<v-card-media :src="group.banner" height="400px">
|
||||||
<v-card-title>
|
<v-layout column class="media">
|
||||||
<v-btn icon @click="$router.go(-1)">
|
<v-card-title>
|
||||||
<v-icon>chevron_left</v-icon>
|
<v-btn icon @click="$router.go(-1)">
|
||||||
</v-btn>
|
<v-icon>chevron_left</v-icon>
|
||||||
<v-spacer></v-spacer>
|
</v-btn>
|
||||||
<v-btn icon class="mr-3" v-if="$store.state.user">
|
<v-spacer></v-spacer>
|
||||||
<v-icon>edit</v-icon>
|
<!--<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.user.actor.id === actor.id">-->
|
||||||
</v-btn>
|
<!--<v-icon>edit</v-icon>-->
|
||||||
<v-btn icon>
|
<!--</v-btn>-->
|
||||||
<v-icon>more_vert</v-icon>
|
<v-btn icon>
|
||||||
</v-btn>
|
<v-icon>more_vert</v-icon>
|
||||||
</v-card-title>
|
</v-btn>
|
||||||
<v-spacer></v-spacer>
|
|
||||||
<div class="text-xs-center">
|
|
||||||
<v-avatar size="125px">
|
|
||||||
<img v-if="!group.avatar_url"
|
|
||||||
class="img-circle elevation-7 mb-1"
|
|
||||||
src="http://lorempixel.com/125/125/"
|
|
||||||
>
|
|
||||||
<img v-else
|
|
||||||
class="img-circle elevation-7 mb-1"
|
|
||||||
:src="group.avatar_url"
|
|
||||||
>
|
|
||||||
</v-avatar>
|
|
||||||
<v-card-title class="pl-5 pt-5">
|
|
||||||
<div class="display-1 pl-5 pt-5">{{ group.title }}<span v-if="group.server">@{{ group.server.address }}</span></div>
|
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-card-text v-html="group.description"></v-card-text>
|
<v-spacer></v-spacer>
|
||||||
</div>
|
<div class="text-xs-center">
|
||||||
</v-layout>
|
<v-avatar size="125px">
|
||||||
|
<img v-if="!group.avatar"
|
||||||
|
class="img-circle elevation-7 mb-1"
|
||||||
|
src="https://picsum.photos/125/125/"
|
||||||
|
>
|
||||||
|
<img v-else
|
||||||
|
class="img-circle elevation-7 mb-1"
|
||||||
|
:src="group.avatar"
|
||||||
|
>
|
||||||
|
</v-avatar>
|
||||||
|
</div>
|
||||||
|
<v-container fluid grid-list-lg>
|
||||||
|
<v-layout row>
|
||||||
|
<v-flex xs7>
|
||||||
|
<div class="headline">{{ group.display_name }}</div>
|
||||||
|
<div>
|
||||||
|
<span class="subheading">
|
||||||
|
~{{ group.username }}
|
||||||
|
<span v-if="group.domain">
|
||||||
|
@{{ group.domain }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<v-chip color="indigo" text-color="white">
|
||||||
|
<v-avatar>
|
||||||
|
<v-icon>group</v-icon>
|
||||||
|
</v-avatar>
|
||||||
|
Group
|
||||||
|
</v-chip>
|
||||||
|
</div>
|
||||||
|
<v-card-text v-if="group.description" v-html="group.description"></v-card-text>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
|
</v-layout>
|
||||||
|
</v-card-media>
|
||||||
<v-list three-line>
|
<v-list three-line>
|
||||||
<v-list-tile>
|
<v-list-tile>
|
||||||
<v-list-tile-action>
|
<v-list-tile-action>
|
||||||
@ -59,48 +79,90 @@
|
|||||||
</v-list-tile-content>
|
</v-list-tile-content>
|
||||||
</v-list-tile>
|
</v-list-tile>
|
||||||
<v-divider inset></v-divider>
|
<v-divider inset></v-divider>
|
||||||
<v-list-tile v-if="group.address">
|
<v-list-tile>
|
||||||
<v-list-tile-action>
|
<v-list-tile-action>
|
||||||
<v-icon color="indigo">location_on</v-icon>
|
<v-icon color="indigo">location_on</v-icon>
|
||||||
</v-list-tile-action>
|
</v-list-tile-action>
|
||||||
<v-list-tile-content>
|
<v-list-tile-content>
|
||||||
<v-list-tile-title>{{ group.address.streetAddress }}</v-list-tile-title>
|
<v-list-tile-title>1400 Main Street</v-list-tile-title>
|
||||||
<v-list-tile-sub-title>{{ group.address.postalCode }} {{ group.address.locality }}</v-list-tile-sub-title>
|
<v-list-tile-sub-title>Orlando, FL 79938</v-list-tile-sub-title>
|
||||||
</v-list-tile-content>
|
</v-list-tile-content>
|
||||||
</v-list-tile>
|
</v-list-tile>
|
||||||
</v-list>
|
</v-list>
|
||||||
<v-container fluid grid-list-md v-if="group.members.length > 0">
|
<v-container fluid grid-list-md v-if="group.members.length > 0">
|
||||||
<v-subheader>Membres</v-subheader>
|
<v-subheader>Membres</v-subheader>
|
||||||
<v-layout row>
|
<v-layout row>
|
||||||
<v-flex xs2 v-for="member in group.members" :key="member.id">
|
<v-flex xs2 v-for="member in group.members" :key="member.actor.username">
|
||||||
<router-link :to="{name: 'Account', params: {'id': member.actor.id}}">
|
<router-link :to="{name: 'Account', params: { name: member.actor.username } }">
|
||||||
<v-badge overlap>
|
<v-badge overlap>
|
||||||
<span slot="badge" v-if="member.role == 3"><v-icon>stars</v-icon></span>
|
<span slot="badge" v-if="member.role === 1"><v-icon>star_half</v-icon></span>
|
||||||
|
<span slot="badge" v-if="member.role === 2"><v-icon>star</v-icon></span>
|
||||||
<v-avatar size="75px">
|
<v-avatar size="75px">
|
||||||
<img v-if="!member.account.avatar_url"
|
<img v-if="!member.actor.avatar"
|
||||||
class="img-circle elevation-7 mb-1"
|
class="img-circle elevation-7 mb-1"
|
||||||
src="http://lorempixel.com/125/125/"
|
src="https://picsum.photos/125/125/"
|
||||||
>
|
>
|
||||||
<img v-else
|
<img v-else
|
||||||
class="img-circle elevation-7 mb-1"
|
class="img-circle elevation-7 mb-1"
|
||||||
:src="member.account.avatar_url"
|
:src="member.actor.avatar"
|
||||||
>
|
>
|
||||||
</v-avatar>
|
</v-avatar>
|
||||||
</v-badge>
|
</v-badge>
|
||||||
</router-link>
|
</router-link>
|
||||||
<span>{{ groupAccount.actor.username }}</span>
|
<span>{{ member.actor.username }}</span>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</v-container>
|
</v-container>
|
||||||
<v-container fluid grid-list-md v-if="group.events.length > 0">
|
<v-container fluid grid-list-md v-if="group.participatingEvents && group.participatingEvents.length > 0">
|
||||||
<v-subheader>Participated at</v-subheader>
|
<v-subheader>Participated at</v-subheader>
|
||||||
<v-layout row wrap>
|
<v-layout row wrap>
|
||||||
<v-flex v-for="event in group.events" :key="event.id">
|
<v-flex v-for="event in group.participatingEvents" :key="event.id">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-media
|
<v-card-media
|
||||||
class="black--text"
|
class="black--text"
|
||||||
height="200px"
|
height="200px"
|
||||||
src="http://lorempixel.com/400/200/"
|
src="https://picsum.photos/400/200/"
|
||||||
|
>
|
||||||
|
<v-container fill-height fluid>
|
||||||
|
<v-layout fill-height>
|
||||||
|
<v-flex xs12 align-end flexbox>
|
||||||
|
<span class="headline">{{ event.title }}</span>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
|
</v-card-media>
|
||||||
|
<v-card-title>
|
||||||
|
<div>
|
||||||
|
<span class="grey--text">{{ event.startDate | formatDate }} à {{ event.location }}</span><br>
|
||||||
|
<p>{{ event.description }}</p>
|
||||||
|
<p v-if="event.organizer">Organisé par <router-link :to="{name: 'Account', params: {'id': event.organizer.id}}">{{ event.organizer.username }}</router-link></p>
|
||||||
|
</div>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn icon>
|
||||||
|
<v-icon>favorite</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
<v-btn icon>
|
||||||
|
<v-icon>bookmark</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
<v-btn icon>
|
||||||
|
<v-icon>share</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
|
<v-container fluid grid-list-md v-if="group.organizingEvents && group.organizingEvents.length > 0">
|
||||||
|
<v-subheader>Organized events</v-subheader>
|
||||||
|
<v-layout row wrap>
|
||||||
|
<v-flex v-for="event in group.organizingEvents" :key="event.id">
|
||||||
|
<v-card>
|
||||||
|
<v-card-media
|
||||||
|
class="black--text"
|
||||||
|
height="200px"
|
||||||
|
src="https://picsum.photos/400/200/"
|
||||||
>
|
>
|
||||||
<v-container fill-height fluid>
|
<v-container fill-height fluid>
|
||||||
<v-layout fill-height>
|
<v-layout fill-height>
|
||||||
@ -140,40 +202,39 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import eventFetch from '@/api/eventFetch';
|
||||||
|
|
||||||
import eventFetch from '@/api/eventFetch';
|
export default {
|
||||||
|
name: 'Group',
|
||||||
export default {
|
data() {
|
||||||
name: 'Group',
|
return {
|
||||||
props: ['id'],
|
group: null,
|
||||||
data() {
|
loading: true,
|
||||||
return {
|
}
|
||||||
group: {
|
|
||||||
id: this.id,
|
|
||||||
title: '',
|
|
||||||
description: '',
|
|
||||||
},
|
},
|
||||||
loading: true,
|
props: {
|
||||||
}
|
name: {
|
||||||
},
|
type: String,
|
||||||
methods: {
|
required: true,
|
||||||
fetchData() {
|
}
|
||||||
eventFetch(`/groups/${this.id}`, this.$store)
|
},
|
||||||
.then(response => response.json())
|
created() {
|
||||||
.then((data) => {
|
this.fetchData();
|
||||||
this.loading = false;
|
},
|
||||||
this.group = data.data;
|
watch: {
|
||||||
});
|
// call again the method if the route changes
|
||||||
},
|
'$route': 'fetchData'
|
||||||
deleteGroup() {
|
},
|
||||||
const router = this.$router;
|
methods: {
|
||||||
eventFetch(`/groups/${this.id}`, this.$store, { method: 'DELETE' })
|
fetchData() {
|
||||||
.then(response => response.json())
|
eventFetch(`/actors/${this.name}`, this.$store)
|
||||||
.then(() => router.push('/groups'));
|
.then(response => response.json())
|
||||||
},
|
.then((response) => {
|
||||||
},
|
this.group = response.data;
|
||||||
created() {
|
this.loading = false;
|
||||||
this.fetchData();
|
console.log(this.group);
|
||||||
},
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<v-card-media
|
<v-card-media
|
||||||
class="black--text"
|
class="black--text"
|
||||||
height="200px"
|
height="200px"
|
||||||
src="http://lorempixel.com/400/200/"
|
src="https://picsum.photos/400/200/"
|
||||||
>
|
>
|
||||||
<v-container fill-height fluid>
|
<v-container fill-height fluid>
|
||||||
<v-layout fill-height>
|
<v-layout fill-height>
|
||||||
@ -26,9 +26,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-btn flat color="green" @click="joinGroup(group.id)"><v-icon v-if="group.locked">lock</v-icon>Join</v-btn>
|
<v-btn flat color="green" @click="joinGroup(group)"><v-icon v-if="group.locked">lock</v-icon>Join</v-btn>
|
||||||
<v-btn flat color="orange" @click="viewActor(group)">Explore</v-btn>
|
<v-btn flat color="orange" @click="viewActor(group)">Explore</v-btn>
|
||||||
<v-btn flat color="red" @click="deleteEvent(group.id)">Delete</v-btn>
|
<v-btn flat color="red" @click="deleteGroup(group)">Delete</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
@ -64,20 +64,20 @@
|
|||||||
this.groups = data.data;
|
this.groups = data.data;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteEvent(id) {
|
deleteGroup(group) {
|
||||||
const router = this.$router;
|
const router = this.$router;
|
||||||
eventFetch('/groups/' + id, this.$store, {'method': 'DELETE'})
|
eventFetch(`/groups/${this.username_with_domain(group)}`, this.$store, {'method': 'DELETE'})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(() => router.push('/groups'));
|
.then(() => router.push('/groups'));
|
||||||
},
|
},
|
||||||
viewActor(actor) {
|
viewActor(actor) {
|
||||||
this.$router.push({ name: 'Account', params: { name: this.username_with_domain(actor) } })
|
this.$router.push({ name: 'Group', params: { name: this.username_with_domain(actor) } })
|
||||||
},
|
},
|
||||||
joinGroup(id) {
|
joinGroup(group) {
|
||||||
const router = this.$router;
|
const router = this.$router;
|
||||||
eventFetch('/groups/' + id + '/join', this.$store)
|
eventFetch(`/groups/${this.username_with_domain(group)}/join`, this.$store, { method: 'POST' })
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(() => router.push('/group/' + id))
|
.then(() => router.push({ name: 'Group', params: { name: this.username_with_domain(group) } }));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,59 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container>
|
<v-container>
|
||||||
<h1 class="welcome" v-if="$store.state.user">{{ $t("home.welcome", { 'username': this.displayed_name }) }}</h1>
|
<v-jumbotron
|
||||||
<h1 class="welcome" v-else>{{ $t("home.welcome_off", { 'username': $store.state.user.username}) }}</h1>
|
:gradient="gradient"
|
||||||
<router-link :to="{ name: 'EventList' }">{{ $t('home.events') }}</router-link>
|
src="https://picsum.photos/1200/900"
|
||||||
<router-link v-if="$store.state.user === false" :to="{ name: 'Login' }">{{ $t('home.login') }}</router-link>
|
dark
|
||||||
<router-link v-if="$store.state.user === false" :to="{ name: 'Register' }">{{ $t('home.register') }}</router-link>
|
v-if="$store.state.user === false"
|
||||||
|
>
|
||||||
|
<v-container fill-height>
|
||||||
|
<v-layout align-center>
|
||||||
|
<v-flex text-xs-center>
|
||||||
|
<h1 class="display-3">Find events you like</h1>
|
||||||
|
<h2>Share it with Eventos</h2>
|
||||||
|
<v-btn>{{ $t("home.register") }}</v-btn>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
|
</v-jumbotron>
|
||||||
|
<v-layout>
|
||||||
|
<v-flex xs12 sm8 offset-sm2>
|
||||||
|
<v-card>
|
||||||
|
<v-layout row wrap>
|
||||||
|
<v-flex xs4 v-for="event in events" :key="event.uuid">
|
||||||
|
<v-card :to="{ name: 'Event', params:{ uuid: event.uuid } }">
|
||||||
|
<v-card-media v-if="!event.image"
|
||||||
|
class="white--text"
|
||||||
|
height="200px"
|
||||||
|
src="https://picsum.photos/g/400/200/"
|
||||||
|
>
|
||||||
|
<v-container fill-height fluid>
|
||||||
|
<v-layout fill-height>
|
||||||
|
<v-flex xs12 align-end flexbox>
|
||||||
|
<span class="headline black--text">{{ event.title }}</span>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
|
</v-card-media>
|
||||||
|
<v-card-title primary-title>
|
||||||
|
<div>
|
||||||
|
<span class="grey--text">{{ event.begins_on | formatDate }}</span><br>
|
||||||
|
<router-link :to="{name: 'Account', params: { name: event.organizer.username } }">
|
||||||
|
<v-avatar size="25px">
|
||||||
|
<img class="img-circle elevation-7 mb-1"
|
||||||
|
:src="event.organizer.avatar"
|
||||||
|
>
|
||||||
|
</v-avatar>
|
||||||
|
</router-link>
|
||||||
|
<span v-if="event.organizer">Organisé par {{ event.organizer.display_name }}</span>
|
||||||
|
</div>
|
||||||
|
</v-card-title>
|
||||||
|
</v-card>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</v-card>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
<v-layout row>
|
<v-layout row>
|
||||||
<v-flex xs6>
|
<v-flex xs6>
|
||||||
<v-btn large @click="geoLocalize"><v-icon>my_location</v-icon>Me géolocaliser</v-btn>
|
<v-btn large @click="geoLocalize"><v-icon>my_location</v-icon>Me géolocaliser</v-btn>
|
||||||
@ -36,6 +85,7 @@ export default {
|
|||||||
name: 'Home',
|
name: 'Home',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
gradient: 'to top right, rgba(63,81,181, .7), rgba(25,32,72, .7)',
|
||||||
user: null,
|
user: null,
|
||||||
searchTerm: null,
|
searchTerm: null,
|
||||||
location_field: {
|
location_field: {
|
||||||
@ -43,10 +93,11 @@ export default {
|
|||||||
search: null,
|
search: null,
|
||||||
},
|
},
|
||||||
locations: [],
|
locations: [],
|
||||||
|
events: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
created() {
|
||||||
// this.fetchLocations();
|
this.fetchData();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
displayed_name: function() {
|
displayed_name: function() {
|
||||||
@ -61,6 +112,14 @@ export default {
|
|||||||
this.locations = response;
|
this.locations = response;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
fetchData() {
|
||||||
|
eventFetch('/events', this.$store)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then((response) => {
|
||||||
|
this.loading = false;
|
||||||
|
this.events = response.data;
|
||||||
|
});
|
||||||
|
},
|
||||||
geoLocalize() {
|
geoLocalize() {
|
||||||
const router = this.$router;
|
const router = this.$router;
|
||||||
if (sessionStorage.getItem('City')) {
|
if (sessionStorage.getItem('City')) {
|
||||||
@ -85,6 +144,9 @@ export default {
|
|||||||
sessionStorage.setItem('City', geohash);
|
sessionStorage.setItem('City', geohash);
|
||||||
this.$router.push({name: 'EventList', params: {location: geohash}});
|
this.$router.push({name: 'EventList', params: {location: geohash}});
|
||||||
},
|
},
|
||||||
|
viewEvent(event) {
|
||||||
|
this.$router.push({ name: 'Event', params: { uuid: event.uuid } })
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<v-toolbar-title style="width: 300px" class="ml-0 pl-3">
|
<v-toolbar-title style="width: 300px" class="ml-0 pl-3">
|
||||||
<v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
|
<v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
|
||||||
<router-link :to="{ name: 'Home' }">
|
<router-link :to="{ name: 'Home' }">
|
||||||
Libre-Event
|
Eventos
|
||||||
</router-link>
|
</router-link>
|
||||||
</v-toolbar-title>
|
</v-toolbar-title>
|
||||||
<v-select
|
<v-select
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
home: {
|
home: {
|
||||||
welcome: 'Welcome on Libre-Event, {username}',
|
welcome: 'Welcome on Eventos, {username}',
|
||||||
welcome_off: 'Welcome on Libre-Event',
|
welcome_off: 'Welcome on Eventos',
|
||||||
events: 'Events',
|
events: 'Events',
|
||||||
groups: 'Groups',
|
groups: 'Groups',
|
||||||
login: 'Login',
|
login: 'Login',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
home: {
|
home: {
|
||||||
welcome: 'Bienvenue sur Libre-Event, {username}!',
|
welcome: 'Bienvenue sur Eventos, {username}!',
|
||||||
welcome_off: 'Bienvenue sur Libre-Event',
|
welcome_off: 'Bienvenue sur Eventos',
|
||||||
events: 'Événements',
|
events: 'Événements',
|
||||||
groups: 'Groupes',
|
groups: 'Groupes',
|
||||||
login: 'Se connecter',
|
login: 'Se connecter',
|
||||||
|
@ -8,8 +8,8 @@ import Vuetify from 'vuetify';
|
|||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import VuexI18n from 'vuex-i18n';
|
import VuexI18n from 'vuex-i18n';
|
||||||
|
import 'material-design-icons/iconfont/material-icons.css';
|
||||||
import 'vuetify/dist/vuetify.min.css';
|
import 'vuetify/dist/vuetify.min.css';
|
||||||
import 'material-design-icons-iconfont/dist/material-design-icons.css';
|
|
||||||
import App from '@/App';
|
import App from '@/App';
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
import storeData from '@/store/index';
|
import storeData from '@/store/index';
|
||||||
@ -37,6 +37,7 @@ let language = window.navigator.userLanguage || window.navigator.language;
|
|||||||
moment.locale(language);
|
moment.locale(language);
|
||||||
|
|
||||||
Vue.filter('formatDate', value => (value ? moment(String(value)).format('LLLL') : null));
|
Vue.filter('formatDate', value => (value ? moment(String(value)).format('LLLL') : null));
|
||||||
|
Vue.filter('formatDay', value => (value ? moment(String(value)).format('LL') : null));
|
||||||
|
|
||||||
if (!(language in translations)) {
|
if (!(language in translations)) {
|
||||||
[language] = language.split('-', 1);
|
[language] = language.split('-', 1);
|
||||||
|
@ -103,7 +103,7 @@ const router = new Router({
|
|||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/@:name/:slug',
|
path: '/events/:uuid',
|
||||||
name: 'Event',
|
name: 'Event',
|
||||||
component: Event,
|
component: Event,
|
||||||
props: true,
|
props: true,
|
||||||
|
@ -133,6 +133,15 @@ defmodule Eventos.Actors do
|
|||||||
Repo.all(from a in Actor, where: a.type == "Group")
|
Repo.all(from a in Actor, where: a.type == "Group")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_group_by_name(name) do
|
||||||
|
actor = case String.split(name, "@") do
|
||||||
|
[name] ->
|
||||||
|
Repo.get_by(Actor, preferred_username: name, type: :Group)
|
||||||
|
[name, domain] ->
|
||||||
|
Repo.get_by(Actor, preferred_username: name, domain: domain, type: :Group)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Creates a group.
|
Creates a group.
|
||||||
|
|
||||||
@ -176,7 +185,7 @@ defmodule Eventos.Actors do
|
|||||||
|
|
||||||
def insert_or_update_actor(data) do
|
def insert_or_update_actor(data) do
|
||||||
cs = Actor.remote_actor_creation(data)
|
cs = Actor.remote_actor_creation(data)
|
||||||
Repo.insert(cs, on_conflict: [set: [public_key: data.public_key, avatar_url: data.avatar_url, banner: data.banner_url, name: data.name]], conflict_target: [:preferred_username, :domain])
|
Repo.insert(cs, on_conflict: [set: [public_key: data.public_key, avatar_url: data.avatar_url, banner_url: data.banner_url, name: data.name]], conflict_target: [:preferred_username, :domain])
|
||||||
end
|
end
|
||||||
|
|
||||||
# def increase_event_count(%Actor{} = actor) do
|
# def increase_event_count(%Actor{} = actor) do
|
||||||
@ -494,7 +503,8 @@ defmodule Eventos.Actors do
|
|||||||
def create_member(attrs \\ %{}) do
|
def create_member(attrs \\ %{}) do
|
||||||
%Member{}
|
%Member{}
|
||||||
|> Member.changeset(attrs)
|
|> Member.changeset(attrs)
|
||||||
|> Repo.insert()
|
|> Repo.insert!()
|
||||||
|
|> Repo.preload([:actor, :parent])
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
@ -544,6 +554,22 @@ defmodule Eventos.Actors do
|
|||||||
Member.changeset(member, %{})
|
Member.changeset(member, %{})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def groups_for_actor(%Actor{id: id} = _actor) do
|
||||||
|
Repo.all(
|
||||||
|
from m in Member,
|
||||||
|
where: m.actor_id == ^id,
|
||||||
|
preload: [:parent]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def members_for_group(%Actor{type: :Group, id: id} = _group) do
|
||||||
|
Repo.all(
|
||||||
|
from m in Member,
|
||||||
|
where: m.parent_id == ^id,
|
||||||
|
preload: [:parent, :actor]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
alias Eventos.Actors.Bot
|
alias Eventos.Actors.Bot
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@ defmodule Eventos.Actors.Member do
|
|||||||
alias Eventos.Actors.Member
|
alias Eventos.Actors.Member
|
||||||
alias Eventos.Actors.Actor
|
alias Eventos.Actors.Actor
|
||||||
|
|
||||||
|
@primary_key false
|
||||||
schema "members" do
|
schema "members" do
|
||||||
field :approved, :boolean
|
field :approved, :boolean, default: true
|
||||||
field :role, :integer
|
field :role, :integer, default: 0 # 0 : Member, 1 : Moderator, 2 : Admin
|
||||||
belongs_to :parent, Actor
|
belongs_to :parent, Actor
|
||||||
belongs_to :actor, Actor
|
belongs_to :actor, Actor
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ defmodule Eventos.Actors.Member do
|
|||||||
@doc false
|
@doc false
|
||||||
def changeset(%Member{} = member, attrs) do
|
def changeset(%Member{} = member, attrs) do
|
||||||
member
|
member
|
||||||
|> cast(attrs, [:role])
|
|> cast(attrs, [:role, :approved, :parent_id, :actor_id])
|
||||||
|> validate_required([:role])
|
|> validate_required([:parent_id, :actor_id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -26,6 +26,5 @@ defmodule Eventos.Addresses.Address do
|
|||||||
def changeset(%Address{} = address, attrs) do
|
def changeset(%Address{} = address, attrs) do
|
||||||
address
|
address
|
||||||
|> cast(attrs, [:description, :floor, :geom, :addressCountry, :addressLocality, :addressRegion, :postalCode, :streetAddress])
|
|> cast(attrs, [:description, :floor, :geom, :addressCountry, :addressLocality, :addressRegion, :postalCode, :streetAddress])
|
||||||
|> validate_required([:geom])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -51,6 +51,7 @@ defmodule Eventos.Events.Event do
|
|||||||
field :thumbnail, :string
|
field :thumbnail, :string
|
||||||
field :large_image, :string
|
field :large_image, :string
|
||||||
field :publish_at, Timex.Ecto.DateTimeWithTimezone
|
field :publish_at, Timex.Ecto.DateTimeWithTimezone
|
||||||
|
field :uuid, Ecto.UUID, default: Ecto.UUID.generate()
|
||||||
belongs_to :organizer_actor, Actor, [foreign_key: :organizer_actor_id]
|
belongs_to :organizer_actor, Actor, [foreign_key: :organizer_actor_id]
|
||||||
many_to_many :tags, Tag, join_through: "events_tags"
|
many_to_many :tags, Tag, join_through: "events_tags"
|
||||||
belongs_to :category, Category
|
belongs_to :category, Category
|
||||||
@ -64,12 +65,17 @@ defmodule Eventos.Events.Event do
|
|||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
def changeset(%Event{} = event, attrs) do
|
def changeset(%Event{} = event, attrs) do
|
||||||
event
|
changeset = event
|
||||||
|> cast(attrs, [:title, :description, :url, :begins_on, :ends_on, :organizer_actor_id, :category_id, :state, :status, :public, :thumbnail, :large_image, :publish_at])
|
|> cast(attrs, [:title, :description, :url, :begins_on, :ends_on, :organizer_actor_id, :category_id, :state, :status, :public, :thumbnail, :large_image, :publish_at])
|
||||||
|> cast_assoc(:tags)
|
|> cast_assoc(:tags)
|
||||||
|> cast_assoc(:address)
|
|> cast_assoc(:address)
|
||||||
|> validate_required([:title, :description, :begins_on, :ends_on, :organizer_actor_id, :category_id])
|
|> validate_required([:title, :description, :begins_on, :ends_on, :organizer_actor_id, :category_id])
|
||||||
|> TitleSlug.maybe_generate_slug()
|
|> TitleSlug.maybe_generate_slug()
|
||||||
|> TitleSlug.unique_constraint()
|
|> TitleSlug.unique_constraint()
|
||||||
|
|> put_change(:uuid, Ecto.UUID.generate())
|
||||||
|
|
||||||
|
import Logger
|
||||||
|
Logger.debug(inspect changeset)
|
||||||
|
changeset
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -77,6 +77,13 @@ defmodule Eventos.Events do
|
|||||||
Repo.get_by(Event, url: url)
|
Repo.get_by(Event, url: url)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Gets an event by it's UUID
|
||||||
|
"""
|
||||||
|
def get_event_by_uuid(uuid) do
|
||||||
|
Repo.get_by(Event, uuid: uuid)
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets a single event, with all associations loaded.
|
Gets a single event, with all associations loaded.
|
||||||
"""
|
"""
|
||||||
@ -93,6 +100,14 @@ defmodule Eventos.Events do
|
|||||||
Repo.preload(event, [:organizer_actor, :category, :sessions, :tracks, :tags, :participants, :address])
|
Repo.preload(event, [:organizer_actor, :category, :sessions, :tracks, :tags, :participants, :address])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Gets a full event by it's UUID
|
||||||
|
"""
|
||||||
|
def get_event_full_by_uuid(uuid) do
|
||||||
|
event = Repo.get_by(Event, uuid: uuid)
|
||||||
|
Repo.preload(event, [:organizer_actor, :category, :sessions, :tracks, :tags, :participants, :address])
|
||||||
|
end
|
||||||
|
|
||||||
@spec get_event_full_by_name_and_slug!(String.t, String.t) :: Event.t
|
@spec get_event_full_by_name_and_slug!(String.t, String.t) :: Event.t
|
||||||
def get_event_full_by_name_and_slug!(name, slug) do
|
def get_event_full_by_name_and_slug!(name, slug) do
|
||||||
query = case String.split(name, "@") do
|
query = case String.split(name, "@") do
|
||||||
@ -139,7 +154,8 @@ defmodule Eventos.Events do
|
|||||||
def create_event(attrs \\ %{}) do
|
def create_event(attrs \\ %{}) do
|
||||||
%Event{}
|
%Event{}
|
||||||
|> Event.changeset(attrs)
|
|> Event.changeset(attrs)
|
||||||
|> Repo.insert()
|
|> Repo.insert!()
|
||||||
|
|> Repo.preload([:organizer_actor])
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -9,7 +9,7 @@ defmodule Eventos.Events.Participant do
|
|||||||
|
|
||||||
@primary_key false
|
@primary_key false
|
||||||
schema "participants" do
|
schema "participants" do
|
||||||
field :role, :integer
|
field :role, :integer, default: 0 # 0 : participant, 1 : moderator, 2 : administrator, 3 : creator
|
||||||
field :approved, :boolean
|
field :approved, :boolean
|
||||||
belongs_to :event, Event, primary_key: true
|
belongs_to :event, Event, primary_key: true
|
||||||
belongs_to :actor, Actor, primary_key: true
|
belongs_to :actor, Actor, primary_key: true
|
||||||
|
@ -11,7 +11,8 @@ defmodule Eventos.Export.ICalendar do
|
|||||||
summary: event.title,
|
summary: event.title,
|
||||||
dtstart: event.begins_on,
|
dtstart: event.begins_on,
|
||||||
dtend: event.ends_on,
|
dtend: event.ends_on,
|
||||||
description: event.description
|
description: event.description,
|
||||||
|
uid: event.uuid
|
||||||
}]
|
}]
|
||||||
%ICalendar{events: events}
|
%ICalendar{events: events}
|
||||||
|> ICalendar.to_ics()
|
|> ICalendar.to_ics()
|
||||||
|
@ -27,6 +27,27 @@ defmodule EventosWeb.AddressController do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def process_geom(%{"type" => type, "data" => data}) do
|
||||||
|
import Logger
|
||||||
|
Logger.debug("Process geom")
|
||||||
|
Logger.debug(inspect data)
|
||||||
|
Logger.debug(inspect type)
|
||||||
|
types = [:point]
|
||||||
|
unless is_atom(type) do
|
||||||
|
type = String.to_existing_atom(type)
|
||||||
|
end
|
||||||
|
case type do
|
||||||
|
:point ->
|
||||||
|
%Geo.Point{coordinates: {data["latitude"], data["longitude"]}, srid: 4326}
|
||||||
|
nil ->
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_geom(nil) do
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
def show(conn, %{"id" => id}) do
|
def show(conn, %{"id" => id}) do
|
||||||
address = Addresses.get_address!(id)
|
address = Addresses.get_address!(id)
|
||||||
render(conn, "show.json", address: address)
|
render(conn, "show.json", address: address)
|
||||||
|
@ -17,18 +17,30 @@ defmodule EventosWeb.EventController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create(conn, %{"event" => event_params}) do
|
def create(conn, %{"event" => event_params}) do
|
||||||
event_params = %{event_params | "address" => process_address(event_params["address"])}
|
address = process_address(event_params["address"])
|
||||||
|
event_params = if is_nil address do
|
||||||
|
event_params
|
||||||
|
else
|
||||||
|
%{event_params | "address" => address}
|
||||||
|
end
|
||||||
with {:ok, %Event{} = event} <- Events.create_event(event_params) do
|
with {:ok, %Event{} = event} <- Events.create_event(event_params) do
|
||||||
conn
|
conn
|
||||||
|> put_status(:created)
|
|> put_status(:created)
|
||||||
|> put_resp_header("location", event_path(conn, :show, event))
|
|> put_resp_header("location", event_path(conn, :show, event.uuid))
|
||||||
|> render("show_simple.json", event: event)
|
|> render("show_simple.json", event: event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp process_address(address) do
|
defp process_address(address) do
|
||||||
case Addresses.process_geom(address["geom"]) do
|
import Logger
|
||||||
{:ok, geom} ->
|
Logger.debug("process address")
|
||||||
|
Logger.debug(inspect address)
|
||||||
|
geom = EventosWeb.AddressController.process_geom(address["geom"])
|
||||||
|
Logger.debug(inspect geom)
|
||||||
|
case geom do
|
||||||
|
nil ->
|
||||||
|
address
|
||||||
|
_ ->
|
||||||
%{address | "geom" => geom}
|
%{address | "geom" => geom}
|
||||||
_ ->
|
_ ->
|
||||||
address
|
address
|
||||||
@ -40,27 +52,26 @@ defmodule EventosWeb.EventController do
|
|||||||
render(conn, "index.json", events: events)
|
render(conn, "index.json", events: events)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show(conn, %{"username" => username, "slug" => slug}) do
|
def show(conn, %{"uuid" => uuid}) do
|
||||||
event = Events.get_event_full_by_name_and_slug!(username, slug)
|
event = Events.get_event_full_by_uuid(uuid)
|
||||||
render(conn, "show.json", event: event)
|
render(conn, "show.json", event: event)
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_to_ics(conn, %{"username" => username, "slug" => slug}) do
|
def export_to_ics(conn, %{"uuid" => uuid}) do
|
||||||
event = Events.get_event_full_by_name_and_slug!(username, slug)
|
event = Events.get_event_full_by_uuid(uuid) |> ICalendar.export_event()
|
||||||
|> ICalendar.export_event()
|
|
||||||
send_resp(conn, 200, event)
|
send_resp(conn, 200, event)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update(conn, %{"username" => username, "slug" => slug, "event" => event_params}) do
|
def update(conn, %{"uuid" => uuid, "event" => event_params}) do
|
||||||
event = Events.get_event_full_by_name_and_slug!(username, slug)
|
event = Events.get_event_full_by_uuid(uuid)
|
||||||
|
|
||||||
with {:ok, %Event{} = event} <- Events.update_event(event, event_params) do
|
with {:ok, %Event{} = event} <- Events.update_event(event, event_params) do
|
||||||
render(conn, "show_simple.json", event: event)
|
render(conn, "show_simple.json", event: event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete(conn, %{"username" => username, "slug" => slug}) do
|
def delete(conn, %{"uuid" => uuid}) do
|
||||||
event = Events.get_event_full_by_name_and_slug!(username, slug)
|
event = Events.get_event_by_uuid(uuid)
|
||||||
with {:ok, %Event{}} <- Events.delete_event(event) do
|
with {:ok, %Event{}} <- Events.delete_event(event) do
|
||||||
send_resp(conn, :no_content, "")
|
send_resp(conn, :no_content, "")
|
||||||
end
|
end
|
||||||
|
@ -5,7 +5,7 @@ defmodule EventosWeb.GroupController do
|
|||||||
use EventosWeb, :controller
|
use EventosWeb, :controller
|
||||||
|
|
||||||
alias Eventos.Actors
|
alias Eventos.Actors
|
||||||
alias Eventos.Actors.Actor
|
alias Eventos.Actors.{Actor, Member}
|
||||||
|
|
||||||
action_fallback EventosWeb.FallbackController
|
action_fallback EventosWeb.FallbackController
|
||||||
|
|
||||||
@ -23,4 +23,18 @@ defmodule EventosWeb.GroupController do
|
|||||||
|> render(EventosWeb.ActorView, "acccount_basic.json", actor: group)
|
|> render(EventosWeb.ActorView, "acccount_basic.json", actor: group)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def join(conn, %{"name" => group_name}) do
|
||||||
|
with actor = Guardian.Plug.current_resource(conn).actor,
|
||||||
|
group <- Actors.get_group_by_name(group_name),
|
||||||
|
%Member{} = member <- Actors.create_member(%{"parent_id" => group.id, "actor_id" => actor.id}) do
|
||||||
|
conn
|
||||||
|
|> put_status(:created)
|
||||||
|
|> render(EventosWeb.MemberView, "member.json", member: member)
|
||||||
|
else
|
||||||
|
err ->
|
||||||
|
import Logger
|
||||||
|
Logger.debug(inspect err)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -40,10 +40,10 @@ defmodule EventosWeb.Router do
|
|||||||
get "/groups", GroupController, :index
|
get "/groups", GroupController, :index
|
||||||
get "/events", EventController, :index
|
get "/events", EventController, :index
|
||||||
get "/events/search/:name", EventController, :search
|
get "/events/search/:name", EventController, :search
|
||||||
get "/events/:username/:slug", EventController, :show
|
get "/events/:uuid/ics", EventController, :export_to_ics
|
||||||
get "/events/:username/:slug/ics", EventController, :export_to_ics
|
get "/events/:uuid/tracks", TrackController, :show_tracks_for_event
|
||||||
get "/events/:username/:slug/tracks", TrackController, :show_tracks_for_event
|
get "/events/:uuid/sessions", SessionController, :show_sessions_for_event
|
||||||
get "/events/:username/:slug/sessions", SessionController, :show_sessions_for_event
|
get "/events/:uuid", EventController, :show
|
||||||
resources "/comments", CommentController, only: [:show]
|
resources "/comments", CommentController, only: [:show]
|
||||||
get "/bots/:id", BotController, :view
|
get "/bots/:id", BotController, :view
|
||||||
|
|
||||||
@ -71,18 +71,17 @@ defmodule EventosWeb.Router do
|
|||||||
resources "/users", UserController, except: [:new, :edit, :show]
|
resources "/users", UserController, except: [:new, :edit, :show]
|
||||||
patch "/actors/:name", ActorController, :update
|
patch "/actors/:name", ActorController, :update
|
||||||
post "/events", EventController, :create
|
post "/events", EventController, :create
|
||||||
patch "/events/:username/:slug", EventController, :update
|
patch "/events/:uuid", EventController, :update
|
||||||
put "/events/:username/:slug", EventController, :update
|
put "/events/:uuid", EventController, :update
|
||||||
delete "/events/:username/:slug", EventController, :delete
|
delete "/events/:uuid", EventController, :delete
|
||||||
resources "/comments", CommentController, except: [:new, :edit, :show]
|
resources "/comments", CommentController, except: [:new, :edit, :show]
|
||||||
#post "/events/:id/request", EventRequestController, :create_for_event
|
#post "/events/:id/request", EventRequestController, :create_for_event
|
||||||
resources "/participant", ParticipantController
|
resources "/participant", ParticipantController
|
||||||
resources "/bots", BotController, except: [:new, :edit, :show]
|
resources "/bots", BotController, except: [:new, :edit, :show]
|
||||||
#resources "/requests", EventRequestController
|
#resources "/requests", EventRequestController
|
||||||
post "/groups", GroupController, :create
|
post "/groups", GroupController, :create
|
||||||
#post "/groups/:id/request", GroupRequestController, :create_for_group
|
post "/groups/:name/join", GroupController, :join
|
||||||
resources "/members", MemberController
|
resources "/members", MemberController
|
||||||
#resources "/requests", GroupRequestController
|
|
||||||
resources "/sessions", SessionController, except: [:index, :show]
|
resources "/sessions", SessionController, except: [:index, :show]
|
||||||
resources "/tracks", TrackController, except: [:index, :show]
|
resources "/tracks", TrackController, except: [:index, :show]
|
||||||
get "/tracks/:id/sessions", SessionController, :show_sessions_for_track
|
get "/tracks/:id/sessions", SessionController, :show_sessions_for_track
|
||||||
|
@ -3,7 +3,8 @@ defmodule EventosWeb.ActorView do
|
|||||||
View for Actors
|
View for Actors
|
||||||
"""
|
"""
|
||||||
use EventosWeb, :view
|
use EventosWeb, :view
|
||||||
alias EventosWeb.{ActorView, EventView}
|
alias EventosWeb.{ActorView, EventView, MemberView}
|
||||||
|
alias Eventos.Actors
|
||||||
|
|
||||||
def render("index.json", %{actors: actors}) do
|
def render("index.json", %{actors: actors}) do
|
||||||
%{data: render_many(actors, ActorView, "acccount_basic.json")}
|
%{data: render_many(actors, ActorView, "acccount_basic.json")}
|
||||||
@ -32,7 +33,7 @@ defmodule EventosWeb.ActorView do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render("actor.json", %{actor: actor}) do
|
def render("actor.json", %{actor: actor}) do
|
||||||
%{id: actor.id,
|
output = %{id: actor.id,
|
||||||
username: actor.preferred_username,
|
username: actor.preferred_username,
|
||||||
domain: actor.domain,
|
domain: actor.domain,
|
||||||
display_name: actor.name,
|
display_name: actor.name,
|
||||||
@ -45,5 +46,14 @@ defmodule EventosWeb.ActorView do
|
|||||||
banner: actor.banner_url,
|
banner: actor.banner_url,
|
||||||
organized_events: render_many(actor.organized_events, EventView, "event_for_actor.json")
|
organized_events: render_many(actor.organized_events, EventView, "event_for_actor.json")
|
||||||
}
|
}
|
||||||
|
import Logger
|
||||||
|
Logger.debug(inspect actor.type)
|
||||||
|
if actor.type == :Group do
|
||||||
|
Logger.debug("I'm a group !")
|
||||||
|
Map.put(output, :members, render_many(Actors.members_for_group(actor), MemberView, "member.json"))
|
||||||
|
else
|
||||||
|
Logger.debug("not a group")
|
||||||
|
output
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -20,7 +20,8 @@ defmodule EventosWeb.EventView do
|
|||||||
def render("event_for_actor.json", %{event: event}) do
|
def render("event_for_actor.json", %{event: event}) do
|
||||||
%{id: event.id,
|
%{id: event.id,
|
||||||
title: event.title,
|
title: event.title,
|
||||||
slug: event.slug
|
slug: event.slug,
|
||||||
|
uuid: event.uuid,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -31,8 +32,11 @@ defmodule EventosWeb.EventView do
|
|||||||
description: event.description,
|
description: event.description,
|
||||||
begins_on: event.begins_on,
|
begins_on: event.begins_on,
|
||||||
ends_on: event.ends_on,
|
ends_on: event.ends_on,
|
||||||
|
uuid: event.uuid,
|
||||||
organizer: %{
|
organizer: %{
|
||||||
username: event.organizer_actor.preferred_username
|
username: event.organizer_actor.preferred_username,
|
||||||
|
display_name: event.organizer_actor.name,
|
||||||
|
avatar: event.organizer_actor.avatar_url,
|
||||||
},
|
},
|
||||||
type: "Event",
|
type: "Event",
|
||||||
}
|
}
|
||||||
@ -44,6 +48,7 @@ defmodule EventosWeb.EventView do
|
|||||||
description: event.description,
|
description: event.description,
|
||||||
begins_on: event.begins_on,
|
begins_on: event.begins_on,
|
||||||
ends_on: event.ends_on,
|
ends_on: event.ends_on,
|
||||||
|
uuid: event.uuid,
|
||||||
organizer: render_one(event.organizer_actor, ActorView, "acccount_basic.json"),
|
organizer: render_one(event.organizer_actor, ActorView, "acccount_basic.json"),
|
||||||
participants: render_many(event.participants, ActorView, "show_basic.json"),
|
participants: render_many(event.participants, ActorView, "show_basic.json"),
|
||||||
address: render_one(event.address, AddressView, "address.json"),
|
address: render_one(event.address, AddressView, "address.json"),
|
||||||
|
@ -3,7 +3,7 @@ defmodule EventosWeb.MemberView do
|
|||||||
View for Members
|
View for Members
|
||||||
"""
|
"""
|
||||||
use EventosWeb, :view
|
use EventosWeb, :view
|
||||||
alias EventosWeb.MemberView
|
alias EventosWeb.{MemberView, ActorView}
|
||||||
|
|
||||||
def render("index.json", %{members: members}) do
|
def render("index.json", %{members: members}) do
|
||||||
%{data: render_many(members, MemberView, "member.json")}
|
%{data: render_many(members, MemberView, "member.json")}
|
||||||
@ -14,7 +14,10 @@ defmodule EventosWeb.MemberView do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render("member.json", %{member: member}) do
|
def render("member.json", %{member: member}) do
|
||||||
%{id: member.id,
|
%{
|
||||||
role: member.role}
|
role: member.role,
|
||||||
|
actor: render_one(member.actor, ActorView, "acccount_basic.json"),
|
||||||
|
group: render_one(member.parent, ActorView, "acccount_basic.json")
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
defmodule EventosWeb.RequestView do
|
|
||||||
@moduledoc """
|
|
||||||
View for event request
|
|
||||||
"""
|
|
||||||
use EventosWeb, :view
|
|
||||||
alias EventosWeb.RequestView
|
|
||||||
|
|
||||||
def render("index.json", %{requests: requests}) do
|
|
||||||
%{data: render_many(requests, RequestView, "request.json")}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("show.json", %{request: request}) do
|
|
||||||
%{data: render_one(request, RequestView, "request.json")}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("request.json", %{request: request}) do
|
|
||||||
%{id: request.id,
|
|
||||||
state: request.state}
|
|
||||||
end
|
|
||||||
end
|
|
@ -0,0 +1,15 @@
|
|||||||
|
defmodule Eventos.Repo.Migrations.AddUUIDIdToEvents do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
alter table(:events) do
|
||||||
|
add :uuid, :uuid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
alter table(:events) do
|
||||||
|
remove :uuid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
defmodule Eventos.Repo.Migrations.AddApprovedStatusToMember do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
alter table(:members) do
|
||||||
|
add :approved, :boolean, default: true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
alter table(:members) do
|
||||||
|
remove :approved
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user