From bcaec60e0def5284a35c7e7a6a8beaaf48348a04 Mon Sep 17 00:00:00 2001 From: George Daneke Date: Sat, 22 Jun 2024 00:26:05 +0300 Subject: [PATCH] updated importer. updated readme file --- README.md | 13 ++++ app/Filament/Imports/ItemImporter.php | 87 ++++++++++++++++++------- app/Filament/Resources/ItemResource.php | 8 ++- 3 files changed, 85 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 72f67fd..69b51c3 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,13 @@ Still some part are in WIP status: I need to add queue worker to docker-compose. - [ ] Show related items in Location view - https://filamentphp.com/docs/3.x/panels/resources/relation-managers#creating-a-relation-manager - [ ] Add QR code to items - [x] Add multi-tenancy support - https://filamentphp.com/docs/3.x/panels/tenancy + - [ ] Fix ItemImporter to support multi-tenancy with queue. Team ID is not set up correctly for now on async driver - [ ] Add better import/export of items with relation to locations + - [x] Add import of locations. if location by name not found it will create new one + - [ ] Support labels/tags during import + - [ ] Support attachments during import + - [ ] Support nested path exports (e.g. `Home / Office / Desk`) + - [ ] Support custom fields during import - [x] Add Laravel Octane - [ ] Add Laravel Pulse - [x] Add nice Dashboard for home-screen @@ -90,8 +96,15 @@ Still some part are in WIP status: I need to add queue worker to docker-compose. - [x] Text field - [x] File(s) field - [x] Image field + - [x] Add spotlight. Click: CTRL + K or CMD + K or CTRL + / or CMD + / ## Contributing Thank you for choosing to contribute to the project! Any contribution is welcome. + + + +#https://github.com/benjaminjonard/koillection/blob/1f9eb74309777e292118db899671db49ebacb395/Dockerfile.frankenphp +#https://github.com/andrewdwallo/filament-companies +# add https://github.com/awcodes/filament-table-repeater?tab=readme-ov-file for custom fileds diff --git a/app/Filament/Imports/ItemImporter.php b/app/Filament/Imports/ItemImporter.php index 7544480..deb2948 100644 --- a/app/Filament/Imports/ItemImporter.php +++ b/app/Filament/Imports/ItemImporter.php @@ -3,9 +3,15 @@ namespace App\Filament\Imports; use App\Models\Item; +use App\Models\Location; +use App\Models\Team; +use App\Models\User; use Filament\Actions\Imports\ImportColumn; use Filament\Actions\Imports\Importer; use Filament\Actions\Imports\Models\Import; +use Filament\Facades\Filament; +use Illuminate\Log\Logger; +use Illuminate\Support\Facades\Log; class ItemImporter extends Importer { @@ -14,12 +20,9 @@ class ItemImporter extends Importer public static function getColumns(): array { return [ - ImportColumn::make('ulid') - ->requiredMapping() - ->rules(['required']), ImportColumn::make('name') ->requiredMapping() - ->rules(['required']), + ->rules(['required', 'nullable']), ImportColumn::make('description'), ImportColumn::make('import_ref'), ImportColumn::make('notes'), @@ -34,55 +37,95 @@ public static function getColumns(): array ->boolean() ->rules(['boolean']), ImportColumn::make('asset_id') - ->numeric() - ->rules(['integer']), + ->castStateUsing(function (string $state) { + // find from 000-001 integer value + if (blank($state)) { + return null; + } + // remove any non-numeric characters + $state = preg_replace('/[^0-9]/', '', $state); + + return (int)$state; + }) + ->rules([ + 'required', +// \Illuminate\Validation\Rule::unique('items', 'asset_id') +// ->where(function ($query) { +// return $query->andWhere('team_id', Filament::auth()->user()->currentTeam->id); +// }) + ]), ImportColumn::make('serial_number'), ImportColumn::make('model_number'), ImportColumn::make('manufacturer'), ImportColumn::make('lifetime_warranty') ->boolean() - ->rules(['boolean']), + ->rules(['boolean', 'nullable']), ImportColumn::make('warranty_expires') - ->rules(['datetime']), + ->rules(['date', 'nullable']), ImportColumn::make('warranty_details'), ImportColumn::make('purchase_time') - ->rules(['datetime']), + ->rules(['date', 'nullable']), ImportColumn::make('purchase_from'), ImportColumn::make('purchase_price') ->numeric() - ->rules(['integer']), + ->numeric(decimalPlaces: 2) + ->rules(['integer', 'nullable']), ImportColumn::make('sold_time') - ->rules(['datetime']), + ->rules(['date', 'nullable']), ImportColumn::make('sold_to'), ImportColumn::make('sold_price') + ->numeric(decimalPlaces: 2) ->numeric() - ->rules(['integer']), + ->rules(['integer', 'nullable']), ImportColumn::make('sold_notes'), ImportColumn::make('location') ->requiredMapping() - ->relationship() - ->rules(['required']), + ->relationship(resolveUsing: function (string $state + ): \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model { + // find the location by name or id OR create a new location + // TODO check team_id + return Location::query() + ->where('name', $state) + ->orWhere('id', $state) + ->firstOr(function () use ($state) { + return Location::create([ + 'name' => $state, + ]); + }); + }) + ->rules(['required', 'nullable']), ]; } public function resolveRecord(): ?Item { - // return Item::firstOrNew([ - // // Update existing records, matching them by `$this->data['column_name']` - // 'email' => $this->data['email'], - // ]); - - return new Item(); +// return Item::firstOrNew([ +// // Update existing records, matching them by `$this->data['column_name']` +// 'asset_id' => $this->data['asset_id'], +// 'team_id' => Filament::auth()->user()->currentTeam->id, +// ]); + $item = new Item(); + $item->team_id = $this->options['team_id']; + return $item; } public static function getCompletedNotificationBody(Import $import): string { - $body = 'Your item import has completed and '.number_format($import->successful_rows).' '.str('row')->plural($import->successful_rows).' imported.'; + $body = 'Your item import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.'; if ($failedRowsCount = $import->getFailedRowsCount()) { - $body .= ' '.number_format($failedRowsCount).' '.str('row')->plural($failedRowsCount).' failed to import.'; + $body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.'; } return $body; } + + + protected function beforeCreate(): void + { + } + + protected function beforeFill(): void + { + } } diff --git a/app/Filament/Resources/ItemResource.php b/app/Filament/Resources/ItemResource.php index c881090..a9b23cd 100644 --- a/app/Filament/Resources/ItemResource.php +++ b/app/Filament/Resources/ItemResource.php @@ -6,6 +6,7 @@ use App\Filament\Imports\ItemImporter; use App\Filament\Resources\ItemResource\Pages; use App\Models\Item; +use Filament\Facades\Filament; use Filament\Forms\Components\Builder; use Filament\Forms\Components\Checkbox; use Filament\Forms\Components\DatePicker; @@ -87,6 +88,7 @@ public static function form(Form $form): Form TextInput::make('name') ->label('Item name') ->columnSpanFull() + ->autofocus() ->required(), Textarea::make('description') @@ -315,7 +317,9 @@ public static function table(Table $table): Table ]) ->headerActions([ ImportAction::make() - ->importer(ItemImporter::class), + ->importer(ItemImporter::class)->options([ + 'team_id' => Filament::getTenant()?->id, + ]), ExportAction::make()->exporter(ItemExporter::class), ]) ->bulkActions([ @@ -358,6 +362,8 @@ public static function getGlobalSearchResultDetails(Model $record): array { $details = []; + $record->load('location'); + if ($record->location) { $details['Location'] = $record->location->name; }