From abd5b2166144f287307698fc58045075d3699832 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 19 Apr 2024 15:17:17 +0800 Subject: [PATCH 1/7] preparing v04.27 branch --- composer.json | 2 +- extension.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 23c7ccbb..9c3f661a 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "fleetbase/fleetops-api", - "version": "0.4.26", + "version": "0.4.27", "description": "Fleet & Transport Management Extension for Fleetbase", "keywords": [ "fleetbase-extension", diff --git a/extension.json b/extension.json index eeb7ac51..cc705778 100644 --- a/extension.json +++ b/extension.json @@ -1,6 +1,6 @@ { "name": "Fleet-Ops", - "version": "0.4.26", + "version": "0.4.27", "description": "Fleet & Transport Management Extension for Fleetbase", "repository": "https://github.com/fleetbase/fleetops", "license": "MIT", diff --git a/package.json b/package.json index d85bf9d6..3d19bc77 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fleetbase/fleetops-engine", - "version": "0.4.26", + "version": "0.4.27", "description": "Fleet & Transport Management Extension for Fleetbase", "fleetbase": { "route": "fleet-ops" From 1382abd04d6b229a2bc0fecfb3e11b8da4e9112d Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Fri, 19 Apr 2024 15:46:01 +0800 Subject: [PATCH 2/7] set user property on driver resource --- server/src/Http/Resources/v1/Driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/Http/Resources/v1/Driver.php b/server/src/Http/Resources/v1/Driver.php index cd76d764..7408d6d6 100644 --- a/server/src/Http/Resources/v1/Driver.php +++ b/server/src/Http/Resources/v1/Driver.php @@ -27,7 +27,7 @@ public function toArray($request) 'vendor_uuid' => $this->when(Http::isInternalRequest(), $this->vendor_uuid), 'current_job_uuid' => $this->when(Http::isInternalRequest(), $this->current_job_uuid), 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id), - 'user_id' => $this->when(Http::isPublicRequest(), data_get($this, 'user.public_id')), + 'user' => $this->when(Http::isPublicRequest(), $this->user->public_id), 'internal_id' => $this->internal_id, 'name' => $this->name, 'email' => $this->email, From 856f868c21918ec8dd9695ca04fd072acfe8a3e1 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 19 Apr 2024 16:54:20 +0800 Subject: [PATCH 3/7] added field --- server/src/Models/Driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/Models/Driver.php b/server/src/Models/Driver.php index a01fcfe5..f0a1fd7b 100644 --- a/server/src/Models/Driver.php +++ b/server/src/Models/Driver.php @@ -193,7 +193,7 @@ protected static function boot() */ public function user() { - return $this->belongsTo(\Fleetbase\Models\User::class)->select(['uuid', 'company_uuid', 'avatar_uuid', 'name', 'phone', 'email'])->without(['driver'])->withTrashed(); + return $this->belongsTo(\Fleetbase\Models\User::class)->select(['uuid', 'company_uuid', 'public_id', 'avatar_uuid', 'name', 'phone', 'email'])->without(['driver'])->withTrashed(); } /** From 0af6199082c753059a927abc84d834ae217d96ba Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Tue, 30 Apr 2024 17:32:09 +0800 Subject: [PATCH 4/7] improved user account management for driver profiles and added new user filter for users who do not have a driver profile --- addon/components/driver-form-panel.hbs | 109 +++++++++++------- addon/components/driver-form-panel.js | 60 ++++++++++ addon/components/driver-panel/details.hbs | 84 +++++++------- server/src/Expansions/UserFilterExpansion.php | 29 +++++ .../Internal/v1/DriverController.php | 53 +++++---- .../Requests/CreateServiceRateRequest.php | 2 +- .../Requests/Internal/CreateDriverRequest.php | 6 +- server/src/Http/Resources/v1/Driver.php | 3 +- server/src/Observers/DriverObserver.php | 13 +-- server/src/Rules/ComputableAlgo.php | 33 ++++++ translations/en-us.yaml | 27 +++-- 11 files changed, 287 insertions(+), 132 deletions(-) create mode 100644 server/src/Expansions/UserFilterExpansion.php create mode 100644 server/src/Rules/ComputableAlgo.php diff --git a/addon/components/driver-form-panel.hbs b/addon/components/driver-form-panel.hbs index cd2737ab..0541a614 100644 --- a/addon/components/driver-form-panel.hbs +++ b/addon/components/driver-form-panel.hbs @@ -61,58 +61,81 @@
-
- - - + +
+ + +
+
+ {{this.user.name}} +
+
+
{{model.name}}
+
{{n-a model.phone}}
+
+
+
+
+
+ {{#if this.driver.user}} +
+ + + - - - + + + - - - + + + +
+ {{/if}} +
- - - + +
+ + + - - - + + + - - - {{model.name}} - - + + + {{model.name}} + + - - - {{model.display_name}} - - + + + {{model.display_name}} + + - - - + + + - - - + + + - -
- - {{smart-humanize status}} - -
-
- - - -
+ +
+ + {{smart-humanize status}} + +
+
+ + + +
+ diff --git a/addon/components/driver-form-panel.js b/addon/components/driver-form-panel.js index 6ac0178a..1c2cea4d 100644 --- a/addon/components/driver-form-panel.js +++ b/addon/components/driver-form-panel.js @@ -16,6 +16,7 @@ export default class DriverFormPanelComponent extends Component { * @service fetch */ @service fetch; + /** * @service intl */ @@ -46,6 +47,11 @@ export default class DriverFormPanelComponent extends Component { */ @service contextPanel; + /** + * @service modalsManager + */ + @service modalsManager; + /** * Overlay context. * @type {any} @@ -70,6 +76,60 @@ export default class DriverFormPanelComponent extends Component { */ @tracked coordinatesInputComponent; + /** + * Action to create a new user quickly + * + * @memberof DriverFormPanelComponent + */ + userAccountActionButtons = [ + { + text: 'Create new user', + icon: 'user-plus', + size: 'xs', + onClick: () => { + const user = this.store.createRecord('user', { + status: 'pending', + type: 'user', + }); + + this.modalsManager.show('modals/user-form', { + title: 'Create a new user', + user, + uploadNewPhoto: (file) => { + this.fetch.uploadFile.perform( + file, + { + path: `uploads/${this.currentUser.companyId}/users/${user.slug}`, + key_uuid: user.id, + key_type: 'user', + type: 'user_photo', + }, + (uploadedFile) => { + user.setProperties({ + avatar_uuid: uploadedFile.id, + avatar_url: uploadedFile.url, + avatar: uploadedFile, + }); + } + ); + }, + confirm: (modal) => { + modal.startLoading(); + + return user + .save() + .then(() => { + this.notifications.success('New user created successfully!'); + }) + .catch((error) => { + this.notifications.serverError(error); + }); + }, + }); + }, + }, + ]; + /** * Constructs the component and applies initial state. */ diff --git a/addon/components/driver-panel/details.hbs b/addon/components/driver-panel/details.hbs index 91eada29..bf559292 100644 --- a/addon/components/driver-panel/details.hbs +++ b/addon/components/driver-panel/details.hbs @@ -1,44 +1,50 @@
- -
-
-
{{t "fleet-ops.common.name"}}
-
{{n-a @driver.name}}
-
-
-
{{t "fleet-ops.common.id"}}
- {{n-a @driver.public_id}} -
-
-
{{t "fleet-ops.common.internal-id"}}
-
{{n-a @driver.internal_id}}
-
-
-
{{t "fleet-ops.common.driver-license"}}
-
{{n-a @driver.drivers_license_number}}
-
-
-
{{t "fleet-ops.common.email"}}
- {{n-a @driver.email}} -
-
-
{{t "fleet-ops.common.phone"}}
- {{n-a @driver.phone}} -
-
-
{{t "fleet-ops.common.city"}}
-
{{n-a @driver.city}}
-
-
-
{{t "fleet-ops.common.country"}}
-
- +
+ +
+
+
{{t "fleet-ops.common.name"}}
+
{{n-a @driver.name}}
+
+
+
{{t "fleet-ops.common.email"}}
+ {{n-a @driver.email}} +
+
+
{{t "fleet-ops.common.phone"}}
+ {{n-a @driver.phone}}
-
-
{{t "fleet-ops.common.coordinates"}}
-
{{point-coordinates @driver.location}}
+ + +
+
+
{{t "fleet-ops.common.id"}}
+ {{n-a @driver.public_id}} +
+
+
{{t "fleet-ops.common.internal-id"}}
+
{{n-a @driver.internal_id}}
+
+
+
{{t "fleet-ops.common.driver-license"}}
+
{{n-a @driver.drivers_license_number}}
+
+
+
{{t "fleet-ops.common.city"}}
+
{{n-a @driver.city}}
+
+
+
{{t "fleet-ops.common.country"}}
+
+ +
+
+
+
{{t "fleet-ops.common.coordinates"}}
+
{{point-coordinates @driver.location}}
+
-
-
+ +
\ No newline at end of file diff --git a/server/src/Expansions/UserFilterExpansion.php b/server/src/Expansions/UserFilterExpansion.php new file mode 100644 index 00000000..f4aef0a9 --- /dev/null +++ b/server/src/Expansions/UserFilterExpansion.php @@ -0,0 +1,29 @@ +builder->whereDoesntHave('driver'); + }; + } +} diff --git a/server/src/Http/Controllers/Internal/v1/DriverController.php b/server/src/Http/Controllers/Internal/v1/DriverController.php index 4234dd68..4c76bfd0 100644 --- a/server/src/Http/Controllers/Internal/v1/DriverController.php +++ b/server/src/Http/Controllers/Internal/v1/DriverController.php @@ -142,35 +142,42 @@ public function createRecord(Request $request) function (&$request, &$input) { $input = collect($input); - $userInput = $input - ->only(['name', 'password', 'email', 'phone', 'status', 'avatar_uuid']) - ->filter() - ->toArray(); + // Get current session company + $company = Auth::getCompany(); - // handle `photo_uuid` - if (isset($input['photo_uuid']) && Str::isUuid($input['photo_uuid'])) { - $userInput['avatar_uuid'] = $input['photo_uuid']; - } + if ($input->has('user_uuid')) { + $user = User::where('uuid', $input->get('user_uuid'))->first(); + } else { + $userInput = $input + ->only(['name', 'password', 'email', 'phone', 'status', 'avatar_uuid']) + ->filter() + ->toArray(); - $input = $input - ->except(['name', 'password', 'email', 'phone', 'meta', 'avatar_uuid', 'photo_uuid']) - ->filter() - ->toArray(); + // handle `photo_uuid` + if (isset($input['photo_uuid']) && Str::isUuid($input['photo_uuid'])) { + $userInput['avatar_uuid'] = $input['photo_uuid']; + } - // Make sure password is set - if (empty($userInput['password'])) { - $userInput['password'] = Str::random(14); - } + // Make sure password is set + if (empty($userInput['password'])) { + $userInput['password'] = Str::random(14); + } - // Get current session company - $company = Auth::getCompany(); - $userInput['company_uuid'] = session('company', $company->uuid); + // Set user company + $userInput['company_uuid'] = session('company', $company->uuid); + + // Apply user infos + $userInput = User::applyUserInfoFromRequest($request, $userInput); - // Apply user infos - $userInput = User::applyUserInfoFromRequest($request, $userInput); + // Create user account + $user = User::create($userInput); + } - // Create user account - $user = User::create($userInput); + // Prepare input + $input = $input + ->except(['name', 'password', 'email', 'phone', 'meta', 'avatar_uuid', 'photo_uuid']) + ->filter() + ->toArray(); // Assign user to company if ($company) { diff --git a/server/src/Http/Requests/CreateServiceRateRequest.php b/server/src/Http/Requests/CreateServiceRateRequest.php index bf15d152..b2af73ea 100644 --- a/server/src/Http/Requests/CreateServiceRateRequest.php +++ b/server/src/Http/Requests/CreateServiceRateRequest.php @@ -2,9 +2,9 @@ namespace Fleetbase\FleetOps\Http\Requests; +use Fleetbase\FleetOps\Rules\ComputableAlgo; use Fleetbase\FleetOps\Support\Utils; use Fleetbase\Http\Requests\FleetbaseRequest; -use Fleetbase\Rules\ComputableAlgo; use Illuminate\Validation\Rule; class CreateServiceRateRequest extends FleetbaseRequest diff --git a/server/src/Http/Requests/Internal/CreateDriverRequest.php b/server/src/Http/Requests/Internal/CreateDriverRequest.php index 72267929..0b54aee2 100644 --- a/server/src/Http/Requests/Internal/CreateDriverRequest.php +++ b/server/src/Http/Requests/Internal/CreateDriverRequest.php @@ -27,9 +27,9 @@ public function rules() $isCreating = $this->isMethod('POST'); return [ - 'name' => [Rule::requiredIf($isCreating)], - 'email' => [Rule::requiredIf($isCreating), Rule::when($this->filled('email'), ['email']), Rule::when($isCreating, [Rule::unique('users')->whereNull('deleted_at')])], - 'phone' => [Rule::requiredIf($isCreating), Rule::when($isCreating, [Rule::unique('users')->whereNull('deleted_at')])], + // 'name' => [Rule::requiredIf($isCreating)], + // 'email' => [Rule::requiredIf($isCreating), Rule::when($this->filled('email'), ['email']), Rule::when($isCreating, [Rule::unique('users')->whereNull('deleted_at')])], + // 'phone' => [Rule::requiredIf($isCreating), Rule::when($isCreating, [Rule::unique('users')->whereNull('deleted_at')])], 'password' => 'nullable|string', 'country' => 'nullable|size:2', 'city' => 'nullable|string', diff --git a/server/src/Http/Resources/v1/Driver.php b/server/src/Http/Resources/v1/Driver.php index 7408d6d6..a82429b6 100644 --- a/server/src/Http/Resources/v1/Driver.php +++ b/server/src/Http/Resources/v1/Driver.php @@ -4,6 +4,7 @@ use Fleetbase\FleetOps\Support\Utils; use Fleetbase\Http\Resources\FleetbaseResource; +use Fleetbase\Http\Resources\User; use Fleetbase\LaravelMysqlSpatial\Types\Point; use Fleetbase\Support\Http; @@ -27,7 +28,7 @@ public function toArray($request) 'vendor_uuid' => $this->when(Http::isInternalRequest(), $this->vendor_uuid), 'current_job_uuid' => $this->when(Http::isInternalRequest(), $this->current_job_uuid), 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id), - 'user' => $this->when(Http::isPublicRequest(), $this->user->public_id), + 'user' => $this->when(Http::isPublicRequest(), $this->user->public_id, new User($this->user)), 'internal_id' => $this->internal_id, 'name' => $this->name, 'email' => $this->email, diff --git a/server/src/Observers/DriverObserver.php b/server/src/Observers/DriverObserver.php index a2b5aeb7..346475f5 100644 --- a/server/src/Observers/DriverObserver.php +++ b/server/src/Observers/DriverObserver.php @@ -5,8 +5,6 @@ use Fleetbase\FleetOps\Models\Driver; use Fleetbase\FleetOps\Models\Order; use Fleetbase\LaravelMysqlSpatial\Types\Point; -use Fleetbase\Models\CompanyUser; -use Fleetbase\Models\User; class DriverObserver { @@ -30,7 +28,7 @@ public function creating(Driver $driver) */ public function deleting(Driver $driver) { - // unassign the vehicle from the driver + // Unassign the vehicle from the driver $driver->vehicle_uuid = null; } @@ -41,14 +39,7 @@ public function deleting(Driver $driver) */ public function deleted(Driver $driver) { - // if the driver is deleted, delete their user account assosciated as well - if ($driver->user->companies()->count() === 1) { - User::where(['uuid' => $driver->user_uuid, 'type' => 'driver'])->delete(); - } else { - CompanyUser::where(['user_uuid' => $driver->user_uuid, 'company_uuid' => session('company')])->delete(); - } - - // also unassign them from any order they are assigned to + // Unassign them from any order they are assigned to Order::where(['driver_assigned_uuid' => $driver->uuid])->update(['driver_assigned_uuid' => null]); } } diff --git a/server/src/Rules/ComputableAlgo.php b/server/src/Rules/ComputableAlgo.php new file mode 100644 index 00000000..25e8207c --- /dev/null +++ b/server/src/Rules/ComputableAlgo.php @@ -0,0 +1,33 @@ + 0; + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return 'Algorithm provided is not computable.'; + } +} diff --git a/translations/en-us.yaml b/translations/en-us.yaml index 4b883d88..6f919654 100644 --- a/translations/en-us.yaml +++ b/translations/en-us.yaml @@ -764,18 +764,23 @@ fleet-ops: driver-card: no-fleets: No fleets driver-form-panel: - success-message: Driver ({driverName}) saved successfully. - driver-detail: View driver details - save-driver: Save Driver - create-driver: Create Driver - cancel-edit-driver: Cancel edit driver - cancel-new-driver: Cancel new driver - upload-new-photo: Upload new photo - new-driver: New Driver - vendor: Vendor - select-vehicle: Select Vehicle - driver-status: Select driver status + driver-details: Driver Details + user-account: User Account + user-account-help-text: Each driver profile needs to be connected to a specific user account. This association is essential for handling the authentication process, ensuring that each driver can securely access and manage their profile. + success-message: Driver ({driverName}) saved successfully. + driver-detail: View driver details + save-driver: Save Driver + create-driver: Create Driver + cancel-edit-driver: Cancel edit driver + cancel-new-driver: Cancel new driver + upload-new-photo: Upload new photo + new-driver: New Driver + vendor: Vendor + select-vehicle: Select Vehicle + driver-status: Select driver status driver-panel: + user-account: User Account + driver-details: Driver Details locate-button-text: Locate driver edit-button-text: Edit driver close-button-text: Close driver details From f7637d302d2567a901c73b37706657ad9d19baf1 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Tue, 30 Apr 2024 17:37:29 +0800 Subject: [PATCH 5/7] upgraded core-api dependency --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9c3f661a..258c0381 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ ], "require": { "php": "^8.0", - "fleetbase/core-api": "^1.4.18", + "fleetbase/core-api": "^1.4.20", "barryvdh/laravel-dompdf": "^2.0", "brick/geo": "0.7.2", "cknow/laravel-money": "^7.1", From e66effd58eaafecc6cfd7d641d1834c0994fb3d2 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Tue, 30 Apr 2024 17:40:39 +0800 Subject: [PATCH 6/7] handle photo upload on driver controller --- server/src/Http/Controllers/Internal/v1/DriverController.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/Http/Controllers/Internal/v1/DriverController.php b/server/src/Http/Controllers/Internal/v1/DriverController.php index 4c76bfd0..67bef43f 100644 --- a/server/src/Http/Controllers/Internal/v1/DriverController.php +++ b/server/src/Http/Controllers/Internal/v1/DriverController.php @@ -147,6 +147,10 @@ function (&$request, &$input) { if ($input->has('user_uuid')) { $user = User::where('uuid', $input->get('user_uuid'))->first(); + // handle `photo_uuid` + if ($user && $input->has('photo_uuid')) { + $user->update(['avatar_uuid' => $input->get('photo_uuid')]); + } } else { $userInput = $input ->only(['name', 'password', 'email', 'phone', 'status', 'avatar_uuid']) From 251bc3c1d896c2387bfb2099059a055802c5ce29 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Tue, 30 Apr 2024 17:42:53 +0800 Subject: [PATCH 7/7] added fleetbase fork for laravel model caching --- composer.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/composer.json b/composer.json index 258c0381..7e762cd3 100644 --- a/composer.json +++ b/composer.json @@ -42,6 +42,12 @@ "phpstan/phpstan": "^1.10.38", "symfony/var-dumper": "^5.4.29" }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/fleetbase/laravel-model-caching" + } + ], "autoload": { "psr-4": { "Fleetbase\\FleetOps\\": "server/src/",