Add some identities UI

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2018-07-11 13:46:19 +02:00
parent 3566ece9fa
commit 01328d183e
5 changed files with 186 additions and 29 deletions

View File

@ -10,37 +10,46 @@
> >
<v-list dense> <v-list dense>
<v-list-group <v-list-group
value="false" value="false"
> >
<v-list-tile avatar v-if="$store.state.actor" slot="activator"> <v-list-tile avatar v-if="$store.state.actor" slot="activator">
<v-list-tile-avatar> <v-list-tile-avatar>
<img v-if="!$store.state.actor.avatar" <img v-if="!$store.state.actor.avatar"
class="img-circle elevation-7 mb-1" class="img-circle elevation-7 mb-1"
src="https://picsum.photos/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="$store.state.actor.avatar" :src="$store.state.actor.avatar"
> >
</v-list-tile-avatar> </v-list-tile-avatar>
<v-list-tile-content @click="$router.push({name: 'Account', params: { name: $store.state.actor.username }})"> <v-list-tile-content @click="$router.push({name: 'Account', params: { name: $store.state.actor.username }})">
<v-list-tile-title>{{ this.displayed_name }}</v-list-tile-title> <v-list-tile-title>{{ this.displayed_name }}</v-list-tile-title>
</v-list-tile-content> </v-list-tile-content>
</v-list-tile> </v-list-tile>
<v-list-tile avatar v-if="$store.state.actor"> <v-list-tile avatar v-if="$store.state.actor">
<v-list-tile-avatar> <v-list-tile-avatar>
<img <img
class="img-circle elevation-7 mb-1" class="img-circle elevation-7 mb-1"
src="https://picsum.photos/125/125/" src="https://picsum.photos/125/125/"
> >
</v-list-tile-avatar> </v-list-tile-avatar>
<v-list-tile-content> <v-list-tile-content>
<v-list-tile-title>Autre identité</v-list-tile-title> <v-list-tile-title>Autre identité</v-list-tile-title>
</v-list-tile-content> </v-list-tile-content>
</v-list-tile> </v-list-tile>
<v-list-tile @click="$router.push({ name: 'Identities' })">
<v-list-tile-action>
<v-icon>group</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>Identities</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list-group> </v-list-group>
<template v-for="(item, i) in items" v-if="showMenuItem(item.role)"> <template v-for="(item, i) in items" v-if="showMenuItem(item.role)">
<v-layout <v-layout

View File

@ -0,0 +1,132 @@
<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-toolbar dark color="primary">
<v-toolbar-title>Identities</v-toolbar-title>
</v-toolbar>
<v-card-text>
<v-list two-line>
<v-list-tile
v-for="actor in actors"
:key="actor.id"
avatar
@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-list-tile-action>
<v-list-tile-content>
<v-list-tile-title v-text="actor.username"></v-list-tile-title>
<v-list-tile-sub-title v-if="actor.display_name" v-text="actor.display_name"></v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-avatar>
<img :src="actor.avatar">
</v-list-tile-avatar>
</v-list-tile>
</v-list>
<v-divider v-if="showForm"></v-divider>
<v-form v-if="showForm">
<v-text-field
label="Username"
required
type="text"
v-model="newActor.preferred_username"
:rules="[rules.required]"
:error="this.state.username.status"
:error-messages="this.state.username.msg"
:suffix="this.host()"
hint="You will be able to create more identities once registered"
persistent-hint
>
</v-text-field>
<v-textarea
name="input-7-1"
label="Profile description"
hint="Will be displayed publicly on your profile"
></v-textarea>
</v-form>
<v-btn
color="pink"
dark
absolute
bottom
right
fab
@click="toggleForm()"
>
<v-icon>{{ showForm ? 'check' : 'add' }}</v-icon>
</v-btn>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</template>
<script>
import eventFetch from "@/api/eventFetch";
import auth from "@/auth";
export default {
name: "Identities",
data() {
return {
actors: [],
newActor: {
preferred_username: "",
summary: ""
},
loading: true,
showForm: false,
rules: {
required: value => !!value || "Required."
},
state: {
username: {
status: false,
msg: []
}
}
};
},
created() {
this.fetchData();
},
methods: {
fetchData() {
eventFetch(`/user`, this.$store)
.then(response => response.json())
.then(response => {
this.actors = response.data.actors;
this.loading = false;
});
},
sendData() {
this.loading = true;
this.showForm = false;
eventFetch(`/actors`, this.$store, {
method: "POST",
body: JSON.stringify({ actor: this.newActor })
})
.then(response => response.json())
.then(response => {
this.actors.push(response.data);
this.loading = false;
});
},
toggleForm() {
if (this.showForm === true) {
this.sendData();
} else {
this.showForm = true;
}
},
host() {
return `@${window.location.host}`;
}
}
};
</script>

View File

@ -38,7 +38,7 @@ Vue.i18n.set(language);
Vue.i18n.fallback('en'); Vue.i18n.fallback('en');
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiredAuth)) { if (to.matched.some(record => record.meta.requiredAuth) && !store.state.user) {
next({ next({
name: 'Login', name: 'Login',
query: { redirect: to.fullPath }, query: { redirect: to.fullPath },

View File

@ -18,6 +18,7 @@ import Account from '@/components/Account/Account';
import CreateGroup from '@/components/Group/Create'; import CreateGroup from '@/components/Group/Create';
import Group from '@/components/Group/Group'; import Group from '@/components/Group/Group';
import GroupList from '@/components/Group/GroupList'; import GroupList from '@/components/Group/GroupList';
import Identities from '../components/Account/Identities.vue';
Vue.use(Router); Vue.use(Router);
@ -110,6 +111,12 @@ const router = new Router({
props: true, props: true,
meta: { requiredAuth: false }, meta: { requiredAuth: false },
}, },
{
path: '/identities',
name: 'Identities',
component: Identities,
meta: { requiredAuth: true },
},
{ {
path: '/groups', path: '/groups',
name: 'GroupList', name: 'GroupList',

View File

@ -18,6 +18,7 @@ defmodule EventosWeb.ActorController do
def create(conn, %{"actor" => actor_params}) do def create(conn, %{"actor" => actor_params}) do
with %User{} = user <- Guardian.Plug.current_resource(conn), with %User{} = user <- Guardian.Plug.current_resource(conn),
actor_params <- Map.put(actor_params, "user_id", user.id), actor_params <- Map.put(actor_params, "user_id", user.id),
actor_params <- Map.put(actor_params, "keys", keys_for_account()),
{:ok, %Actor{} = actor} <- Actors.create_actor(actor_params) do {:ok, %Actor{} = actor} <- Actors.create_actor(actor_params) do
conn conn
|> put_status(:created) |> put_status(:created)
@ -26,6 +27,14 @@ defmodule EventosWeb.ActorController do
end end
end end
defp keys_for_account() do
key = :public_key.generate_key({:rsa, 2048, 65_537})
entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
[entry]
|> :public_key.pem_encode()
|> String.trim_trailing()
end
def show(conn, %{"name" => name}) do def show(conn, %{"name" => name}) do
actor = Actors.get_actor_by_name_with_everything(name) actor = Actors.get_actor_by_name_with_everything(name)
render(conn, "show.json", actor: actor) render(conn, "show.json", actor: actor)