add profile editor
This commit is contained in:
parent
d4a6470141
commit
0172f0ce8a
6 changed files with 204 additions and 9 deletions
|
@ -2213,6 +2213,7 @@ sub startup {
|
|||
|
||||
$authed_r->get('/account')->to('account#account');
|
||||
$authed_r->get('/account/privacy')->to('account#privacy');
|
||||
$authed_r->get('/account/profile')->to('account#profile');
|
||||
$authed_r->get('/account/hooks')->to('account#webhook');
|
||||
$authed_r->get('/account/traewelling')->to('traewelling#settings');
|
||||
$authed_r->get('/account/insight')->to('account#insight');
|
||||
|
@ -2239,6 +2240,7 @@ sub startup {
|
|||
$authed_r->get('/s/*station')->to('traveling#station');
|
||||
$authed_r->get('/confirm_mail/:token')->to('account#confirm_mail');
|
||||
$authed_r->post('/account/privacy')->to('account#privacy');
|
||||
$authed_r->post('/account/profile')->to('account#profile');
|
||||
$authed_r->post('/account/hooks')->to('account#webhook');
|
||||
$authed_r->post('/account/traewelling')->to('traewelling#settings');
|
||||
$authed_r->post('/account/insight')->to('account#insight');
|
||||
|
|
|
@ -7,6 +7,8 @@ use Mojo::Base 'Mojolicious::Controller';
|
|||
|
||||
use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64);
|
||||
use JSON;
|
||||
use Mojo::Util qw(xml_escape);
|
||||
use Text::Markdown;
|
||||
use UUID::Tiny qw(:std);
|
||||
|
||||
my %visibility_itoa = (
|
||||
|
@ -499,6 +501,72 @@ sub privacy {
|
|||
}
|
||||
}
|
||||
|
||||
sub profile {
|
||||
my ($self) = @_;
|
||||
my $user = $self->current_user;
|
||||
|
||||
if ( $self->param('action') and $self->param('action') eq 'save' ) {
|
||||
if ( $self->validation->csrf_protect->has_error('csrf_token') ) {
|
||||
$self->render(
|
||||
'edit_profile',
|
||||
invalid => 'csrf',
|
||||
);
|
||||
return;
|
||||
}
|
||||
my $md = Text::Markdown->new;
|
||||
my $bio = $self->param('bio');
|
||||
|
||||
if ( length($bio) > 2000 ) {
|
||||
$bio = substr( $bio, 0, 2000 ) . '…';
|
||||
}
|
||||
|
||||
my $profile = {
|
||||
bio => {
|
||||
markdown => $bio,
|
||||
html => $md->markdown( xml_escape($bio) ),
|
||||
},
|
||||
metadata => [],
|
||||
};
|
||||
for my $i ( 0 .. 20 ) {
|
||||
my $key = $self->param("key_$i");
|
||||
my $value = $self->param("value_$i");
|
||||
if ($key) {
|
||||
if ( length($value) > 500 ) {
|
||||
$value = substr( $value, 0, 500 ) . '…';
|
||||
}
|
||||
my $html_value
|
||||
= ( $value
|
||||
=~ s{ \[ ([^]]+) \]\( ([^)]+) \) }{'<a href="' . xml_escape($2) . '">' . xml_escape($1) .'</a>' }egrx
|
||||
);
|
||||
$profile->{metadata}[$i] = {
|
||||
key => $key,
|
||||
value => {
|
||||
markdown => $value,
|
||||
html => $html_value,
|
||||
},
|
||||
};
|
||||
}
|
||||
else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
$self->users->set_profile(
|
||||
uid => $user->{id},
|
||||
profile => $profile
|
||||
);
|
||||
$self->redirect_to( '/p/' . $user->{name} );
|
||||
}
|
||||
|
||||
my $profile = $self->users->get_profile( uid => $user->{id} );
|
||||
$self->param( bio => $profile->{bio}{markdown} );
|
||||
for my $i ( 0 .. $#{ $profile->{metadata} } ) {
|
||||
$self->param( "key_$i" => $profile->{metadata}[$i]{key} );
|
||||
$self->param( "value_$i" => $profile->{metadata}[$i]{value}{markdown} );
|
||||
}
|
||||
|
||||
$self->render( 'edit_profile', name => $user->{name} );
|
||||
}
|
||||
|
||||
sub insight {
|
||||
my ($self) = @_;
|
||||
|
||||
|
|
|
@ -70,6 +70,30 @@ sub profile {
|
|||
return;
|
||||
}
|
||||
|
||||
my $profile = $self->users->get_profile( uid => $user->{id} );
|
||||
|
||||
my $my_user;
|
||||
my $relation;
|
||||
my $inverse_relation;
|
||||
my $is_self;
|
||||
if ( $self->is_user_authenticated ) {
|
||||
$my_user = $self->current_user;
|
||||
if ( $my_user->{id} == $user->{id} ) {
|
||||
$is_self = 1;
|
||||
$my_user = undef;
|
||||
}
|
||||
else {
|
||||
$relation = $self->users->get_relation(
|
||||
subject => $my_user->{id},
|
||||
object => $user->{id}
|
||||
);
|
||||
$inverse_relation = $self->users->get_relation(
|
||||
subject => $user->{id},
|
||||
object => $my_user->{id}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
my $status = $self->get_user_status( $user->{id} );
|
||||
my $visibility;
|
||||
if ( $status->{checked_in} or $status->{arr_name} ) {
|
||||
|
@ -84,7 +108,12 @@ sub profile {
|
|||
and $self->status_token_ok($status) )
|
||||
or (
|
||||
$visibility eq 'travelynx'
|
||||
and ( $self->is_user_authenticated
|
||||
and ( $my_user
|
||||
or $self->status_token_ok($status) )
|
||||
)
|
||||
or (
|
||||
$visibility eq 'followers'
|
||||
and ( ( $relation and $relation eq 'follows' )
|
||||
or $self->status_token_ok($status) )
|
||||
)
|
||||
)
|
||||
|
@ -104,7 +133,7 @@ sub profile {
|
|||
my @journeys;
|
||||
|
||||
if ( $user->{past_visible} == 2
|
||||
or ( $user->{past_visible} == 1 and $self->is_user_authenticated ) )
|
||||
or ( $user->{past_visible} == 1 and $my_user ) )
|
||||
{
|
||||
|
||||
my %opt = (
|
||||
|
@ -122,7 +151,10 @@ sub profile {
|
|||
if (
|
||||
$user->{default_visibility_str} eq 'public'
|
||||
or ( $user->{default_visibility_str} eq 'travelynx'
|
||||
and $self->is_user_authenticated )
|
||||
and $my_user )
|
||||
or ( $user->{default_visibility_str} eq 'followers'
|
||||
and $relation
|
||||
and $relation eq 'follows' )
|
||||
)
|
||||
{
|
||||
$opt{with_default_visibility} = 1;
|
||||
|
@ -131,8 +163,13 @@ sub profile {
|
|||
$opt{with_default_visibility} = 0;
|
||||
}
|
||||
|
||||
if ( $self->is_user_authenticated ) {
|
||||
$opt{min_visibility} = 'travelynx';
|
||||
if ($my_user) {
|
||||
if ( $relation and $relation eq 'follows' ) {
|
||||
$opt{min_visibility} = 'followers';
|
||||
}
|
||||
else {
|
||||
$opt{min_visibility} = 'travelynx';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$opt{min_visibility} = 'public';
|
||||
|
@ -143,9 +180,12 @@ sub profile {
|
|||
|
||||
$self->render(
|
||||
'profile',
|
||||
name => $name,
|
||||
uid => $user->{id},
|
||||
public_level => $user->{public_level},
|
||||
name => $name,
|
||||
uid => $user->{id},
|
||||
bio => $profile->{bio}{html},
|
||||
metadata => $profile->{metadata},
|
||||
public_level => $user->{public_level},
|
||||
is_self => $is_self,
|
||||
journey => $status,
|
||||
journey_visibility => $visibility,
|
||||
journeys => [@journeys],
|
||||
|
|
|
@ -750,6 +750,30 @@ sub update_webhook_status {
|
|||
);
|
||||
}
|
||||
|
||||
sub set_profile {
|
||||
my ( $self, %opt ) = @_;
|
||||
|
||||
my $db = $opt{db} // $self->{pg}->db;
|
||||
my $uid = $opt{uid};
|
||||
my $profile = $opt{profile};
|
||||
|
||||
$db->update(
|
||||
'users',
|
||||
{ profile => JSON->new->encode($profile) },
|
||||
{ id => $uid }
|
||||
);
|
||||
}
|
||||
|
||||
sub get_profile {
|
||||
my ( $self, %opt ) = @_;
|
||||
|
||||
my $db = $opt{db} // $self->{pg}->db;
|
||||
my $uid = $opt{uid};
|
||||
|
||||
return $db->select( 'users', ['profile'], { id => $uid } )
|
||||
->expand->hash->{profile};
|
||||
}
|
||||
|
||||
sub get_relation {
|
||||
my ( $self, %opt ) = @_;
|
||||
|
||||
|
|
|
@ -73,7 +73,8 @@
|
|||
<th scope="row">Sichtbarkeit</th>
|
||||
<td>
|
||||
<a href="/account/privacy"><i class="material-icons">edit</i></a>
|
||||
<span><i class="material-icons"><%= visibility_icon($acc->{default_visibility_str}) %></i></span>
|
||||
<i class="material-icons"><%= visibility_icon($acc->{default_visibility_str}) %></i>
|
||||
• <a href="/p/<%= $acc->{name} %>">Öffentliches Profil</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
60
templates/edit_profile.html.ep
Normal file
60
templates/edit_profile.html.ep
Normal file
|
@ -0,0 +1,60 @@
|
|||
<div class="row">
|
||||
<div class="col s12">
|
||||
<h1>Profil bearbeiten</h1>
|
||||
</div>
|
||||
</div>
|
||||
%= form_for '/account/profile' => (method => 'POST') => begin
|
||||
%= csrf_field
|
||||
<div class="row">
|
||||
<div class="col s12">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<span class="card-title"><%= $name %></span>
|
||||
<p>
|
||||
Markdown möglich, maximal 2000 Zeichen.
|
||||
%= text_area 'bio', id => 'bio', class => 'materialize-textarea'
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a href="/p/<%= $name %>" class="waves-effect waves-light btn">
|
||||
Abbrechen
|
||||
</a>
|
||||
<button class="btn waves-effect waves-light right" type="submit" name="action" value="save">
|
||||
Speichern
|
||||
<i class="material-icons right">send</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col s12">
|
||||
Metadaten: Markdown-Links im Inhalt erlaubt, jeweils maximal 500 Zeichen
|
||||
</div>
|
||||
</div>
|
||||
% for my $i (0 .. 10) {
|
||||
<div class="row">
|
||||
<div class="input-field col l3 m12 s12">
|
||||
%= text_field "key_$i", id => "key_$i", maxlength => 50
|
||||
<label for="key_<%= $i %>">Attribut</label>
|
||||
</div>
|
||||
<div class="input-field col l9 m12 s12">
|
||||
%= text_field "value_$i", id => "value_$i", maxlength => 500
|
||||
<label for="value_<%= $i %>">Inhalt</label>
|
||||
</div>
|
||||
</div>
|
||||
% }
|
||||
<div class="row center-align">
|
||||
<div class="col s6">
|
||||
<a href="/p/<%= $name %>" class="waves-effect waves-light btn">
|
||||
Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
<div class="col s6">
|
||||
<button class="btn waves-effect waves-light" type="submit" name="action" value="save">
|
||||
Speichern
|
||||
<i class="material-icons right">send</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
%= end
|
Loading…
Reference in a new issue