Skip to content

Commit

Permalink
Added more imports
Browse files Browse the repository at this point in the history
  • Loading branch information
korridor committed Mar 11, 2024
1 parent 14e3017 commit 4738b75
Show file tree
Hide file tree
Showing 52 changed files with 1,646 additions and 56 deletions.
3 changes: 2 additions & 1 deletion app/Actions/Jetstream/AddOrganizationMember.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Models\User;
use Closure;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
Expand Down Expand Up @@ -59,7 +60,7 @@ protected function validate(Organization $organization, string $email, ?string $
/**
* Get the validation rules for adding a team member.
*
* @return array<string, array<Rule|string>>
* @return array<string, array<ValidationRule|Rule|string>>
*/
protected function rules(): array
{
Expand Down
2 changes: 1 addition & 1 deletion app/Actions/Jetstream/InviteOrganizationMember.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function invite(User $user, Organization $organization, string $email, ?s

InvitingTeamMember::dispatch($organization, $email, $role);

/** @var TeamInvitation $invitation */
/** @var OrganizationInvitation $invitation */
$invitation = $organization->teamInvitations()->create([
'email' => $email,
'role' => $role,
Expand Down
10 changes: 7 additions & 3 deletions app/Exceptions/Api/ApiException.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

abstract class ApiException extends Exception
{
public const string KEY = 'api_exception';

/**
* Render the exception into an HTTP response.
*/
Expand All @@ -29,11 +31,13 @@ public function render(Request $request): JsonResponse
*/
public function getKey(): string
{
if (defined(static::class.'::KEY')) {
return static::KEY;
$key = static::KEY;

if ($key === ApiException::KEY) {
throw new LogicException('API exceptions need the KEY constant defined.');
}

throw new LogicException('API exceptions need the KEY constant defined.');
return $key;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion app/Exceptions/Api/TimeEntryStillRunningApiException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@

class TimeEntryStillRunningApiException extends ApiException
{
const string KEY = 'time_entry_still_running';
public const string KEY = 'time_entry_still_running';
}
2 changes: 1 addition & 1 deletion app/Exceptions/Api/UserNotPlaceholderApiException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@

class UserNotPlaceholderApiException extends ApiException
{
const string KEY = 'user_not_placeholder';
public const string KEY = 'user_not_placeholder';
}
5 changes: 3 additions & 2 deletions app/Filament/Resources/OrganizationResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public static function table(Table $table): Table
// TODO: different disk!
try {
/** @var ReportDto $report */
$report = app(ImportService::class)->import($record, $data['type'], Storage::disk('public')->get($data['file']), []);
$report = app(ImportService::class)->import($record, $data['type'], Storage::disk('public')->get($data['file']));
Notification::make()
->title('Import successful')
->success()
Expand All @@ -98,9 +98,10 @@ public static function table(Table $table): Table
->send();
}
})
->tooltip(fn (Organization $record): string => "Import into {$record->name}")
->tooltip(fn (Organization $record): string => 'Import into '.$record->name)
->form([
Forms\Components\FileUpload::make('file')
// TODO: disk!
->label('File')
->required(),
Select::make('type')
Expand Down
20 changes: 18 additions & 2 deletions app/Filament/Resources/TaskResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@

use App\Filament\Resources\TaskResource\Pages;
use App\Models\Task;
use Filament\Forms;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;

class TaskResource extends Resource
Expand All @@ -25,7 +28,18 @@ public static function form(Form $form): Form
{
return $form
->schema([
//
Forms\Components\TextInput::make('name')
->label('Name')
->required()
->maxLength(255),
Select::make('project_id')
->relationship(name: 'project', titleAttribute: 'name')
->searchable(['name'])
->required(),
Select::make('organization_id')
->relationship(name: 'organization', titleAttribute: 'name')
->searchable(['name'])
->required(),
]);
}

Expand All @@ -46,7 +60,9 @@ public static function table(Table $table): Table
->sortable(),
])
->filters([
//
SelectFilter::make('organization')
->relationship('organization', 'name')
->searchable(),
])
->defaultSort('created_at', 'desc')
->actions([
Expand Down
6 changes: 5 additions & 1 deletion app/Filament/Resources/TimeEntryResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;

class TimeEntryResource extends Resource
Expand Down Expand Up @@ -67,6 +68,7 @@ public static function table(Table $table): Table
return $table
->columns([
TextColumn::make('description')
->searchable()
->label('Description'),
TextColumn::make('user.email')
->label('User'),
Expand All @@ -89,7 +91,9 @@ public static function table(Table $table): Table
->sortable(),
])
->filters([
//
SelectFilter::make('organization')
->relationship('organization', 'name')
->searchable(),
])
->defaultSort('created_at', 'desc')
->actions([
Expand Down
3 changes: 1 addition & 2 deletions app/Http/Controllers/Api/V1/ImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ public function import(Organization $organization, ImportRequest $request, Impor
$report = $importService->import(
$organization,
$request->input('type'),
$request->input('data'),
$request->input('options')
$request->input('data')
);

return new JsonResponse([
Expand Down
2 changes: 2 additions & 0 deletions app/Http/Requests/V1/Project/ProjectStoreRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use App\Models\Client;
use App\Models\Organization;
use App\Rules\ColorRule;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Http\FormRequest;
Expand Down Expand Up @@ -35,6 +36,7 @@ public function rules(): array
'required',
'string',
'max:255',
new ColorRule(),
],
'client_id' => [
'nullable',
Expand Down
2 changes: 2 additions & 0 deletions app/Http/Requests/V1/Project/ProjectUpdateRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use App\Models\Client;
use App\Models\Organization;
use App\Rules\ColorRule;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Http\FormRequest;
Expand Down Expand Up @@ -34,6 +35,7 @@ public function rules(): array
'required',
'string',
'max:255',
new ColorRule(),
],
'client_id' => [
'nullable',
Expand Down
5 changes: 1 addition & 4 deletions app/Http/Requests/V1/TimeEntry/TimeEntryIndexRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ public function rules(): array
'uuid',
new ExistsEloquent(User::class, null, function (Builder $builder): Builder {
/** @var Builder<User> $builder */
return $builder->whereHas('organizations', function (Builder $builder) {
/** @var Builder<Organization> $builder */
return $builder->whereKey($this->organization->getKey());
});
return $builder->belongsToOrganization($this->organization);
}),
],
// Filter only time entries that have a start date before (not including) the given date (example: 2021-12-31)
Expand Down
5 changes: 1 addition & 4 deletions app/Http/Requests/V1/TimeEntry/TimeEntryStoreRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ public function rules(): array
'uuid',
new ExistsEloquent(User::class, null, function (Builder $builder): Builder {
/** @var Builder<User> $builder */
return $builder->whereHas('organizations', function (Builder $builder) {
/** @var Builder<Organization> $builder */
return $builder->whereKey($this->organization->getKey());
});
return $builder->belongsToOrganization($this->organization);
}),
],
// ID of the task that the time entry should belong to
Expand Down
17 changes: 16 additions & 1 deletion app/Models/Organization.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Laravel\Jetstream\Events\TeamCreated;
use Laravel\Jetstream\Events\TeamDeleted;
use Laravel\Jetstream\Events\TeamUpdated;
use Laravel\Jetstream\Jetstream;
use Laravel\Jetstream\Team as JetstreamTeam;

/**
Expand All @@ -21,6 +22,7 @@
* @property bool $personal_team
* @property User $owner
* @property Collection<User> $users
* @property Collection<string, User> $realUsers
*
* @method HasMany<OrganizationInvitation> teamInvitations()
* @method static OrganizationFactory factory()
Expand Down Expand Up @@ -64,7 +66,7 @@ class Organization extends JetstreamTeam
/**
* Get all the non-placeholder users of the organization including its owner.
*
* @return Collection<User>
* @return Collection<string, User>
*/
public function allRealUsers(): Collection
{
Expand All @@ -78,6 +80,19 @@ public function hasRealUserWithEmail(string $email): bool
});
}

/**
* Get all the users that belong to the team.
*
* @return BelongsToMany<User>
*/
public function users(): BelongsToMany
{
return $this->belongsToMany(Jetstream::userModel(), Jetstream::membershipModel())
->withPivot('role')
->withTimestamps()
->as('membership');
}

/**
* @return BelongsToMany<User>
*/
Expand Down
1 change: 1 addition & 0 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public function boot(): void

Model::preventLazyLoading(! $this->app->isProduction());
Model::preventSilentlyDiscardingAttributes(! $this->app->isProduction());
Model::preventAccessingMissingAttributes(! $this->app->isProduction());
Relation::enforceMorphMap([
'membership' => Membership::class,
'organization' => Organization::class,
Expand Down
3 changes: 3 additions & 0 deletions app/Providers/JetstreamServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,8 @@ protected function configurePermissions(): void
'time-entries:delete:own',
'organizations:view',
])->description('Editor users have the ability to read, create, and update.');

Jetstream::role('placeholder', 'Placeholder', [
])->description('Placeholders are used for importing data. They cannot log in and have no permissions.');
}
}
32 changes: 32 additions & 0 deletions app/Rules/ColorRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace App\Rules;

use App\Service\ColorService;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Translation\PotentiallyTranslatedString;

class ColorRule implements ValidationRule
{
/**
* Run the validation rule.
*
* @param Closure(string): PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (! is_string($value)) {
$fail(__('validation.string'));

return;
}
if (! app(ColorService::class)->isValid($value)) {
$fail(__('validation.color'));

return;
}
}
}
7 changes: 7 additions & 0 deletions app/Service/ColorService.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,15 @@ class ColorService
'#78909c',
];

private const string VALID_REGEX = '/^#[0-9a-f]{6}$/';

public function getRandomColor(): string
{
return self::COLORS[array_rand(self::COLORS)];
}

public function isValid(string $color): bool
{
return preg_match(self::VALID_REGEX, $color) === 1;
}
}
Loading

0 comments on commit 4738b75

Please sign in to comment.