Skip to content

Commit

Permalink
Merge pull request #528 from HZ-HBO-ICT/feature/combine-predefined-an…
Browse files Browse the repository at this point in the history
…d-action-based-roles

Feature - Combine predefined and action based roles
  • Loading branch information
TimKardol authored Sep 16, 2024
2 parents 37d6030 + c429479 commit a172da3
Show file tree
Hide file tree
Showing 17 changed files with 356 additions and 59 deletions.
7 changes: 3 additions & 4 deletions app/Livewire/Booth/JoinBoothOwnerModal.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ class JoinBoothOwnerModal extends ModalComponent
*/
public function save()
{
$user = Auth::user();

$this->authorize('becomeBoothOwner', $user->company);
$user->assignRole('booth owner');
$this->authorize('becomeBoothOwner', Auth::user()->company);
Auth::user()->assignRole('booth owner');
Auth::user()->removeRole('pending booth owner');

return redirect(route('dashboard'))
->with('status', 'You successfully became a booth owner.');
Expand Down
45 changes: 33 additions & 12 deletions app/Livewire/Company/AddMember.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
class AddMember extends Component
{
public Company $company;
public $roles;

#[Validate('required|in:speaker,booth owner,company member')]
public $currentRole;

#[Validate('required|unique:users')]
public string $email;
Expand All @@ -25,35 +29,52 @@ class AddMember extends Component
public function mount($company)
{
$this->company = $company;
$this->roles = [
'speaker' => 'The user can request to give a presentation or become a co-speaker for another presentation
within the company.',
'booth owner' => 'The user can request a booth if one does not already exist and is expected to be present
at the booth during the conference.',
'company member' => 'The user can choose to be a speaker or a booth owner. If they do not take action to
become a speaker or booth owner, they will simply accompany the other members.'
];
}

/**
* Handles the selecting of a new role
*
* @param $role
* @return void
*/
public function selectRole($role)
{
$this->currentRole = $role;
}


/**
* Invite a new team member to the given team.
*/
public function invite(): void
{
$this->validate();
if ($this->currentRole == 'speaker') {
$this->currentRole = 'pending speaker';
} else if ($this->currentRole == 'booth owner') {
$this->currentRole = 'pending booth owner';
}

$invitation = $this->company->invitations()->create([
'email' => $this->email,
'role' => 'company member'
'role' => $this->currentRole
]);

Mail::to($this->email)->send(new CustomCompanyInvitation($invitation));

$this->email = '';
$this->currentRole = '';

$this->company = $this->company->refresh();
}


/**
* Returns all roles and descriptions available
* @return array
*/
public function getRolesProperty() : array
{
return config('roles');
session()->flash('message', 'Post successfully updated.');
}

/**
Expand All @@ -73,7 +94,7 @@ public function cancelInvitation($invitation_id)
* Renders the component
* @return View
*/
public function render() : View
public function render(): View
{
return view('livewire.company.add-member');
}
Expand Down
5 changes: 5 additions & 0 deletions app/Livewire/Company/BoothRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ public function requestBooth()
);

Auth::user()->assignRole('booth owner');

if (Auth::user()->hasRole('pending booth owner')) {
Auth::user()->removeRole('pending booth owner');
}

$this->additionalInformation = '';
$this->requestSent = true;
$this->company->refresh();
Expand Down
2 changes: 1 addition & 1 deletion app/Mail/CustomCompanyInvitation.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class CustomCompanyInvitation extends Mailable
* @param $invitation
* @return void
*/
public function __construct(Invitation $invitation)
public function __construct($invitation)
{
$this->invitation = $invitation;
}
Expand Down
2 changes: 1 addition & 1 deletion app/Models/Company.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public function isHz(): Attribute
public function isGoldSponsor(): Attribute
{
return Attribute::make(
get: fn() => $this->sponsorship ? $this->sponsorship->name === 'gold' && $this->is_sponsorhip_approved : 0
get: fn() => $this->sponsorship ? $this->sponsorship->name === 'gold' && $this->is_sponsorship_approved : 0
);
}

Expand Down
4 changes: 4 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ public function joinPresentation($presentation, string $role = 'participant'): b
'role' => $role
]);

if ($this->hasRole('pending speaker')) {
$this->removeRole('pending speaker');
}

return true;
}

Expand Down
15 changes: 12 additions & 3 deletions app/Policies/CompanyPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public function viewAny(User $user): bool
*/
public function view(User $user, Company $company): bool
{
// Edge case since the speaker doesn't have a role that I can give permission to
if ($user->isMemberOf($company) && $user->presenter_of) {
return true;
}

return ($user->is_crew || $user->isMemberOf($company))
&& $user->can('view company');
}
Expand Down Expand Up @@ -96,6 +101,11 @@ public function approveRequest(User $user, Company $company): bool
*/
public function viewAnyMember(User $user, Company $company): bool
{
// Edge case since the speaker doesn't have a role that I can give permission to
if ($user->isMemberOf($company) && $user->presenter_of && $company->is_approved) {
return true;
}

return ($user->is_crew
|| $user->isMemberOf($company) && $company->is_approved)
&& $user->hasPermissionTo('viewAny company member');
Expand Down Expand Up @@ -205,7 +215,7 @@ public function viewRequests(User $user, Company $company): bool
'view booth request',
'view sponsorship request',
'view company delete request'
]) || $user->hasRole('booth owner');
]) || $user->hasRole(['booth owner', 'pending booth owner']);

return $isCrewOrCompanyMember && $hasRequiredPermissions;
}
Expand All @@ -220,7 +230,7 @@ public function requestBooth(User $user, Company $company): bool
{
return $user->isMemberOf($company)
&& !$company->booth
&& ($user->isDefaultCompanyMember() || $user->hasRole('company representative', 'web'))
&& ($user->isDefaultCompanyMember() || $user->hasRole(['company representative', 'pending booth owner']))
&& $user->hasPermissionTo('create booth request');
}

Expand Down Expand Up @@ -248,7 +258,6 @@ public function becomeBoothOwner(User $user, Company $company): bool
{
return $user->isMemberOf($company)
&& $company->booth
&& ($user->isDefaultCompanyMember() || $user->hasRole('company representative', 'web'))
&& $user->hasPermissionTo('create booth request');
}
}
11 changes: 6 additions & 5 deletions app/Policies/PresentationPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ public function view(User $user, Presentation $presentation): bool
}

if ($presentation->company) {
// View if the company member hasn't decided their role
if ($user->isMemberOf($presentation->company) && $user->isDefaultCompanyMember) {
if ($user->isMemberOf($presentation->company)
&& ($user->isDefaultCompanyMember || $user->hasRole(['pending speaker', 'company representative']))) {
return true;
}
}
Expand Down Expand Up @@ -121,8 +121,8 @@ public function request(User $user): bool
// When the user is associated to a company, allow only if the user's
// company has presentations left
if ($user->company) {
// When the user is not default company member and also not company rep, they should be denied
if (!$user->isDefaultCompanyMember && !$user->hasRole('company representative')) {
// When the user is company representative, speaker or pending speaker
if (!$user->hasRole(['company representative', 'pending speaker', 'speaker'])) {
return false;
}

Expand Down Expand Up @@ -225,6 +225,7 @@ public function joinAsCospeaker(User $user, Presentation $presentation): bool
return $user->company
&& $presentation->company
&& $presentation->company->id == $user->company->id
&& $user->isDefaultCompanyMember;
&& !$user->presenter_of
&& ($user->isDefaultCompanyMember || $user->hasAnyRole(['pending speaker', 'company representative']));
}
}
33 changes: 33 additions & 0 deletions app/View/Components/Dashboards/Blocks/BoothOwnerInfo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace App\View\Components\Dashboards\Blocks;

use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\Component;

class BoothOwnerInfo extends Component
{
public $boothButtons = [];

/**
* Create a new component instance.
*/
public function __construct()
{
if (!Auth::user()->company->booth) {
$this->boothButtons['Request a booth'] = 'company.requests';
} else {
$this->boothButtons['Join the others at the booth'] = null;
}
}

/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.dashboards.blocks.booth-owner-info');
}
}
39 changes: 39 additions & 0 deletions app/View/Components/Dashboards/Blocks/SpeakerInfo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\View\Components\Dashboards\Blocks;

use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\Component;

class SpeakerInfo extends Component
{
public $speakerButtons = [];

/**
* Create a new component instance.
*/
public function __construct()
{
$company = Auth::user()->company;

if ($company->hasPresentationsLeft) {
$this->speakerButtons['Request a presentation'] = 'presentations.create';
}
if ($company->presentations) {
foreach ($company->presentations as $presentation) {
$this->speakerButtons["Join '{$presentation->name}' as a co-speaker"] =
['presentations.show', $presentation];
}
}
}

/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.dashboards.blocks.speaker-info');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@php use \Illuminate\Support\Facades\Auth @endphp
<div>
<dl class="pt-11 pb-5 px-6">
<div
class="py-5 px-4 rounded-lg overflow-hidden relative bg-partner-100 dark:bg-partner-900 shadow-md dark:shadow-md">
<dt>
<div class="p-3 rounded-md absolute bg-partner-500">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="white"
aria-hidden="true" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"/>
</svg>
</div>
</dt>
<div class="ml-16 font-semibold text-md text-gray-700 dark:text-gray-100 overflow-hidden text-ellipsis">
<p>You are part of the people joining {{Auth::user()->company->name}} for the "We are in IT together"
conference!<br>
When the company representative invited you, they specified that you would be part of the booth owners of
the company.
</p>
<div class="pt-8 grid grid-cols-1">
<div class="w-full">
To become a booth owner you must do the following:
</div>
@foreach($boothButtons as $label => $route)
<div class="pt-2">
@if($route)
<a href="{{ route($route) }}"
class="flex w-full items-center bg-partner-500 hover:bg-partner-700 dark:bg-partner-600 dark:hover:bg-gray-900 text-gray-200 dark:text-white font-semibold justify-center py-2 px-4 w-3/4 rounded-lg transition duration-300 ease-in-out">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor"
class="w-6 h-6 mr-2">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
<span>{{ $label }}</span>
</a>
@else
<button
class="flex w-full items-center bg-partner-500 hover:bg-partner-700 dark:bg-partner-600 dark:hover:bg-gray-900 text-gray-200 dark:text-white font-semibold justify-center py-2 px-4 w-3/4 rounded-lg transition duration-300 ease-in-out"
onclick="Livewire.dispatch('openModal', { component: 'booth.join-booth-owner-modal' })">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor"
class="w-6 h-6 mr-2">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
<span>{{ $label }}</span>
</button>
@endif
</div>
@endforeach
</div>
</div>
</div>
</dl>
</div>
Loading

0 comments on commit a172da3

Please sign in to comment.