mirror of https://github.com/kcal-app/kcal.git
Complete profile management functionality
This commit is contained in:
parent
adc63d975c
commit
78c3095036
|
@ -22,7 +22,9 @@ trait UpdatesUser
|
||||||
else {
|
else {
|
||||||
unset($input['password']);
|
unset($input['password']);
|
||||||
}
|
}
|
||||||
$input['admin'] = $input['admin'] ?? false;
|
|
||||||
|
// Maintain the existing value if it is not on the form.
|
||||||
|
$input['admin'] = $input['admin'] ?? ($user->exists && $user->admin);
|
||||||
|
|
||||||
$user->fill($input)->save();
|
$user->fill($input)->save();
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -27,10 +27,13 @@
|
||||||
|
|
||||||
<x-slot name="content">
|
<x-slot name="content">
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<x-dropdown-link :href="route('goals.index')">Goals</x-dropdown-link>
|
<x-dropdown-link :href="route('profiles.show', Auth::user())">My Profile</x-dropdown-link>
|
||||||
|
<x-dropdown-link :href="route('goals.index')">My Goals</x-dropdown-link>
|
||||||
@can('administer', \App\Models\User::class)
|
@can('administer', \App\Models\User::class)
|
||||||
<x-dropdown-link :href="route('users.index')">Users</x-dropdown-link>
|
<hr />
|
||||||
|
<x-dropdown-link :href="route('users.index')">Manage Users</x-dropdown-link>
|
||||||
@endcan
|
@endcan
|
||||||
|
<hr />
|
||||||
<form method="POST" action="{{ route('logout') }}" x-data>
|
<form method="POST" action="{{ route('logout') }}" x-data>
|
||||||
@csrf
|
@csrf
|
||||||
<x-dropdown-link :href="route('logout')" @click.prevent="$el.closest('form').submit();">Logout</x-dropdown-link>
|
<x-dropdown-link :href="route('logout')" @click.prevent="$el.closest('form').submit();">Logout</x-dropdown-link>
|
||||||
|
|
|
@ -1,9 +1,24 @@
|
||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<x-slot name="title">Profile</x-slot>
|
@php($title = ($user->id === Auth::user()->id ? 'My Profile': "{$user->name}'s Profile"))
|
||||||
|
<x-slot name="title">{{ $title }}</x-slot>
|
||||||
<x-slot name="header">
|
<x-slot name="header">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<h1 class="font-semibold text-2xl text-gray-800 leading-tight">Profile</h1>
|
<h1 class="font-semibold text-2xl text-gray-800 leading-tight">{{ $title }}</h1>
|
||||||
|
@can('editProfile', $user)
|
||||||
|
<x-button-link.green href="{{ route('profiles.edit', $user) }}" class="text-sm">
|
||||||
|
Edit Profile
|
||||||
|
</x-button-link.green>
|
||||||
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
</x-slot>
|
</x-slot>
|
||||||
{{ $user->name }}
|
@if($user->hasMedia())
|
||||||
|
<div class="inline-block">
|
||||||
|
<a href="{{ $user->getFirstMedia()->getFullUrl() }}" target="_blank">
|
||||||
|
{{ $user->getFirstMedia()('icon') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 text-gray-500">
|
||||||
|
{{ $user->name }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
<div class="flex flex-col space-y-4">
|
<div class="flex flex-col space-y-4">
|
||||||
<div class="flex flex-col space-y-4 md:flex-row md:space-x-4 md:space-y-0">
|
<div class="flex flex-col space-y-4 md:flex-row md:space-x-4 md:space-y-0">
|
||||||
<!-- Username -->
|
<!-- Username -->
|
||||||
<div class="flex-auto">
|
<div class="flex-auto space-y-1">
|
||||||
<x-inputs.label for="username" value="Username"/>
|
<x-inputs.label for="username" value="Username"/>
|
||||||
|
|
||||||
<x-inputs.input name="username"
|
<x-inputs.input name="username"
|
||||||
type="text"
|
type="text"
|
||||||
class="block mt-1 w-full"
|
class="block w-full"
|
||||||
autocapitalize="none"
|
autocapitalize="none"
|
||||||
:value="old('username', $user->username)"
|
:value="old('username', $user->username)"
|
||||||
:hasError="$errors->has('username')"
|
:hasError="$errors->has('username')"
|
||||||
|
@ -23,12 +23,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Name -->
|
<!-- Name -->
|
||||||
<div class="flex-auto">
|
<div class="flex-auto space-y-1">
|
||||||
<x-inputs.label for="name" value="Display name"/>
|
<x-inputs.label for="name" value="Display name"/>
|
||||||
|
|
||||||
<x-inputs.input name="name"
|
<x-inputs.input name="name"
|
||||||
type="text"
|
type="text"
|
||||||
class="block mt-1 w-full"
|
class="block w-full"
|
||||||
:value="old('name', $user->name)"/>
|
:value="old('name', $user->name)"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -36,36 +36,37 @@
|
||||||
|
|
||||||
<div class="flex flex-col space-y-4 md:flex-row md:space-x-4 md:space-y-0">
|
<div class="flex flex-col space-y-4 md:flex-row md:space-x-4 md:space-y-0">
|
||||||
<!-- Password -->
|
<!-- Password -->
|
||||||
<div class="flex-auto">
|
<div class="flex-auto space-y-1">
|
||||||
<x-inputs.label for="password" value="Password"/>
|
<x-inputs.label for="password" value="Password"/>
|
||||||
|
|
||||||
<x-inputs.input name="password"
|
<x-inputs.input name="password"
|
||||||
type="password"
|
type="password"
|
||||||
class="block mt-1 w-full"
|
class="block w-full"
|
||||||
:hasError="$errors->has('password')"
|
:hasError="$errors->has('password')"
|
||||||
:required="!$user->exists"/>
|
:required="!$user->exists"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Password confirm -->
|
<!-- Password confirm -->
|
||||||
<div class="flex-auto">
|
<div class="flex-auto space-y-1">
|
||||||
<x-inputs.label for="password_confirmation" value="Confirm Password"/>
|
<x-inputs.label for="password_confirmation" value="Confirm Password"/>
|
||||||
|
|
||||||
<x-inputs.input name="password_confirmation"
|
<x-inputs.input name="password_confirmation"
|
||||||
type="password"
|
type="password"
|
||||||
class="block mt-1 w-full"
|
class="block w-full"
|
||||||
:hasError="$errors->has('password')"
|
:hasError="$errors->has('password')"
|
||||||
:required="!$user->exists"/>
|
:required="!$user->exists"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Admin -->
|
<!-- Admin -->
|
||||||
<div class="space-x-2">
|
<div class="space-y-1">
|
||||||
<x-inputs.label for="admin" value="Site Admin" class="inline-block"/>
|
<x-inputs.label for="admin" value="Site Admin" class="inline-block"/>
|
||||||
|
|
||||||
<x-inputs.input name="admin"
|
<x-inputs.select name="admin"
|
||||||
type="checkbox"
|
class="block"
|
||||||
value="1"
|
:options="[['value' => 0, 'label' => 'No'], ['value' => 1, 'label' => 'Yes']]"
|
||||||
:checked="old('admin', $user->admin)" />
|
:selectedValue="old('admin', $user->admin)">
|
||||||
|
</x-inputs.select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Image -->
|
<!-- Image -->
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\ProfileController;
|
||||||
|
use App\Models\User;
|
||||||
|
use Tests\LoggedInTestCase;
|
||||||
|
|
||||||
|
class ProfileControllerTest extends LoggedInTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test view own profile.
|
||||||
|
*/
|
||||||
|
public function testCanViewOwnProfile(): void
|
||||||
|
{
|
||||||
|
$view_url = action([ProfileController::class, 'show'], ['user' => $this->user]);
|
||||||
|
$response = $this->get($view_url);
|
||||||
|
$response->assertOk();
|
||||||
|
$response->assertViewHas('user', $this->user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test view other user profile.
|
||||||
|
*/
|
||||||
|
public function testCanViewOtherUserProfile(): void
|
||||||
|
{
|
||||||
|
$user = User::factory()->createOne();
|
||||||
|
$view_url = action([ProfileController::class, 'show'], ['user' => $user]);
|
||||||
|
$response = $this->get($view_url);
|
||||||
|
$response->assertOk();
|
||||||
|
$response->assertViewHas('user', $user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test view own profile.
|
||||||
|
*/
|
||||||
|
public function testCanEditOwnProfile(): void
|
||||||
|
{
|
||||||
|
$edit_url = action([ProfileController::class, 'edit'], ['user' => $this->user]);
|
||||||
|
$response = $this->get($edit_url);
|
||||||
|
$response->assertOk();
|
||||||
|
|
||||||
|
$new_user = User::factory()->make();
|
||||||
|
$put_url = action([ProfileController::class, 'update'], ['user' => $this->user]);
|
||||||
|
$response = $this->put($put_url, $new_user->toArray());
|
||||||
|
$response->assertSessionHasNoErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test view own profile.
|
||||||
|
*/
|
||||||
|
public function testCanNotEditOtherUserProfile(): void
|
||||||
|
{
|
||||||
|
$user = User::factory()->createOne();
|
||||||
|
$edit_url = action([ProfileController::class, 'edit'], ['user' => $user]);
|
||||||
|
$response = $this->get($edit_url);
|
||||||
|
$response->assertForbidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue