Move to GraphQL

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2018-11-06 10:30:27 +01:00
parent 7e137d1a1c
commit b54dae7e15
149 changed files with 5605 additions and 4665 deletions

View File

@@ -1,216 +1,210 @@
<template>
<v-layout row>
<v-flex xs12 sm6 offset-sm3>
<v-progress-circular v-if="loading" indeterminate color="primary"></v-progress-circular>
<v-card v-if="!loading">
<v-img :src="actor.banner || 'https://picsum.photos/400/'" height="300px">
<v-layout column class="media">
<v-card-title>
<v-btn icon @click="$router.go(-1)">
<v-icon>chevron_left</v-icon>
</v-btn>
<v-spacer></v-spacer>
<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.actor.id === actor.id">
<v-icon>edit</v-icon>
</v-btn>
<v-menu bottom left>
<v-btn icon slot="activator">
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-tile @click="logoutUser()" v-if="$store.state.user && $store.state.actor.id === actor.id">
<v-list-tile-title>User logout</v-list-tile-title>
</v-list-tile>
<v-list-tile @click="deleteAccount()" v-if="$store.state.user && $store.state.actor.id === actor.id">
<v-list-tile-title>Delete</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</v-card-title>
<v-spacer></v-spacer>
<div class="text-xs-center">
<v-avatar size="125px">
<img v-if="!actor.avatar"
class="img-circle elevation-7 mb-1"
src="https://picsum.photos/125/125/"
>
<img v-else
<ApolloQuery :query="FETCH_ACTOR" :variables="{ name }">
<template slot-scope="{ result: { loading, error, data } }">
<v-progress-circular v-if="loading" indeterminate color="primary"></v-progress-circular>
<v-card v-if="data">
<v-img :src="data.actor.banner || 'https://picsum.photos/400/'" height="300px">
<v-layout column class="media">
<v-card-title>
<v-btn icon @click="$router.go(-1)">
<v-icon>chevron_left</v-icon>
</v-btn>
<v-spacer></v-spacer>
<!-- <v-btn icon class="mr-3" v-if="actor.id === data.actor.id">
<v-icon>edit</v-icon>
</v-btn> -->
<v-menu bottom left>
<v-btn icon slot="activator">
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<!-- <v-list-tile @click="logoutUser()" v-if="actor.id === data.actor.id">
<v-list-tile-title>User logout</v-list-tile-title>
</v-list-tile>
<v-list-tile @click="deleteAccount()" v-if="actor.id === data.actor.id">
<v-list-tile-title>Delete</v-list-tile-title>
</v-list-tile> -->
</v-list>
</v-menu>
</v-card-title>
<v-spacer></v-spacer>
<div class="text-xs-center">
<v-avatar size="125px">
<img v-if="!data.actor.avatarUrl"
class="img-circle elevation-7 mb-1"
:src="actor.avatar"
>
</v-avatar>
</div>
<v-container fluid grid-list-lg>
<v-layout row>
<v-flex xs7>
<div class="headline">{{ actor.display_name }}</div>
<div><span class="subheading">@{{ actor.username }}<span v-if="actor.domain">@{{ actor.domain }}</span></span></div>
<v-card-text v-if="actor.description" v-html="actor.description"></v-card-text>
src="https://picsum.photos/125/125/"
>
<img v-else
class="img-circle elevation-7 mb-1"
:src="data.actor.avatarUrl"
>
</v-avatar>
</div>
<v-container fluid grid-list-lg>
<v-layout row>
<v-flex xs7>
<div class="headline">{{ data.actor.name }}</div>
<div><span class="subheading">@{{ data.actor.preferredUsername }}<span v-if="data.actor.domain">@{{ data.actor.domain }}</span></span></div>
<v-card-text v-if="data.actor.description" v-html="data.actor.description"></v-card-text>
</v-flex>
</v-layout>
</v-container>
</v-layout>
</v-img>
<v-list three-line>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">phone</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>(323) 555-6789</v-list-tile-title>
<v-list-tile-sub-title>Work</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-icon dark>chat</v-icon>
</v-list-tile-action>
</v-list-tile>
<v-divider inset></v-divider>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">mail</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>ali_connors@example.com</v-list-tile-title>
<v-list-tile-sub-title>Work</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
<v-divider inset></v-divider>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">location_on</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>1400 Main Street</v-list-tile-title>
<v-list-tile-sub-title>Orlando, FL 79938</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
<v-container fluid grid-list-md v-if="data.actor.participatingEvents && data.actor.participatingEvents.length > 0">
<v-subheader>Participated at</v-subheader>
<v-layout row wrap>
<v-flex v-for="event in data.actor.participatingEvents" :key="event.id">
<v-card>
<v-img
class="black--text"
height="200px"
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-img>
<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-layout>
</v-img>
<v-list three-line>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">phone</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>(323) 555-6789</v-list-tile-title>
<v-list-tile-sub-title>Work</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-icon dark>chat</v-icon>
</v-list-tile-action>
</v-list-tile>
<v-divider inset></v-divider>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">mail</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>ali_connors@example.com</v-list-tile-title>
<v-list-tile-sub-title>Work</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
<v-divider inset></v-divider>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">location_on</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>1400 Main Street</v-list-tile-title>
<v-list-tile-sub-title>Orlando, FL 79938</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
<v-container fluid grid-list-md v-if="actor.participatingEvents && actor.participatingEvents.length > 0">
<v-subheader>Participated at</v-subheader>
<v-layout row wrap>
<v-flex v-for="event in actor.participatingEvents" :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-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="actor.organized_events && actor.organized_events.length > 0">
<v-subheader>Organized events</v-subheader>
<v-layout row wrap>
<v-flex v-for="event in actor.organized_events" :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-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-card>
<v-container fluid grid-list-md v-if="data.actor.organizedEvents && data.actor.organizedEvents.length > 0">
<v-subheader>Organized events</v-subheader>
<v-layout row wrap>
<v-flex v-for="event in data.actor.organizedEvents" :key="event.id" md6>
<v-card>
<v-img
height="200px"
src="https://picsum.photos/400/200/"
/>
<v-card-title primary-title>
<div>
<router-link :to="{name: 'Event', params: {uuid: event.uuid}}">
<div class="headline">{{ event.title }}</div>
</router-link>
<span class="grey--text" v-html="nl2br(event.description)"></span>
</div>
</v-card-title>
<!-- <v-card-title>
<div>
<span class="grey--text" v-if="event.addressType === 'physical'">{{ event.startDate }} à {{ event.location }}</span><br>
<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-card>
</template>
</ApolloQuery>
</v-flex>
</v-layout>
</template>
<script>
import eventFetch from '@/api/eventFetch';
import auth from '@/auth';
import { FETCH_ACTOR } from '@/graphql/actor';
export default {
name: 'Account',
data() {
return {
actor: null,
loading: true,
}
loading: true,
};
},
props: {
name: {
type: String,
required: true,
}
name: {
type: String,
required: true,
},
},
created() {
this.fetchData();
},
watch: {
// call again the method if the route changes
'$route': 'fetchData'
$route: 'fetchData',
},
methods: {
fetchData() {
eventFetch(`/actors/${this.name}`, this.$store)
.then(response => response.json())
.then((response) => {
this.actor = response.data;
this.loading = false;
console.log('actor', this.actor);
})
},
logoutUser() {
auth.logout(this.$store);
// TODO : implement logout
this.$router.push({ name: 'Home' });
},
}
}
nl2br: function(text) {
return text.replace(/(?:\r\n|\r|\n)/g, '<br>');
}
},
};
</script>

View File

@@ -15,7 +15,7 @@
@click="$router.push({ name: 'Account', params: { name: actor.username } })"
>
<v-list-tile-action>
<v-icon v-if="$store.state.defaultActor === actor.username" color="pink">star</v-icon>
<v-icon v-if="defaultActor === actor.username" color="pink">star</v-icon>
</v-list-tile-action>
<v-list-tile-content>
@@ -67,29 +67,26 @@
</template>
<script>
import eventFetch from "@/api/eventFetch";
import auth from "@/auth";
export default {
name: "Identities",
name: 'Identities',
data() {
return {
actors: [],
newActor: {
preferred_username: "",
summary: ""
preferred_username: '',
summary: '',
},
loading: true,
showForm: false,
rules: {
required: value => !!value || "Required."
required: value => !!value || 'Required.',
},
state: {
username: {
status: false,
msg: []
}
}
msg: [],
},
},
};
},
created() {
@@ -97,9 +94,9 @@ export default {
},
methods: {
fetchData() {
eventFetch(`/user`, this.$store)
eventFetch('/user', this.$store)
.then(response => response.json())
.then(response => {
.then((response) => {
this.actors = response.data.actors;
this.loading = false;
});
@@ -107,12 +104,12 @@ export default {
sendData() {
this.loading = true;
this.showForm = false;
eventFetch(`/actors`, this.$store, {
method: "POST",
body: JSON.stringify({ actor: this.newActor })
eventFetch('/actors', this.$store, {
method: 'POST',
body: JSON.stringify({ actor: this.newActor }),
})
.then(response => response.json())
.then(response => {
.then((response) => {
this.actors.push(response.data);
this.loading = false;
});
@@ -126,7 +123,7 @@ export default {
},
host() {
return `@${window.location.host}`;
}
}
},
},
};
</script>

View File

@@ -60,83 +60,88 @@
<script>
import { LOGIN_USER } from '@/store/mutation-types';
import auth from '@/auth/index';
import Gravatar from 'vue-gravatar';
import RegisterAvatar from './RegisterAvatar';
import Gravatar from 'vue-gravatar';
import RegisterAvatar from './RegisterAvatar';
import { AUTH_TOKEN, AUTH_USER_ID, AUTH_USER_ACTOR } from '@/constants';
import { LOGIN } from '@/graphql/auth';
export default {
props: {
email: {
type: String,
required: false,
default: '',
export default {
props: {
email: {
type: String,
required: false,
default: '',
},
password: {
type: String,
required: false,
default: '',
},
},
beforeCreate() {
if (this.user) {
this.$router.push('/');
}
},
components: {
'v-gravatar': Gravatar,
avatar: RegisterAvatar,
},
mounted() {
this.credentials.email = this.email;
this.credentials.password = this.password;
},
data() {
return {
credentials: {
email: '',
password: '',
},
password: {
type: String,
required: false,
default: '',
},
},
beforeCreate() {
if (this.$store.state.user) {
this.$router.push('/');
}
},
components: {
'v-gravatar': Gravatar,
'avatar': RegisterAvatar
},
mounted() {
this.credentials.email = this.email;
this.credentials.password = this.password;
},
data() {
return {
credentials: {
email: '',
password: '',
validationSent: false,
error: {
show: false,
text: '',
timeout: 3000,
field: {
email: false,
password: false,
},
validationSent: false,
error: {
show: false,
text: '',
timeout: 3000,
field: {
email: false,
password: false,
},
},
rules: {
required: value => !!value || 'Required.',
email: (value) => {
const pattern = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return pattern.test(value) || 'Invalid e-mail.';
},
},
};
},
methods: {
loginAction(e) {
e.preventDefault();
auth.login(JSON.stringify(this.credentials), (data) => {
this.$store.commit(LOGIN_USER, data.user);
this.$router.push({ name: 'Home' });
}, (error) => {
Promise.resolve(error).then((errorMsg) => {
console.log(errorMsg);
this.error.show = true;
this.error.text = this.$t(errorMsg.display_error);
}).catch((e) => {
console.log(e);
this.error.show = true;
this.error.text = e.message;
});
});
},
validEmail() {
return this.rules.email(this.credentials.email) === true ? 'v-gravatar' : 'avatar';
rules: {
required: value => !!value || 'Required.',
email: (value) => {
const pattern = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return pattern.test(value) || 'Invalid e-mail.';
},
},
};
},
methods: {
loginAction(e) {
e.preventDefault();
this.$apollo.mutate({
mutation: LOGIN,
variables: {
email: this.credentials.email,
password: this.credentials.password
}
}).then((result) => {
this.saveUserData(result.data);
this.$router.push({name: 'Home'});
}).catch((e) => {
console.log(e);
this.error.show = true;
this.error.text = e.message;
});
},
};
validEmail() {
return this.rules.email(this.credentials.email) === true ? 'v-gravatar' : 'avatar';
},
saveUserData({login: login}) {
localStorage.setItem(AUTH_USER_ID, login.user.id);
localStorage.setItem(AUTH_USER_ACTOR, JSON.stringify(login.actor));
localStorage.setItem(AUTH_TOKEN, login.token);
}
},
};
</script>

View File

@@ -37,8 +37,6 @@
</template>
<script>
import fetchStory from '@/api/eventFetch';
export default {
name: 'PasswordReset',
props: {
@@ -80,7 +78,7 @@ export default {
password_length: value => value.length > 6 || 'Password must be at least 6 caracters long',
required: value => !!value || 'Required.',
password_equal: value => value === this.credentials.password || 'Passwords must be the same',
}
},
};
},
methods: {

View File

@@ -9,7 +9,7 @@
<v-tooltip bottom>
<v-btn
slot="activator"
:to="{ name: 'Login', params: { email: this.credentials.email, password: this.credentials.password } }"
:to="{ name: 'Login', params: { email, password } }"
>
<!-- <v-icon large>login</v-icon> -->
<span>Login</span>
@@ -21,22 +21,22 @@
<div class="text-xs-center">
<v-avatar size="80px">
<transition name="avatar">
<component :is="validEmail()" v-bind="{email: credentials.email}"></component>
<component :is="validEmail()" v-bind="{email}"></component>
<!-- <v-gravatar :email="credentials.email" default-img="mp" v-if="validEmail()"/>
<avatar v-else></avatar> -->
</transition>
</v-avatar>
</div>
<v-form @submit="registerAction" v-if="!validationSent">
<v-form @submit="submit()" v-if="!validationSent">
<v-text-field
label="Username"
required
type="text"
v-model="credentials.username"
v-model="username"
:rules="[rules.required]"
:error="this.state.username.status"
:error-messages="this.state.username.msg"
:suffix="this.host()"
:error="state.username.status"
:error-messages="state.username.msg"
:suffix="host()"
hint="You will be able to create more identities once registered"
persistent-hint
>
@@ -46,30 +46,30 @@
required
type="email"
ref="email"
v-model="credentials.email"
v-model="email"
:rules="[rules.required, rules.email]"
:error="this.state.email.status"
:error-messages="this.state.email.msg"
:error="state.email.status"
:error-messages="state.email.msg"
>
</v-text-field>
<v-text-field
label="Password"
required
:type="showPassword ? 'text' : 'password'"
v-model="credentials.password"
v-model="password"
:rules="[rules.required, rules.password_length]"
:error="this.state.password.status"
:error-messages="this.state.password.msg"
:error="state.password.status"
:error-messages="state.password.msg"
:append-icon="showPassword ? 'visibility_off' : 'visibility'"
@click:append="showPassword = !showPassword"
>
</v-text-field>
<v-btn @click="registerAction" color="primary">Register</v-btn>
<router-link :to="{ name: 'ResendConfirmation', params: { email: credentials.email }}">Didn't receive the instructions ?</router-link>
<v-btn @click="submit()" color="primary">Register</v-btn>
<router-link :to="{ name: 'ResendConfirmation', params: { email }}">Didn't receive the instructions ?</router-link>
</v-form>
<div v-else>
<h2>{{ $t('registration.form.validation_sent', { email: credentials.email }) }}</h2>
<b-alert show variant="info">{{ $t('registration.form.validation_sent_info') }}</b-alert>
<div v-if="validationSent">
<h2><translate>A validation email was sent to %{email}</translate></h2>
<v-alert :value="true" type="info"><translate>Before you can login, you need to click on the link inside it to validate your account</translate></v-alert>
</div>
</v-card-text>
</v-card>
@@ -79,110 +79,101 @@
</template>
<script>
import auth from '@/auth/index';
import Gravatar from 'vue-gravatar';
import RegisterAvatar from './RegisterAvatar';
import Gravatar from 'vue-gravatar';
import RegisterAvatar from './RegisterAvatar';
import { CREATE_USER } from '@/graphql/user';
export default {
props: {
email: {
type: String,
required: false,
default: '',
export default {
props: {
default_email: {
type: String,
required: false,
default: '',
},
default_password: {
type: String,
required: false,
default: '',
},
},
components: {
'v-gravatar': Gravatar,
avatar: RegisterAvatar,
},
data() {
return {
username: '',
email: this.default_email,
password: this.default_password,
error: {
show: false,
},
password: {
type: String,
required: false,
default: '',
showPassword: false,
validationSent: false,
state: {
email: {
status: false,
msg: [],
},
username: {
status: false,
msg: [],
},
password: {
status: false,
msg: [],
},
},
},
components: {
'v-gravatar': Gravatar,
'avatar': RegisterAvatar
},
mounted() {
this.credentials.email = this.email;
this.credentials.password = this.password;
},
data() {
return {
credentials: {
username: '',
email: '',
password: '',
rules: {
password_length: value => value.length > 6 || 'Password must be at least 6 caracters long',
required: value => !!value || 'Required.',
email: (value) => {
const pattern = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return pattern.test(value) || 'Invalid e-mail.';
},
error: {
show: false,
},
};
},
methods: {
resetState() {
this.state = {
email: {
status: false,
msg: '',
},
showPassword: false,
validationSent: false,
state: {
email: {
status: false,
msg: [],
},
username: {
status: false,
msg: [],
},
password: {
status: false,
msg: [],
},
username: {
status: false,
msg: '',
},
rules: {
password_length: value => value.length > 6 || 'Password must be at least 6 caracters long',
required: value => !!value || 'Required.',
email: (value) => {
const pattern = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return pattern.test(value) || 'Invalid e-mail.';
},
password: {
status: false,
msg: '',
},
};
},
methods: {
registerAction(e) {
this.resetState();
e.preventDefault();
auth.signup(JSON.stringify(this.credentials), (data) => {
console.log(data);
this.validationSent = true;
}, (error) => {
Promise.resolve(error).then((errormsg) => {
console.log(errormsg);
this.error.show = true;
Object.entries(errormsg.errors.user).forEach(([key, val]) => {
console.log(key);
console.log(val);
this.state[key] = { status: true, msg: val };
});
});
});
},
resetState() {
this.state = {
email: {
status: false,
msg: '',
},
username: {
status: false,
msg: '',
},
password: {
status: false,
msg: '',
},
};
},
host() {
return `@${window.location.host}`;
},
validEmail() {
return this.rules.email(this.credentials.email) === true ? 'v-gravatar' : 'avatar';
}
host() {
return `@${window.location.host}`;
},
};
validEmail() {
return this.rules.email(this.email) === true ? 'v-gravatar' : 'avatar';
},
submit() {
this.$apollo.mutate({
mutation: CREATE_USER,
variables: {
email: this.email,
password: this.password,
username: this.username,
},
}).then((data) => {
console.log(data);
this.validationSent = true;
}).catch((error) => {
console.error(error);
});
},
},
};
</script>
<style lang="scss">
.avatar-enter-active {

View File

@@ -3,7 +3,7 @@
</template>
<script>
export default {
name: 'RegisterAvatar'
}
name: 'RegisterAvatar',
};
</script>

View File

@@ -31,8 +31,6 @@
</template>
<script>
import fetchStory from '@/api/eventFetch';
export default {
name: 'ResendConfirmation',
props: {

View File

@@ -31,8 +31,6 @@
</template>
<script>
import fetchStory from '@/api/eventFetch';
export default {
name: 'SendPasswordReset',
props: {
@@ -43,8 +41,8 @@ export default {
},
},
mounted() {
this.credentials.email = this.email;
},
this.credentials.email = this.email;
},
data() {
return {
credentials: {

View File

@@ -1,18 +1,17 @@
<template>
<v-container>
<h1 v-if="loading">{{ $t('registration.validation.process') }}</h1>
<h1 v-if="loading"><translate>Your account is being validated</translate></h1>
<div v-else>
<div v-if="failed">
<v-alert :value="true" variant="danger">Error while validating account</v-alert>
<v-alert :value="true" variant="danger"><translate>Error while validating account</translate></v-alert>
</div>
<h1 v-else>{{ $t('registration.validation.finished') }}</h1>
<h1 v-else><translate>Your account has been validated</translate></h1>
</div>
</v-container>
</template>
<script>
import fetchStory from '@/api/eventFetch';
import { LOGIN_USER } from '@/store/mutation-types';
import { VALIDATE_USER } from '@/graphql/user';
export default {
name: 'Validate',
@@ -33,20 +32,27 @@ export default {
},
methods: {
validateAction() {
fetchStory(`/users/validate/${this.token}`, this.$store).then((data) => {
this.$apollo.mutate({
mutation: VALIDATE_USER,
variables: {
token: this.token,
},
}).then((data) => {
this.loading = false;
localStorage.setItem('token', data.token);
localStorage.setItem('refresh_token', data.refresh_token);
this.$store.commit(LOGIN_USER, data.account);
this.$snotify.success(this.$t('registration.success.login', { username: data.account.username }));
this.$router.push({ name: 'Home' });
}).catch((err) => {
Promise.resolve(err).then(() => {
this.failed = true;
this.loading = false;
});
console.log(data);
this.saveUserData(data.data);
this.$router.push({name: 'Home'});
}).catch((error) => {
this.loading = false;
console.log(error);
this.failed = true;
});
},
saveUserData({validateUser: login}) {
localStorage.setItem(AUTH_USER_ID, login.user.id);
localStorage.setItem(AUTH_USER_ACTOR, JSON.stringify(login.actor));
localStorage.setItem(AUTH_TOKEN, login.token);
}
},
};
</script>

View File

@@ -1,42 +1,87 @@
<template>
<div>
<h3>Create a new category</h3>
<v-form>
<v-text-field
label="Name of the category"
v-model="category.title"
:counter="100"
required
></v-text-field>
</v-form>
<v-btn color="primary" @click="create">Create category</v-btn>
</div>
<v-container fluid fill-height>
<v-layout align-center justify-center>
<v-flex xs12 sm8 md4>
<v-card class="elevation-12">
<v-toolbar dark color="primary">
<v-toolbar-title><translate>Create a new category</translate></v-toolbar-title>
</v-toolbar>
<v-card-text>
<v-form>
<v-text-field
:label="$gettext('Name of the category')"
v-model="title"
:counter="100"
required
></v-text-field>
<v-textarea
:label="$gettext('Description')"
v-model="description"
></v-textarea>
<v-flex xs12 class="text-xs-center text-sm-center text-md-center text-lg-center">
<v-img :src="image.url" height="150" v-if="image.url" aspect-ratio="1" contain/>
<v-text-field label="Select Image" @click='pickFile' v-model='image.name' prepend-icon='attach_file'></v-text-field>
<input
type="file"
style="display: none"
ref="image"
accept="image/*"
@change="onFilePicked"
>
</v-flex>
<v-btn color="primary" @click="create"><translate>Create category</translate></v-btn>
</v-form>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import eventFetch from '@/api/eventFetch';
import { UPLOAD_PICTURE } from '@/graphql/upload';
import { CREATE_CATEGORY } from '@/graphql/category';
export default {
name: 'create-category',
data() {
return {
category: {
title: '',
},
};
},
methods: {
create() {
const router = this.$router;
eventFetch('/categories', this.$store, { method: 'POST', body: JSON.stringify({ category: this.category }) })
.then(response => response.json())
.then(() => {
this.loading = false;
router.push('/category')
});
export default {
name: 'create-category',
data() {
return {
title: '',
description: '',
image: {
url: '',
name: '',
file: '',
},
};
},
methods: {
create() {
this.$apollo.mutate({
mutation: CREATE_CATEGORY,
variables: {
title: this.title,
description: this.description,
picture: this.$refs.image.files[0],
}
}).then((data) => {
console.log(data);
}).catch((error) => {
console.error(error);
});
},
};
pickFile () {
this.$refs.image.click ()
},
onFilePicked(e) {
const files = e.target.files;
if(files[0] === undefined || files[0].name.lastIndexOf('.') <= 0) {
console.error("File is incorrect")
}
this.image.name = files[0].name;
},
},
};
</script>
<style>

View File

@@ -1,14 +1,13 @@
<template>
<v-container>
<h1>Category List</h1>
<v-progress-circular v-if="loading" indeterminate color="primary"></v-progress-circular>
<v-container fluid grid-list-md class="grey lighten-4">
<v-layout row wrap v-if="!loading">
<v-progress-circular v-if="$apollo.loading" indeterminate color="primary"></v-progress-circular>
<v-layout row wrap v-else>
<v-flex xs12 sm6 md3 v-for="category in categories" :key="category.id">
<v-card>
<v-card-media v-if="category.image" :src="'/images/categories/' + category.image.name" height="200px">
</v-card-media>
<v-img v-if="category.picture.url" :src="HTTP_ENDPOINT + category.picture.url" height="200px">
</v-img>
<v-card-title primary-title>
<div>
<h3 class="headline mb-0">{{ category.title }}</h3>
@@ -16,8 +15,8 @@
</div>
</v-card-title>
<v-card-actions>
<v-btn flat class="orange--text">Explore</v-btn>
<v-btn flat class="red--text" v-on:click="deleteCategory(category.id)">Delete</v-btn>
<v-btn flat class="orange--text"><translate>Explore</translate></v-btn>
<v-btn flat class="red--text" v-on:click="deleteCategory(category.id)"><translate>Delete</translate></v-btn>
</v-card-actions>
</v-card>
</v-flex>
@@ -32,40 +31,36 @@
</template>
<script>
import eventFetch from '@/api/eventFetch';
import { FETCH_CATEGORIES } from '@/graphql/category';
export default {
name: 'Home',
data() {
return {
categories: [],
loading: true,
};
// TODO : remove this hardcode
export default {
name: 'Home',
data() {
return {
categories: [],
loading: true,
HTTP_ENDPOINT: 'http://localhost:4000',
};
},
apollo: {
categories: {
query: FETCH_CATEGORIES,
},
created() {
this.fetchData();
},
methods: {
fetchData() {
eventFetch('/categories', this.$store)
.then(response => response.json())
.then((response) => {
this.loading = false;
this.categories = response.data;
});
},
deleteCategory(categoryId) {
const router = this.$router;
eventFetch('/categories/' + categoryId, this.$store, {method: 'DELETE'})
.then(() => {
this.categories = this.categories.filter((category) => {
return category.id !== categoryId;
});
},
methods: {
deleteCategory(categoryId) {
const router = this.$router;
eventFetch(`/categories/${categoryId}`, this.$store, { method: 'DELETE' })
.then(() => {
this.categories = this.categories.filter(category => category.id !== categoryId);
router.push('/category');
});
}
},
};
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->

View File

@@ -14,6 +14,8 @@
:counter="100"
required
></v-text-field>
<v-date-picker v-model="event.begins_on">
</v-date-picker>
<v-radio-group v-model="event.location_type" row>
<v-radio label="Address" value="physical" off-icon="place"></v-radio>
<v-radio label="Online" value="online" off-icon="link"></v-radio>
@@ -21,7 +23,7 @@
<v-radio label="Other" value="other"></v-radio>
</v-radio-group>
<!-- <vuetify-google-autocomplete
v-if="event.location_type === 'physical'"
v-if="event.location_type === 'physical'"
id="map"
append-icon="search"
classname="form-control"
@@ -64,134 +66,132 @@
</template>
<script>
// import Location from '@/components/Location';
import eventFetch from '@/api/eventFetch';
import VueMarkdown from 'vue-markdown';
// import Location from '@/components/Location';
import VueMarkdown from 'vue-markdown';
import { CREATE_EVENT, EDIT_EVENT } from '@/graphql/event';
import { FETCH_CATEGORIES } from '@/graphql/category';
import { AUTH_USER_ACTOR } from '@/constants';
export default {
name: 'create-event',
props: ['id'],
components: {
/* Location,*/
VueMarkdown,
export default {
name: 'create-event',
props: {
uuid: {
required: false,
type: String,
},
data() {
return {
e1: 0,
event: {
title: null,
description: null,
begins_on: new Date(),
ends_on: new Date(),
seats: null,
physical_address: null,
location_type: 'physical',
online_address: null,
tel_num: null,
price: null,
category: null,
category_id: null,
tags: [],
participants: [],
},
categories: [],
},
components: {
/* Location, */
VueMarkdown,
},
data() {
return {
e1: 0,
event: {
title: null,
description: '',
begins_on: (new Date()).toISOString().substr(0, 10),
ends_on: new Date(),
seats: null,
physical_address: null,
location_type: 'physical',
online_address: null,
tel_num: null,
price: null,
category: null,
category_id: null,
tags: [],
tagsToSend: [],
tagsFetched: [],
};
participants: [],
},
categories: [],
tags: [],
tagsToSend: [],
tagsFetched: [],
};
},
// created() {
// if (this.uuid) {
// this.fetchEvent();
// }
// },
apollo: {
categories: {
query: FETCH_CATEGORIES,
},
created() {
if (this.id) {
this.fetchEvent();
},
methods: {
create() {
// this.event.seats = parseInt(this.event.seats, 10);
// this.tagsToSend.forEach((tag) => {
// this.event.tags.push({
// title: tag,
// // '@type': 'Tag',
// });
// });
const actor = JSON.parse(localStorage.getItem(AUTH_USER_ACTOR));
this.event.category_id = this.event.category;
this.event.organizer_actor_id = actor.id;
this.event.participants = [actor.id];
// this.event.price = parseFloat(this.event.price);
if (this.uuid === undefined) {
this.$apollo.mutate({
mutation: CREATE_EVENT,
variables: {
title: this.event.title,
description: this.event.description,
organizerActorId: this.event.organizer_actor_id,
categoryId: this.event.category_id,
beginsOn: this.event.begins_on,
addressType: this.event.location_type,
}
}).then((data) => {
this.loading = false;
this.$router.push({ name: 'Event', params: { uuid: data.data.uuid } });
}).catch((error) => {
console.log(error);
});
} else {
this.$apollo.mutate({
mutation: EDIT_EVENT,
}).then((data) => {
this.loading = false;
this.$router.push({ name: 'Event', params: { uuid: data.data.uuid } });
}).catch((error) => {
console.log(error);
});
}
this.event.tags = [];
},
// fetchEvent() {
// eventFetch(`/events/${this.id}`, this.$store)
// .then(response => response.json())
// .then((data) => {
// this.loading = false;
// this.event = data;
// console.log(this.event);
// });
// },
getAddressData(addressData) {
if (addressData !== null) {
this.event.address = {
geom: {
data: {
latitude: addressData.latitude,
longitude: addressData.longitude,
},
type: 'point',
},
addressCountry: addressData.country,
addressLocality: addressData.locality,
addressRegion: addressData.administrative_area_level_1,
postalCode: addressData.postal_code,
streetAddress: `${addressData.street_number} ${addressData.route}`,
};
}
},
mounted() {
this.fetchCategories();
this.fetchTags();
},
methods: {
create() {
// this.event.seats = parseInt(this.event.seats, 10);
// this.tagsToSend.forEach((tag) => {
// this.event.tags.push({
// title: tag,
// // '@type': 'Tag',
// });
// });
this.event.category_id = this.event.category;
this.event.organizer_actor_id = this.$store.state.actor.id;
this.event.participants = [this.$store.state.actor.id];
// this.event.price = parseFloat(this.event.price);
if (this.id === undefined) {
eventFetch('/events', this.$store, {method: 'POST', body: JSON.stringify({ event: this.event })})
.then(response => response.json())
.then((data) => {
this.loading = false;
this.$router.push({name: 'Event', params: {uuid: data.data.uuid}});
}).catch((err) => {
Promise.resolve(err).then((err) => {
console.log('err creation', err);
});
});
} else {
eventFetch(`/events/${this.uuid}`, this.$store, {method: 'PUT', body: JSON.stringify(this.event)})
.then(response => response.json())
.then((data) => {
this.loading = false;
this.$router.push({name: 'Event', params: {uuid: data.uuid}});
});
}
this.event.tags = [];
},
fetchCategories() {
eventFetch('/categories', this.$store)
.then(response => response.json())
.then((response) => {
this.loading = false;
this.categories = response.data;
});
},
fetchTags() {
eventFetch('/tags', this.$store)
.then(response => response.json())
.then((response) => {
this.loading = false;
response.data.forEach((tag) => {
this.tagsFetched.push(tag.name);
});
});
},
fetchEvent() {
eventFetch(`/events/${this.id}`, this.$store)
.then(response => response.json())
.then((data) => {
this.loading = false;
this.event = data;
console.log(this.event);
});
},
getAddressData: function (addressData) {
if (addressData !== null) {
this.event.address = {
geom: {
data: {
latitude: addressData.latitude,
longitude: addressData.longitude,
},
type: "point",
},
addressCountry: addressData.country,
addressLocality: addressData.locality,
addressRegion: addressData.administrative_area_level_1,
postalCode: addressData.postal_code,
streetAddress: `${addressData.street_number} ${addressData.route}`,
};
}
},
},
};
},
};
</script>
<style>

View File

@@ -98,29 +98,27 @@
</template>
<script>
import eventFetch from '@/api/eventFetch';
export default {
props: ['id'],
data() {
return {
loading: true,
event: null,
};
export default {
props: ['id'],
data() {
return {
loading: true,
event: null,
};
},
created() {
this.fetchData();
},
methods: {
fetchData() {
eventFetch(`/events/${this.id}`, this.$store)
.then(response => response.json())
.then((data) => {
this.loading = false;
this.event = data;
console.log(this.event);
});
},
created() {
this.fetchData();
},
methods: {
fetchData() {
eventFetch(`/events/${this.id}`, this.$store)
.then(response => response.json())
.then((data) => {
this.loading = false;
this.event = data;
console.log(this.event);
});
},
}
}
},
};
</script>

View File

@@ -1,239 +1,237 @@
<template>
<v-layout row>
<v-flex xs12 sm6 offset-sm3>
<span v-if="error">Error : event not found</span>
<v-progress-circular v-if="loading" indeterminate color="primary"></v-progress-circular>
<v-card v-if="!loading && !error">
<v-img
src="https://picsum.photos/600/400/"
height="200px"
>
<v-container fill-height fluid>
<v-layout fill-height>
<v-flex xs12 align-end flexbox>
<v-card-title>
<v-btn icon @click="$router.go(-1)" class="white--text">
<v-icon>chevron_left</v-icon>
</v-btn>
<v-progress-circular v-if="$apollo.loading" indeterminate color="primary"></v-progress-circular>
<div>{{ event }}</div>
<v-card v-if="event">
<!-- <v-img
src="https://picsum.photos/600/400/"
height="200px"
>
<v-container fill-height fluid>
<v-layout fill-height>
<v-flex xs12 align-end flexbox>
<v-card-title>
<v-btn icon @click="$router.go(-1)" class="white--text">
<v-icon>chevron_left</v-icon>
</v-btn>
<v-spacer></v-spacer>
<v-btn icon class="mr-3 white--text" v-if="actorIsOrganizer()" :to="{ name: 'EditEvent', params: {uuid: event.uuid}}">
<v-icon>edit</v-icon>
</v-btn>
<v-menu bottom left>
<v-btn icon slot="activator" class="white--text">
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-tile @click="downloadIcsEvent()">
<v-list-tile-title>Download</v-list-tile-title>
</v-list-tile>
<v-list-tile @click="deleteEvent()" v-if="actorIsOrganizer()">
<v-list-tile-title>Delete</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</v-card-title>
</v-flex>
</v-layout>
</v-container>
</v-img> -->
<v-container grid-list-md>
<v-layout row wrap>
<v-flex md10>
<v-spacer></v-spacer>
<v-btn icon class="mr-3 white--text" v-if="actorIsOrganizer()" :to="{ name: 'EditEvent', params: {id: event.id}}">
<v-icon>edit</v-icon>
</v-btn>
<v-menu bottom left>
<v-btn icon slot="activator" class="white--text">
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-tile @click="downloadIcsEvent()">
<v-list-tile-title>Download</v-list-tile-title>
<span class="subheading grey--text">{{ event.begins_on | formatDay }}</span>
<h1 class="display-1">{{ event.title }}</h1>
<div>
<!-- <router-link :to="{name: 'Account', params: { name: event.organizerActor.preferredUsername } }">
<v-avatar size="25px">
<img class="img-circle elevation-7 mb-1"
:src="event.organizer_actor.avatarUrl"
>
</v-avatar>
</router-link> -->
<!-- <span v-if="event.organizerActor">Organisé par {{ event.organizerActor.name ? event.organizerActor.name : event.organizerActor.preferredUsername }}</span> -->
</div>
<!-- <p><router-link :to="{ name: 'Account', params: {id: event.organizer.id} }"><span class="grey&#45;&#45;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-flex>
<!-- <v-flex md2>
<p v-if="actorIsOrganizer()">
Vous êtes organisateur de cet événement.
</p>
<div v-else>
<p v-if="actorIsParticipant()">
Vous avez annoncé aller à cet événement.
</p>
<p v-else>Vous y allez ?
<span class="text--darken-2 grey--text">{{ event.participants.length }} personnes y vont.</span>
</p>
</div>
<v-card-actions v-if="!actorIsOrganizer()">
<v-btn v-if="!actorIsParticipant()" @click="joinEvent" color="success"><v-icon>check</v-icon> Join</v-btn>
<v-btn v-if="actorIsParticipant()" @click="leaveEvent" color="error">Leave</v-btn>
</v-card-actions>
</v-flex> -->
</v-layout>
</v-container>
<v-divider></v-divider>
<v-container>
<v-layout row wrap>
<v-flex xs12 md4 order-md1>
<v-layout
column
fill-height
>
<v-list two-line>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">access_time</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{ event.begins_on | formatDate }}</v-list-tile-title>
<v-list-tile-sub-title>{{ event.ends_on | formatDate }}</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile @click="deleteEvent()" v-if="actorIsOrganizer()">
<v-list-tile-title>Delete</v-list-tile-title>
<v-divider inset></v-divider>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">place</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title><span v-if="event.address_type === 'physical'">
{{ event.physical_address.streetAddress }}
</span></v-list-tile-title>
<v-list-tile-sub-title>Mobile</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-menu>
</v-card-title>
</v-flex>
</v-layout>
</v-container>
</v-img>
<v-container grid-list-md>
<v-layout row wrap>
<v-flex md10>
<v-spacer></v-spacer>
<span class="subheading grey--text">{{ event.begins_on | formatDay }}</span>
<h1 class="display-1">{{ event.title }}</h1>
<div>
<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 ? event.organizer.display_name : event.organizer.username }}</span>
</div>
<!--<p><router-link :to="{ name: 'Account', params: {id: event.organizer.id} }"><span class="grey&#45;&#45;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-flex>
<v-flex md2>
<p v-if="actorIsOrganizer()">
Vous êtes organisateur de cet événement.
</p>
<div v-else>
<p v-if="actorIsParticipant()">
Vous avez annoncé aller à cet événement.
</p>
<p v-else>Vous y allez ?
<span class="text--darken-2 grey--text">{{ event.participants.length }} personnes y vont.</span>
</p>
</div>
<v-card-actions v-if="!actorIsOrganizer()">
<v-btn v-if="!actorIsParticipant()" @click="joinEvent" color="success"><v-icon>check</v-icon> Join</v-btn>
<v-btn v-if="actorIsParticipant()" @click="leaveEvent" color="error">Leave</v-btn>
</v-card-actions>
</v-flex>
</v-layout>
</v-container>
<v-divider></v-divider>
<v-container>
<v-layout row wrap>
<v-flex xs12 md4 order-md1>
<v-layout
column
fill-height
>
<v-list two-line>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">access_time</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{ event.begins_on | formatDate }}</v-list-tile-title>
<v-list-tile-sub-title>{{ event.ends_on | formatDate }}</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
<v-divider inset></v-divider>
<v-list-tile>
<v-list-tile-action>
<v-icon color="indigo">place</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title><span v-if="event.address_type === 'physical'">
{{ event.physical_address.streetAddress }}
</span></v-list-tile-title>
<v-list-tile-sub-title>Mobile</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-layout>
</v-flex>
<v-flex md8 xs12>
<p>
<h2>Details</h2>
<vue-markdown :source="event.description" v-if="event.description" :toc-first-level="3" />
</p>
<v-subheader>Participants</v-subheader>
<v-flex md2 v-for="actor in event.participants" :key="actor.uuid">
<router-link :to="{name: 'Account', params: { name: actor.username }}">
<v-avatar size="75px">
<img v-if="!actor.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="actor.avatar"
>
</v-avatar>
</router-link>
<span>{{ actor.username }}</span>
</v-flex>
</v-flex>
<span v-if="event.participants.length === 0">No participants yet.</span>
</v-layout>
</v-container>
</v-card>
</v-layout>
</v-flex>
<v-flex md8 xs12>
<p>
<h2>Details</h2>
<vue-markdown :source="event.description" v-if="event.description" :toc-first-level="3"></vue-markdown>
</p>
<v-subheader>Participants</v-subheader>
<!-- <v-flex md2 v-for="participant in event.participants" :key="participant.actor.uuid">
<router-link :to="{name: 'Account', params: { name: participant.actor.preferredUsername }}">
<v-card>
<v-avatar size="75px">
<img v-if="!participant.actor.avatarUrl"
class="img-circle elevation-7 mb-1"
src="https://picsum.photos/125/125/"
>
<img v-else
class="img-circle elevation-7 mb-1"
:src="participant.actor.avatarUrl"
>
</v-avatar>
<v-card-title>
<span>{{ participant.actor.preferredUsername }}</span>
</v-card-title>
</v-card>
</router-link>
</v-flex> -->
</v-flex>
<span v-if="event.participants.length === 0">No participants yet.</span>
</v-layout>
</v-container>
</v-card>
</v-flex>
</v-layout>
</template>
<script>
import eventFetch from '@/api/eventFetch';
import VueMarkdown from 'vue-markdown';
import VueMarkdown from 'vue-markdown';
import { FETCH_EVENT } from '@/graphql/event';
import { LOGGED_ACTOR } from '@/graphql/actor';
export default {
name: 'Home',
components: {
VueMarkdown,
},
data() {
return {
loading: true,
error: false,
event: {
name: '',
slug: '',
title: '',
export default {
name: 'Home',
components: {
VueMarkdown,
},
data() {
return {
event: {
name: '',
slug: '',
title: '',
uuid: this.uuid,
description: '',
organizer: {
id: null,
username: null,
},
participants: [],
},
};
},
apollo: {
event: {
query: FETCH_EVENT,
variables() {
return {
uuid: this.uuid,
description: '',
organizer: {
id: null,
username: null,
},
participants: [],
},
};
},
methods: {
deleteEvent() {
const router = this.$router;
eventFetch(`/events/${this.uuid}`, this.$store, { method: 'DELETE' })
.then(() => router.push({'name': 'EventList'}));
};
},
fetchData() {
eventFetch(`/events/${this.uuid}`, this.$store)
.then(response => response.json())
.then((data) => {
this.loading = false;
this.event = data.data;
console.log('event', this.event);
}).catch((res) => {
Promise.resolve(res).then((data) => {
console.log(data);
this.error = true;
this.loading = false;
});
},
// loggedActor: {
// query: LOGGED_ACTOR,
// }
},
methods: {
deleteEvent() {
const router = this.$router;
eventFetch(`/events/${this.uuid}`, this.$store, { method: 'DELETE' })
.then(() => router.push({ name: 'EventList' }));
},
joinEvent() {
eventFetch(`/events/${this.uuid}/join`, this.$store, { method: 'POST' })
.then(response => response.json())
.then((data) => {
console.log(data);
});
},
joinEvent() {
eventFetch(`/events/${this.uuid}/join`, this.$store, { method: 'POST' })
.then(response => response.json())
.then((data) => {
console.log(data);
});
},
leaveEvent() {
eventFetch(`/events/${this.uuid}/leave`, this.$store)
.then(response => response.json())
.then((data) => {
console.log(data);
});
},
downloadIcsEvent() {
eventFetch(`/events/${this.uuid}/ics`, this.$store, {responseType: 'arraybuffer'})
.then((response) => response.text())
.then(response => {
const blob = new Blob([response],{type: 'text/calendar'});
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = `${this.event.title}.ics`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
},
actorIsParticipant() {
return this.$store.state.actor && this.event.participants.map(participant => participant.id).includes(this.$store.state.actor.id) || this.actorIsOrganizer();
},
actorIsOrganizer() {
return this.$store.state.actor && this.$store.state.actor.id === this.event.organizer.id;
}
},
props: {
uuid: {
type: String,
required: true,
},
leaveEvent() {
eventFetch(`/events/${this.uuid}/leave`, this.$store)
.then(response => response.json())
.then((data) => {
console.log(data);
});
},
created() {
this.fetchData();
downloadIcsEvent() {
eventFetch(`/events/${this.uuid}/ics`, this.$store, { responseType: 'arraybuffer' })
.then(response => response.text())
.then((response) => {
const blob = new Blob([response], { type: 'text/calendar' });
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = `${this.event.title}.ics`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
},
};
// actorIsParticipant() {
// return this.loggedActor && this.event.participants.map(participant => participant.actor.preferredUsername).includes(this.loggedActor.preferredUsername) || this.actorIsOrganizer();
// },
// actorIsOrganizer() {
// return this.loggedActor && this.loggedActor.preferredUsername === this.event.organizer.preferredUsername;
// },
},
props: {
uuid: {
type: String,
required: true,
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->

View File

@@ -54,85 +54,84 @@
</template>
<script>
import ngeohash from 'ngeohash';
import VueMarkdown from 'vue-markdown';
import eventFetch from '@/api/eventFetch';
import VCardTitle from "vuetify/es5/components/VCard/VCardTitle";
import ngeohash from 'ngeohash';
import VueMarkdown from 'vue-markdown';
import VCardTitle from 'vuetify/es5/components/VCard/VCardTitle';
export default {
name: 'EventList',
components: {
VCardTitle,
VueMarkdown
},
data() {
return {
events: [],
loading: true,
locationChip: false,
locationText: '',
};
},
props: ['location'],
created() {
this.fetchData(this.$router.currentRoute.params.location);
},
watch: {
locationChip(val) {
if (val === false) {
this.$router.push({name: 'EventList'});
}
export default {
name: 'EventList',
components: {
VCardTitle,
VueMarkdown,
},
data() {
return {
events: [],
loading: true,
locationChip: false,
locationText: '',
};
},
props: ['location'],
created() {
this.fetchData(this.$router.currentRoute.params.location);
},
watch: {
locationChip(val) {
if (val === false) {
this.$router.push({ name: 'EventList' });
}
},
beforeRouteUpdate(to, from, next) {
this.fetchData(to.params.location);
next();
},
beforeRouteUpdate(to, from, next) {
this.fetchData(to.params.location);
next();
},
methods: {
geocode(lat, lon) {
console.log({ lat, lon });
console.log(ngeohash.encode(lat, lon, 10));
return ngeohash.encode(lat, lon, 10);
},
methods: {
geocode(lat, lon) {
console.log({lat, lon});
console.log(ngeohash.encode(lat, lon, 10));
return ngeohash.encode(lat, lon, 10);
},
fetchData(location) {
let queryString = '/events';
if (location) {
queryString += ('?geohash=' + location);
const { latitude, longitude } = ngeohash.decode(location);
this.locationText = latitude.toString() + ' : ' + longitude.toString();
}
this.locationChip = true;
eventFetch(queryString, this.$store)
.then(response => response.json())
.then((response) => {
this.loading = false;
this.events = response.data;
console.log(this.events);
});
},
deleteEvent(event) {
const router = this.$router;
eventFetch(`/events/${event.uuid}`, this.$store, {'method': 'DELETE'})
.then(() => router.push('/events'));
},
viewEvent(event) {
this.$router.push({ name: 'Event', params: { uuid: event.uuid } })
},
downloadIcsEvent(event) {
eventFetch(`/events/${event.uuid}/ics`, this.$store, {responseType: 'arraybuffer'})
.then((response) => response.text())
.then(response => {
const blob = new Blob([response],{type: 'text/calendar'});
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = `${event.title}.ics`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
},
fetchData(location) {
let queryString = '/events';
if (location) {
queryString += (`?geohash=${location}`);
const { latitude, longitude } = ngeohash.decode(location);
this.locationText = `${latitude.toString()} : ${longitude.toString()}`;
}
this.locationChip = true;
eventFetch(queryString, this.$store)
.then(response => response.json())
.then((response) => {
this.loading = false;
this.events = response.data;
console.log(this.events);
});
},
};
deleteEvent(event) {
const router = this.$router;
eventFetch(`/events/${event.uuid}`, this.$store, { method: 'DELETE' })
.then(() => router.push('/events'));
},
viewEvent(event) {
this.$router.push({ name: 'Event', params: { uuid: event.uuid } });
},
downloadIcsEvent(event) {
eventFetch(`/events/${event.uuid}/ics`, this.$store, { responseType: 'arraybuffer' })
.then(response => response.text())
.then((response) => {
const blob = new Blob([response], { type: 'text/calendar' });
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = `${event.title}.ics`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->

View File

@@ -65,66 +65,65 @@
</template>
<script>
import eventFetch from '@/api/eventFetch';
import VueMarkdown from 'vue-markdown';
import VuetifyGoogleAutocomplete from 'vuetify-google-autocomplete';
import VueMarkdown from 'vue-markdown';
import VuetifyGoogleAutocomplete from 'vuetify-google-autocomplete';
export default {
name: 'create-group',
export default {
name: 'create-group',
components: {
VueMarkdown,
VuetifyGoogleAutocomplete,
components: {
VueMarkdown,
VuetifyGoogleAutocomplete,
},
data() {
return {
e1: 0,
group: {
preferred_username: '',
name: '',
summary: '',
// category: null,
},
categories: [],
};
},
mounted() {
this.fetchCategories();
},
methods: {
create() {
// this.group.organizer = "/accounts/" + this.$store.state.user.id;
eventFetch('/groups', this.$store, { method: 'POST', body: JSON.stringify({ group: this.group }) })
.then(response => response.json())
.then((data) => {
this.loading = false;
this.$router.push({ path: 'Group', params: { id: data.id } });
});
},
data() {
return {
e1: 0,
group: {
preferred_username: '',
name: '',
summary: '',
// category: null,
fetchCategories() {
eventFetch('/categories', this.$store)
.then(response => response.json())
.then((data) => {
this.loading = false;
this.categories = data.data;
});
},
getAddressData(addressData) {
this.group.address = {
geo: {
latitude: addressData.latitude,
longitude: addressData.longitude,
},
categories: [],
addressCountry: addressData.country,
addressLocality: addressData.city,
addressRegion: addressData.administrative_area_level_1,
postalCode: addressData.postal_code,
streetAddress: `${addressData.street_number} ${addressData.route}`,
};
},
mounted() {
this.fetchCategories();
},
methods: {
create() {
// this.group.organizer = "/accounts/" + this.$store.state.user.id;
eventFetch('/groups', this.$store, { method: 'POST', body: JSON.stringify({group: this.group}) })
.then(response => response.json())
.then((data) => {
this.loading = false;
this.$router.push({ path: 'Group', params: { id: data.id } });
});
},
fetchCategories() {
eventFetch('/categories', this.$store)
.then(response => response.json())
.then((data) => {
this.loading = false;
this.categories = data.data;
});
},
getAddressData: function (addressData) {
this.group.address = {
geo: {
latitude: addressData.latitude,
longitude: addressData.longitude,
},
addressCountry: addressData.country,
addressLocality: addressData.city,
addressRegion: addressData.administrative_area_level_1,
postalCode: addressData.postal_code,
streetAddress: `${addressData.street_number} ${addressData.route}`,
};
},
},
};
},
};
</script>
<style>

View File

@@ -202,39 +202,37 @@
</template>
<script>
import eventFetch from '@/api/eventFetch';
export default {
name: 'Group',
data() {
return {
group: null,
loading: true,
}
},
props: {
name: {
type: String,
required: true,
}
},
created() {
this.fetchData();
},
watch: {
// call again the method if the route changes
'$route': 'fetchData'
},
methods: {
fetchData() {
eventFetch(`/actors/${this.name}`, this.$store)
.then(response => response.json())
.then((response) => {
this.group = response.data;
this.loading = false;
console.log(this.group);
})
}
}
}
export default {
name: 'Group',
data() {
return {
group: null,
loading: true,
};
},
props: {
name: {
type: String,
required: true,
},
},
created() {
this.fetchData();
},
watch: {
// call again the method if the route changes
$route: 'fetchData',
},
methods: {
fetchData() {
eventFetch(`/actors/${this.name}`, this.$store)
.then(response => response.json())
.then((response) => {
this.group = response.data;
this.loading = false;
console.log(this.group);
});
},
},
};
</script>

View File

@@ -38,49 +38,47 @@
</template>
<script>
import eventFetch from '@/api/eventFetch';
export default {
name: 'GroupList',
data() {
return {
groups: [],
loading: true,
};
export default {
name: 'GroupList',
data() {
return {
groups: [],
loading: true,
};
},
created() {
this.fetchData();
},
methods: {
username_with_domain(actor) {
return actor.username + (actor.domain === null ? '' : `@${actor.domain}`);
},
created() {
this.fetchData();
fetchData() {
eventFetch('/groups', this.$store)
.then(response => response.json())
.then((data) => {
console.log(data);
this.loading = false;
this.groups = data.data;
});
},
methods: {
username_with_domain(actor) {
return actor.username + (actor.domain === null ? '' : `@${actor.domain}`)
},
fetchData() {
eventFetch('/groups', this.$store)
.then(response => response.json())
.then((data) => {
console.log(data);
this.loading = false;
this.groups = data.data;
});
},
deleteGroup(group) {
const router = this.$router;
eventFetch(`/groups/${this.username_with_domain(group)}`, this.$store, {'method': 'DELETE'})
.then(response => response.json())
.then(() => router.push('/groups'));
},
viewActor(actor) {
this.$router.push({ name: 'Group', params: { name: this.username_with_domain(actor) } })
},
joinGroup(group) {
const router = this.$router;
eventFetch(`/groups/${this.username_with_domain(group)}/join`, this.$store, { method: 'POST' })
.then(response => response.json())
.then(() => router.push({ name: 'Group', params: { name: this.username_with_domain(group) } }));
}
deleteGroup(group) {
const router = this.$router;
eventFetch(`/groups/${this.username_with_domain(group)}`, this.$store, { method: 'DELETE' })
.then(response => response.json())
.then(() => router.push('/groups'));
},
};
viewActor(actor) {
this.$router.push({ name: 'Group', params: { name: this.username_with_domain(actor) } });
},
joinGroup(group) {
const router = this.$router;
eventFetch(`/groups/${this.username_with_domain(group)}/join`, this.$store, { method: 'POST' })
.then(response => response.json())
.then(() => router.push({ name: 'Group', params: { name: this.username_with_domain(group) } }));
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->

View File

@@ -5,14 +5,14 @@
src="https://picsum.photos/1200/900"
dark
height="300"
v-if="$store.state.user === false"
v-if="!user"
>
<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 Mobilizon</h2>
<v-btn :to="{ name: 'Register' }">{{ $t("home.register") }}</v-btn>
<v-btn :to="{ name: 'Register' }"><translate>Register</translate></v-btn>
</v-flex>
</v-layout>
</v-container>
@@ -21,7 +21,7 @@
<v-flex xs12 sm8 offset-sm2>
<v-layout row wrap>
<v-flex xs12 sm6>
<h1>Welcome back {{ $store.state.actor.username }}</h1>
<h1><translate :translate-params="{username: actor.preferredUsername}">Welcome back %{username}</translate></h1>
</v-flex>
<v-flex xs12 sm6>
<v-layout align-center>
@@ -33,11 +33,14 @@
</v-layout>
</v-flex>
</v-layout>
<div v-if="$apollo.loading">
Still loading
</div>
<v-card v-if="events.length > 0">
<v-layout row wrap>
<v-flex md4 v-for="event in events" :key="event.uuid">
<v-card :to="{ name: 'Event', params:{ uuid: event.uuid } }">
<v-card-media v-if="!event.image"
<v-img v-if="!event.image"
class="white--text"
height="200px"
src="https://picsum.photos/g/400/200/"
@@ -49,26 +52,26 @@
</v-flex>
</v-layout>
</v-container>
</v-card-media>
</v-img>
<v-card-title primary-title>
<div>
<span class="grey--text">{{ event.begins_on | formatDay }}</span><br>
<router-link :to="{name: 'Account', params: { name: event.organizer.username } }">
<router-link :to="{name: 'Account', params: { name: event.organizerActor.preferredUsername } }">
<v-avatar size="25px">
<img class="img-circle elevation-7 mb-1"
:src="event.organizer.avatar"
:src="event.organizerActor.avatarUrl"
>
</v-avatar>
</router-link>
<span v-if="event.organizer">Organisé par {{ event.organizer.display_name ? event.organizer.display_name : event.organizer.username }}</span>
<span v-if="event.organizerActor">Organisé par {{ event.organizerActor.name ? event.organizerActor.name : event.organizerActor.preferredUsername }}</span>
</div>
</v-card-title>
</v-card>
</v-flex>
</v-layout>
</v-card>
<v-alert v-else :value="true" type="info">
No events found nearby {{ ipLocation() }}
<v-alert v-else :value="true" type="error">
No events found
</v-alert>
</v-flex>
</v-layout>
@@ -76,83 +79,75 @@
</template>
<script>
import ngeohash from 'ngeohash';
import eventFetch from "../api/eventFetch";
import {AUTH_USER_ACTOR, AUTH_USER_ID} from '@/constants';
import { FETCH_EVENTS } from '@/graphql/event';
export default {
name: 'Home',
data() {
return {
gradient: 'to top right, rgba(63,81,181, .7), rgba(25,32,72, .7)',
user: null,
searchTerm: null,
location_field: {
loading: false,
search: null,
},
locations: [],
events: [],
city: {name: null},
country: {name: null},
locations: [],
city: { name: null },
country: { name: null },
actor: JSON.parse(localStorage.getItem(AUTH_USER_ACTOR)),
user: localStorage.getItem(AUTH_USER_ID),
};
},
created() {
this.fetchData();
apollo: {
events: {
query: FETCH_EVENTS,
},
},
computed: {
displayed_name() {
return this.$store.state.actor.display_name === null ? this.$store.state.actor.username : this.$store.state.actor.display_name
return this.actor.name === null ? this.actor.preferredUsername : this.actor.name;
},
},
methods: {
fetchLocations() {
eventFetch('/locations', this.$store)
.then((response) => (response.json()))
.then(response => (response.json()))
.then((response) => {
this.locations = response;
});
},
fetchData() {
eventFetch('/events', this.$store)
.then(response => response.json())
.then((response) => {
this.loading = false;
this.events = response.data;
this.city = response.city;
this.country = response.country;
});
},
geoLocalize() {
const router = this.$router;
if (sessionStorage.getItem('City')) {
router.push({name: 'EventList', params: {location: localStorage.getItem('City')}})
router.push({ name: 'EventList', params: { location: localStorage.getItem('City') } });
} else {
navigator.geolocation.getCurrentPosition((pos) => {
const crd = pos.coords;
const geohash = ngeohash.encode(crd.latitude, crd.longitude, 11);
sessionStorage.setItem('City', geohash);
router.push({name: 'EventList', params: {location: geohash}});
}, (err) => console.warn(`ERROR(${err.code}): ${err.message}`), {
router.push({ name: 'EventList', params: { location: geohash } });
}, err => console.warn(`ERROR(${err.code}): ${err.message}`), {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
maximumAge: 0,
});
}
},
getAddressData: function (addressData) {
getAddressData(addressData) {
const geohash = ngeohash.encode(addressData.latitude, addressData.longitude, 11);
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 } })
this.$router.push({ name: 'Event', params: { uuid: event.uuid } });
},
ipLocation() {
return this.city.name ? this.city.name : this.country.name;
}
},
},
};
</script>

View File

@@ -26,27 +26,27 @@
<script>
export default {
data() {
return {
description: 'Paris, France',
center: { lat: 48.85, lng: 2.35 },
markers: [],
export default {
data() {
return {
description: 'Paris, France',
center: { lat: 48.85, lng: 2.35 },
markers: [],
};
},
props: ['address'],
methods: {
setPlace(place) {
this.center = {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
};
this.markers = [{
position: { lat: this.center.lat, lng: this.center.lng },
}];
this.$emit('input', place.formatted_address);
},
props: ['address'],
methods: {
setPlace(place) {
this.center = {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
};
this.markers = [{
position: { lat: this.center.lat, lng: this.center.lng },
}];
this.$emit('input', place.formatted_address);
},
},
};
},
};
</script>

View File

@@ -12,33 +12,36 @@
</router-link>
</v-toolbar-title>
<v-autocomplete
:loading="searchElement.loading"
:loading="$apollo.loading"
flat
solo-inverted
prepend-icon="search"
label="Search"
:label="$gettext('Search')"
required
item-text="displayedText"
item-text="label"
class="hidden-sm-and-down"
:items="searchElement.items"
:search-input.sync="search"
v-model="searchSelect"
:items="items"
:search-input.sync="searchText"
v-model="model"
return-object
>
<template slot="item" slot-scope="data">
<template v-if="typeof data.item !== 'object'">
<v-list-tile-content v-text="data.item"></v-list-tile-content>
</template>
<template v-else>
<!-- <div>{{ data }}</div> -->
<v-list-tile v-if="data.item.__typename === 'Event'">
<v-list-tile-avatar>
<img :src="data.item.avatar" v-if="data.item.avatar">
<v-icon v-else>event</v-icon>
<v-icon>event</v-icon>
</v-list-tile-avatar>
<v-list-tile-content v-text="data.item.label"></v-list-tile-content>
</v-list-tile>
<v-list-tile v-else-if="data.item.__typename === 'Actor'">
<v-list-tile-avatar>
<img :src="data.item.avatarUrl" v-if="data.item.avatarUrl">
<v-icon v-else>account_circle</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title v-html="username_with_domain(data.item)"></v-list-tile-title>
<v-list-tile-sub-title v-html="data.item.type"></v-list-tile-sub-title>
</v-list-tile-content>
</template>
</v-list-tile>
</template>
</v-autocomplete>
<v-spacer></v-spacer>
@@ -47,7 +50,7 @@
:close-on-content-click="false"
:nudge-width="200"
v-model="notificationMenu"
v-if="getUser()"
v-if="user"
>
<v-btn icon slot="activator">
<v-badge left color="red">
@@ -70,115 +73,98 @@
</v-list>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn flat @click="notificationMenu = false">Close</v-btn>
<v-btn color="primary" flat @click="notificationMenu = false">Save</v-btn>
<v-btn flat @click="notificationMenu = false"><translate>Close</translate></v-btn>
<v-btn color="primary" flat @click="notificationMenu = false"><translate>Save</translate></v-btn>
</v-card-actions>
</v-card>
</v-menu>
<v-btn v-if="!$store.state.user" :to="{ name: 'Login' }">Se connecter</v-btn>
<v-btn v-if="!user" :to="{ name: 'Login' }"><translate>Login</translate></v-btn>
</v-toolbar>
</template>
<script>
import eventFetch from '@/api/eventFetch';
import {AUTH_USER_ACTOR, AUTH_USER_ID} from '@/constants';
import {SEARCH} from '@/graphql/search';
export default {
name: 'NavBar',
props: {
toggleDrawer: {
type: Function,
required: true,
export default {
name: 'NavBar',
props: {
toggleDrawer: {
type: Function,
required: true,
},
},
data() {
return {
notificationMenu: false,
notifications: [
{ header: 'Coucou' },
{ title: "T'as une notification", subtitle: 'Et elle est cool' },
],
model: null,
search: [],
searchText: null,
searchSelect: null,
actor: localStorage.getItem(AUTH_USER_ACTOR),
user: localStorage.getItem(AUTH_USER_ID),
};
},
apollo: {
search: {
query: SEARCH,
variables() {
return {
searchText: this.searchText,
};
},
skip() {
return !this.searchText;
},
},
data() {
return {
notificationMenu: false,
notifications: [
{header: 'Coucou'},
{title: "T'as une notification", subtitle: 'Et elle est cool'},
],
searchElement: {
loading: false,
items: [],
},
search: null,
searchSelect: null,
};
},
watch: {
search (val) {
val && this.querySelections(val)
},
searchSelect(val) {
console.log('searchSelect', val);
if (val.type === 'Event') {
this.$router.push({name: 'Event', params: { uuid: val.uuid }});
} else if (val.type === 'Locality') {
this.$router.push({name: 'EventList', params: {location: val.geohash}});
} else {
this.$router.push({name: 'Account', params: { name : this.username_with_domain(val) }});
}
},
watch: {
model(val) {
switch(val.__typename) {
case 'Event':
this.$router.push({ name: 'Event', params: { uuid: val.uuid } });
break;
case 'Actor':
this.$router.push({ name: 'Account', params: { name: this.username_with_domain(val) } });
break;
}
},
computed: {
displayed_name: function() {
console.log('displayed name', this.$store.state.actor);
if (this.$store.state.actor) {
return this.$store.state.actor.display_name === null ? this.$store.state.actor.username : this.$store.state.actor.display_name;
},
computed: {
items() {
return this.search.map(searchEntry => {
switch (searchEntry.__typename) {
case 'Actor':
searchEntry.label = searchEntry.preferredUsername;
break;
case 'Event':
searchEntry.label = searchEntry.title;
break;
}
},
return searchEntry;
});
},
methods: {
username_with_domain(actor) {
if (actor.type !== 'Event') {
return actor.username + (actor.domain === null ? '' : `@${actor.domain}`)
}
return actor.title;
},
getUser() {
return this.$store.state.user === undefined ? false : this.$store.state.user;
},
querySelections(searchTerm) {
this.searchElement.loading = true;
eventFetch(`/search/${searchTerm}`, this.$store)
.then(response => response.json())
.then((results) => {
console.log('results');
console.log(results);
const accountResults = results.data.actors.map((result) => {
if (result.domain) {
result.displayedText = `${result.username}@${result.domain}`;
} else {
result.displayedText = result.username;
}
return result;
});
const eventsResults = results.data.events.map((result) => {
result.displayedText = result.title;
return result;
});
// const cities = new Set();
// const placeResults = results.places.map((result) => {
// result.displayedText = result.addressLocality;
// return result;
// }).filter((result) => {
// if (cities.has(result.addressLocality)) {
// return false;
// }
// cities.add(result.addressLocality);
// return true;
// });
this.searchElement.items = accountResults.concat(eventsResults);
this.searchElement.loading = false;
});
displayed_name() {
console.log('displayed name', this.actor);
if (this.actor) {
return this.actor.display_name === null ? this.actor.username : this.actor.display_name;
}
}
}
},
},
methods: {
username_with_domain(actor) {
return actor.preferredUsername + (actor.domain === undefined ? '' : `@${actor.domain}`);
},
},
};
</script>
<style>
nav.v-toolbar .v-input__slot {
margin-bottom: 0;
}
</style>
</style>