Typos, Bugfixes and explicit response for organization show page

This commit is contained in:
Constantin Graf
2024-04-21 22:15:11 +02:00
committed by Constantin Graf
parent 2acef6a997
commit 5e979db912
9 changed files with 83 additions and 31 deletions

View File

@@ -27,8 +27,9 @@ use Laravel\Jetstream\Team as JetstreamTeam;
* @property User $owner
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Collection<User> $users
* @property Collection<string, User> $realUsers
* @property Collection<int, User> $users
* @property Collection<int, User> $realUsers
* @property-read Collection<int, OrganizationInvitation> $teamInvitations
* @property Membership $membership
*
* @method HasMany<OrganizationInvitation> teamInvitations()
@@ -83,7 +84,7 @@ class Organization extends JetstreamTeam
/**
* Get all the non-placeholder users of the organization including its owner.
*
* @return Collection<string, User>
* @return Collection<int, User>
*/
public function allRealUsers(): Collection
{

View File

@@ -22,7 +22,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
* @property int|null $billable_rate
* @property-read Organization $organization
* @property-read Client|null $client
* @property-read Collection<Task> $tasks
* @property-read Collection<int, Task> $tasks
*
* @method Builder<Project> visibleByUser(User $user)
* @method static ProjectFactory factory()

View File

@@ -22,7 +22,7 @@ use Illuminate\Support\Carbon;
* @property Carbon|null $updated_at
* @property-read Project $project
* @property-read Organization $organization
* @property-read Collection<TimeEntry> $timeEntries
* @property-read Collection<int, TimeEntry> $timeEntries
*
* @method static TaskFactory factory()
*/

View File

@@ -8,8 +8,10 @@ use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation;
use App\Models\User;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
@@ -35,6 +37,20 @@ class FortifyServiceProvider extends ServiceProvider
Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
Fortify::authenticateUsing(function (Request $request): ?User {
/** @var User|null $user */
$user = User::query()
->where('email', $request->email)
->where('is_placeholder', '=', false)
->first();
if ($user !== null && Hash::check($request->password, $user->password)) {
return $user;
}
return null;
});
RateLimiter::for('login', function (Request $request) {
$throttleKey = Str::transliterate(Str::lower($request->input(Fortify::username())).'|'.$request->ip());

View File

@@ -16,6 +16,7 @@ use App\Enums\Role;
use App\Enums\Weekday;
use App\Models\Organization;
use App\Models\OrganizationInvitation;
use App\Models\User;
use App\Service\TimezoneService;
use Brick\Money\Currency;
use Brick\Money\ISOCurrencyProvider;
@@ -103,7 +104,7 @@ class JetstreamServiceProvider extends ServiceProvider
'members:change-role',
'members:update',
'members:delete',
])->description('Owner users can perform any action.');
])->description('Owner users can perform any action. There is only one owner per organization.');
Jetstream::role(Role::Admin->value, 'Administrator', [
'projects:view',
@@ -145,7 +146,7 @@ class JetstreamServiceProvider extends ServiceProvider
'invitations:remove',
'members:view',
'members:invite-placeholder',
])->description('Administrator users can perform any action.');
])->description('Administrator users can perform any action, except accessing the billing dashboard.');
Jetstream::role(Role::Manager->value, 'Manager', [
'projects:view',
@@ -181,7 +182,7 @@ class JetstreamServiceProvider extends ServiceProvider
'organizations:view',
'invitations:view',
'members:view',
])->description('Managers have the ability to read, create, and update their own time entries as well as those of their team.');
])->description('Managers have full access to all projects, time entries, ect. but cannot manage the organization (add/remove member, edit the organization, ect.).');
Jetstream::role(Role::Employee->value, 'Employee', [
'projects:view',
@@ -192,7 +193,7 @@ class JetstreamServiceProvider extends ServiceProvider
'time-entries:update:own',
'time-entries:delete:own',
'organizations:view',
])->description('Employees have the ability to read, create, and update their own time entries.');
])->description('Employees have the ability to read, create, and update their own time entries and they can see the projects that they are members of.');
Jetstream::role(Role::Placeholder->value, 'Placeholder', [
])->description('Placeholders are used for importing data. They cannot log in and have no permissions.');
@@ -210,7 +211,41 @@ class JetstreamServiceProvider extends ServiceProvider
->whenRendering(
'Teams/Show',
function (Request $request, array $data): array {
/** @var Organization $teamModel */
$teamModel = $data['team'];
$owner = $teamModel->owner;
return array_merge($data, [
'team' => [
'id' => $teamModel->getKey(),
'name' => $teamModel->name,
'currency' => $teamModel->currency,
'owner' => [
'id' => $owner->getKey(),
'name' => $owner->name,
'email' => $owner->email,
'profile_photo_url' => $owner->profile_photo_url,
],
'users' => $teamModel->users->map(function (User $user): array {
return [
'id' => $user->getKey(),
'name' => $user->name,
'email' => $user->email,
'profile_photo_url' => $user->profile_photo_url,
'membership' => [
'id' => $user->membership->id,
'role' => $user->membership->role,
],
];
}),
'team_invitations' => $teamModel->teamInvitations->map(function (OrganizationInvitation $invitation): array {
return [
'id' => $invitation->getKey(),
'email' => $invitation->email,
'role' => $invitation->role,
];
}),
],
'currencies' => array_map(function (Currency $currency): string {
return $currency->getName();
}, ISOCurrencyProvider::getInstance()->getAvailableCurrencies()),

View File

@@ -162,12 +162,12 @@ class ClockifyTimeEntriesImporter extends DefaultImporter
#[\Override]
public function getName(): string
{
return __('importer.toggl_data_importer.name');
return __('importer.clockify_time_entries.name');
}
#[\Override]
public function getDescription(): string
{
return __('importer.toggl_data_importer.description');
return __('importer.clockify_time_entries.description');
}
}

View File

@@ -26,21 +26,21 @@ const deleteTeam = () => {
<template>
<ActionSection>
<template #title> Delete Team </template>
<template #title> Delete Organization </template>
<template #description> Permanently delete this team. </template>
<template #description> Permanently delete this organization. </template>
<template #content>
<div class="max-w-xl text-sm text-muted">
Once a team is deleted, all of its resources and data will be
permanently deleted. Before deleting this team, please download
any data or information regarding this team that you wish to
Once a organization is deleted, all of its resources and data will be
permanently deleted. Before deleting this organization, please download
any data or information regarding this organization that you wish to
retain.
</div>
<div class="mt-5">
<DangerButton @click="confirmTeamDeletion">
Delete Team
Delete Organization
</DangerButton>
</div>
@@ -48,7 +48,7 @@ const deleteTeam = () => {
<ConfirmationModal
:show="confirmingTeamDeletion"
@close="confirmingTeamDeletion = false">
<template #title> Delete Team </template>
<template #title> Delete Organization </template>
<template #content>
Are you sure you want to delete this team? Once a team is
@@ -66,7 +66,7 @@ const deleteTeam = () => {
:class="{ 'opacity-25': form.processing }"
:disabled="form.processing"
@click="deleteTeam">
Delete Team
Delete Organization
</DangerButton>
</template>
</ConfirmationModal>

View File

@@ -130,10 +130,10 @@ const displayableRole = (role: string) => {
<!-- Add Organization Member -->
<FormSection @submitted="addTeamMember">
<template #title> Add Team Member</template>
<template #title> Add Organization Member</template>
<template #description>
Add a new team member to your team, allowing them to
Add a new member to your organization, allowing them to
collaborate with you.
</template>
@@ -141,7 +141,7 @@ const displayableRole = (role: string) => {
<div class="col-span-6">
<div class="max-w-xl text-sm text-muted">
Please provide the email address of the person you
would like to add to this team.
would like to add to this organization.
</div>
</div>
@@ -257,8 +257,8 @@ const displayableRole = (role: string) => {
<template #title> Pending Team Invitations</template>
<template #description>
These people have been invited to your team and have been
sent an invitation email. They may join the team by
These people have been invited to your organization and have been
sent an invitation email. They may join the organization by
accepting the email invitation.
</template>
@@ -293,10 +293,10 @@ const displayableRole = (role: string) => {
<!-- Manage Organization Members -->
<ActionSection class="mt-10 sm:mt-0">
<template #title> Team Members</template>
<template #title> Organization Members</template>
<template #description>
All of the people that are part of this team.
All of the people that are part of this organization.
</template>
<!-- Organization Member List -->
@@ -443,10 +443,10 @@ const displayableRole = (role: string) => {
<ConfirmationModal
:show="confirmingLeavingTeam"
@close="confirmingLeavingTeam = false">
<template #title> Leave Team</template>
<template #title> Leave Organization</template>
<template #content>
Are you sure you would like to leave this team?
Are you sure you would like to leave this organization?
</template>
<template #footer>
@@ -471,7 +471,7 @@ const displayableRole = (role: string) => {
<template #title> Remove Team Member</template>
<template #content>
Are you sure you would like to remove this person from the team?
Are you sure you would like to remove this person from the organization?
</template>
<template #footer>

View File

@@ -34,14 +34,14 @@ const updateTeamName = () => {
<template #title> Organization Name</template>
<template #description>
The team's name and owner information.
The organization's name and owner information.
</template>
<template #form>
<!-- Organization Owner Information -->
<div class="col-span-6 flex items-center justify-between">
<div class="">
<InputLabel value="Team Owner" />
<InputLabel value="Organization Owner" />
<div class="flex items-center mt-2">
<img