From 57fc8697b69f9b13c4e906a092b257dc8b844bbf Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Thu, 28 Dec 2023 08:32:55 -0500 Subject: [PATCH 001/152] Create AssetExchange model, add soft deletes. --- ..._12_26_181818_create_asset_types_table.php | 1 + ..._26_181828_create_asset_statuses_table.php | 2 + ...26_181837_create_asset_locations_table.php | 1 + .../2023_12_26_181855_create_assets_table.php | 1 + ...502_create_maintenance_providers_table.php | 1 + ...12_create_maintenance_activities_table.php | 1 + ...28_131317_create_asset_exchanges_table.php | 22 +++++++++ .../inventory-management/src/Models/Asset.php | 24 ++++++++-- .../src/Models/AssetExchange.php | 45 +++++++++++++++++++ .../src/Models/AssetLocation.php | 6 ++- .../src/Models/AssetStatus.php | 12 ++++- .../src/Models/AssetType.php | 6 ++- .../src/Models/MaintenanceActivity.php | 8 ++-- .../src/Models/MaintenanceProvider.php | 2 + .../src/Models/ServiceRequestStatus.php | 1 - 15 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php create mode 100644 app-modules/inventory-management/src/Models/AssetExchange.php diff --git a/app-modules/inventory-management/database/migrations/2023_12_26_181818_create_asset_types_table.php b/app-modules/inventory-management/database/migrations/2023_12_26_181818_create_asset_types_table.php index c2d2c62e99..64a6b5b6f8 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_26_181818_create_asset_types_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_26_181818_create_asset_types_table.php @@ -45,6 +45,7 @@ public function up(): void $table->uuid('id')->primary(); $table->string('name'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_26_181828_create_asset_statuses_table.php b/app-modules/inventory-management/database/migrations/2023_12_26_181828_create_asset_statuses_table.php index c50e496550..01fe18f9cc 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_26_181828_create_asset_statuses_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_26_181828_create_asset_statuses_table.php @@ -43,8 +43,10 @@ public function up(): void { Schema::create('asset_statuses', function (Blueprint $table) { $table->uuid('id')->primary(); + $table->string('classification'); $table->string('name'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_26_181837_create_asset_locations_table.php b/app-modules/inventory-management/database/migrations/2023_12_26_181837_create_asset_locations_table.php index f3264d6e79..6409f01e97 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_26_181837_create_asset_locations_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_26_181837_create_asset_locations_table.php @@ -45,6 +45,7 @@ public function up(): void $table->uuid('id')->primary(); $table->string('name'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_26_181855_create_assets_table.php b/app-modules/inventory-management/database/migrations/2023_12_26_181855_create_assets_table.php index 57de8650b8..46ee693db6 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_26_181855_create_assets_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_26_181855_create_assets_table.php @@ -51,6 +51,7 @@ public function up(): void $table->foreignUuid('location_id')->constrained('asset_locations'); $table->timestamp('purchase_date'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_27_175502_create_maintenance_providers_table.php b/app-modules/inventory-management/database/migrations/2023_12_27_175502_create_maintenance_providers_table.php index c3ca71714d..f12366afe3 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_27_175502_create_maintenance_providers_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_27_175502_create_maintenance_providers_table.php @@ -45,6 +45,7 @@ public function up(): void $table->uuid('id')->primary(); $table->string('name'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_27_175512_create_maintenance_activities_table.php b/app-modules/inventory-management/database/migrations/2023_12_27_175512_create_maintenance_activities_table.php index 3caa469ecd..b78014de87 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_27_175512_create_maintenance_activities_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_27_175512_create_maintenance_activities_table.php @@ -55,6 +55,7 @@ public function up(): void $table->string('status')->default(MaintenanceActivityStatus::Scheduled); $table->longText('notes')->nullable(); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php new file mode 100644 index 0000000000..d474c186f1 --- /dev/null +++ b/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php @@ -0,0 +1,22 @@ +uuid('id')->primary(); + $table->foreignUuid('asset_id')->constrained('assets'); + $table->string('type'); + $table->string('performed_by_type')->nullable(); + $table->string('performed_by_id')->nullable(); + $table->string('for_type'); + $table->string('for_id'); + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index a2d9dca12d..45da1846ba 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -36,15 +36,18 @@ namespace AdvisingApp\InventoryManagement\Models; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\AssetExchangeType; use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; -use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; class Asset extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'description', @@ -75,4 +78,19 @@ public function maintenanceActivities(): HasMany { return $this->hasMany(MaintenanceActivity::class, 'asset_id'); } + + public function exchanges(): HasMany + { + return $this->hasMany(AssetExchange::class, 'asset_id'); + } + + public function checkOuts(): HasMany + { + return $this->exchanges()->where('type', AssetExchangeType::CheckOut); + } + + public function checkIns(): HasMany + { + return $this->exchanges()->where('type', AssetExchangeType::CheckIn); + } } diff --git a/app-modules/inventory-management/src/Models/AssetExchange.php b/app-modules/inventory-management/src/Models/AssetExchange.php new file mode 100644 index 0000000000..41107d7e83 --- /dev/null +++ b/app-modules/inventory-management/src/Models/AssetExchange.php @@ -0,0 +1,45 @@ + AssetExchangeType::class, + ]; + + public function asset(): BelongsTo + { + return $this->belongsTo(Asset::class, 'asset_id'); + } + + public function scopeCheckIn(Builder $query): void + { + $query->where('type', AssetExchangeType::CheckIn); + } + + public function scopeCheckOut(Builder $query): void + { + $query->where('type', AssetExchangeType::CheckOut); + } +} diff --git a/app-modules/inventory-management/src/Models/AssetLocation.php b/app-modules/inventory-management/src/Models/AssetLocation.php index 37c656e292..3bd7826ec5 100644 --- a/app-modules/inventory-management/src/Models/AssetLocation.php +++ b/app-modules/inventory-management/src/Models/AssetLocation.php @@ -36,14 +36,16 @@ namespace AdvisingApp\InventoryManagement\Models; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\Relations\HasMany; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; class AssetLocation extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'name', diff --git a/app-modules/inventory-management/src/Models/AssetStatus.php b/app-modules/inventory-management/src/Models/AssetStatus.php index da1000a351..5767cf0959 100644 --- a/app-modules/inventory-management/src/Models/AssetStatus.php +++ b/app-modules/inventory-management/src/Models/AssetStatus.php @@ -36,19 +36,27 @@ namespace AdvisingApp\InventoryManagement\Models; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\Relations\HasMany; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; class AssetStatus extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ + 'classification', 'name', ]; + protected $casts = [ + 'classification' => SystemAssetStatusClassification::class, + ]; + public function assets(): HasMany { return $this->hasMany(Asset::class, 'status_id'); diff --git a/app-modules/inventory-management/src/Models/AssetType.php b/app-modules/inventory-management/src/Models/AssetType.php index e00d56af4e..5c8c192a87 100644 --- a/app-modules/inventory-management/src/Models/AssetType.php +++ b/app-modules/inventory-management/src/Models/AssetType.php @@ -36,14 +36,16 @@ namespace AdvisingApp\InventoryManagement\Models; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\Relations\HasMany; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; class AssetType extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'name', diff --git a/app-modules/inventory-management/src/Models/MaintenanceActivity.php b/app-modules/inventory-management/src/Models/MaintenanceActivity.php index 71c75c3ad5..91c4f8c04c 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceActivity.php +++ b/app-modules/inventory-management/src/Models/MaintenanceActivity.php @@ -36,15 +36,17 @@ namespace AdvisingApp\InventoryManagement\Models; -use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus; +use App\Models\BaseModel; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; class MaintenanceActivity extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'asset_id', diff --git a/app-modules/inventory-management/src/Models/MaintenanceProvider.php b/app-modules/inventory-management/src/Models/MaintenanceProvider.php index c319b8eec9..e20ebb6c56 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceProvider.php +++ b/app-modules/inventory-management/src/Models/MaintenanceProvider.php @@ -38,12 +38,14 @@ use App\Models\BaseModel; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; class MaintenanceProvider extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'name', diff --git a/app-modules/service-management/src/Models/ServiceRequestStatus.php b/app-modules/service-management/src/Models/ServiceRequestStatus.php index 22c8749bc9..40bd3148b5 100644 --- a/app-modules/service-management/src/Models/ServiceRequestStatus.php +++ b/app-modules/service-management/src/Models/ServiceRequestStatus.php @@ -52,7 +52,6 @@ class ServiceRequestStatus extends BaseModel implements Auditable { use SoftDeletes; - use HasUuids; use AuditableTrait; protected $fillable = [ From 01a0b4970294bc120cc774db6939edd68d73161a Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Thu, 28 Dec 2023 08:33:16 -0500 Subject: [PATCH 002/152] Asset exchange type and system classification. --- .../src/Enums/AssetExchangeType.php | 50 +++++++++++++++++ .../Enums/SystemAssetStatusClassification.php | 53 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 app-modules/inventory-management/src/Enums/AssetExchangeType.php create mode 100644 app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php diff --git a/app-modules/inventory-management/src/Enums/AssetExchangeType.php b/app-modules/inventory-management/src/Enums/AssetExchangeType.php new file mode 100644 index 0000000000..9af8a53029 --- /dev/null +++ b/app-modules/inventory-management/src/Enums/AssetExchangeType.php @@ -0,0 +1,50 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Enums; + +use Filament\Support\Contracts\HasLabel; + +enum AssetExchangeType: string implements HasLabel +{ + case CheckIn = 'check_in'; + case CheckOut = 'check_out'; + + public function getLabel(): ?string + { + return $this->name; + } +} diff --git a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php new file mode 100644 index 0000000000..d1b153e600 --- /dev/null +++ b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php @@ -0,0 +1,53 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Enums; + +use Filament\Support\Contracts\HasLabel; + +enum SystemAssetStatusClassification: string implements HasLabel +{ + case Available = 'available'; + + case Unavailable = 'unavailable'; + + case Custom = 'custom'; + + public function getLabel(): ?string + { + return $this->name; + } +} From a15892d4dfb1dfb2ae746cd1aa5052e610e5567b Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Thu, 28 Dec 2023 08:42:56 -0500 Subject: [PATCH 003/152] Add policies. --- .../src/Policies/AssetExchangePolicy.php | 100 ++++++++++++++++++ .../src/Policies/AssetLocationPolicy.php | 100 ++++++++++++++++++ .../src/Policies/AssetPolicy.php | 100 ++++++++++++++++++ .../src/Policies/AssetStatusPolicy.php | 100 ++++++++++++++++++ .../src/Policies/AssetTypePolicy.php | 100 ++++++++++++++++++ .../Policies/MaintenanceActivityPolicy.php | 100 ++++++++++++++++++ .../Policies/MaintenanceProviderPolicy.php | 100 ++++++++++++++++++ 7 files changed, 700 insertions(+) create mode 100644 app-modules/inventory-management/src/Policies/AssetExchangePolicy.php create mode 100644 app-modules/inventory-management/src/Policies/AssetLocationPolicy.php create mode 100644 app-modules/inventory-management/src/Policies/AssetPolicy.php create mode 100644 app-modules/inventory-management/src/Policies/AssetStatusPolicy.php create mode 100644 app-modules/inventory-management/src/Policies/AssetTypePolicy.php create mode 100644 app-modules/inventory-management/src/Policies/MaintenanceActivityPolicy.php create mode 100644 app-modules/inventory-management/src/Policies/MaintenanceProviderPolicy.php diff --git a/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php b/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php new file mode 100644 index 0000000000..031744e4f1 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetExchange; + +class AssetExchangePolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_exchange.view-any', + denyResponse: 'You do not have permission to view asset exchanges.' + ); + } + + public function view(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.view', "asset_exchange.{$assetExchange->id}.view"], + denyResponse: 'You do not have permission to view this asset exchange.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_exchange.create', + denyResponse: 'You do not have permission to create asset exchanges.' + ); + } + + public function update(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.update', "asset_exchange.{$assetExchange->id}.update"], + denyResponse: 'You do not have permission to update this asset exchange.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.delete', "asset_exchange.{$assetExchange->id}.delete"], + denyResponse: 'You do not have permission to delete this asset exchange.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.restore', "asset_exchange.{$assetExchange->id}.restore"], + denyResponse: 'You do not have permission to restore this asset exchange.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.force-delete', "asset_exchange.{$assetExchange->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset exchange.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/AssetLocationPolicy.php b/app-modules/inventory-management/src/Policies/AssetLocationPolicy.php new file mode 100644 index 0000000000..f6500dc256 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetLocationPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetLocation; + +class AssetLocationPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_location.view-any', + denyResponse: 'You do not have permission to view asset locations.' + ); + } + + public function view(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.view', "asset_location.{$assetLocation->id}.view"], + denyResponse: 'You do not have permission to view this asset location.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_location.create', + denyResponse: 'You do not have permission to create asset locations.' + ); + } + + public function update(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.update', "asset_location.{$assetLocation->id}.update"], + denyResponse: 'You do not have permission to update this asset location.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.delete', "asset_location.{$assetLocation->id}.delete"], + denyResponse: 'You do not have permission to delete this asset location.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.restore', "asset_location.{$assetLocation->id}.restore"], + denyResponse: 'You do not have permission to restore this asset location.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.force-delete', "asset_location.{$assetLocation->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset location.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/AssetPolicy.php b/app-modules/inventory-management/src/Policies/AssetPolicy.php new file mode 100644 index 0000000000..ec0b8e5140 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\Asset; + +class AssetPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset.view-any', + denyResponse: 'You do not have permission to view assets.' + ); + } + + public function view(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.view', "asset.{$asset->id}.view"], + denyResponse: 'You do not have permission to view this asset.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset.create', + denyResponse: 'You do not have permission to create assets.' + ); + } + + public function update(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.update', "asset.{$asset->id}.update"], + denyResponse: 'You do not have permission to update this asset.' + ); + } + + public function delete(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.delete', "asset.{$asset->id}.delete"], + denyResponse: 'You do not have permission to delete this asset.' + ); + } + + public function restore(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.restore', "asset.{$asset->id}.restore"], + denyResponse: 'You do not have permission to restore this asset.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.force-delete', "asset.{$asset->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/AssetStatusPolicy.php b/app-modules/inventory-management/src/Policies/AssetStatusPolicy.php new file mode 100644 index 0000000000..1e973501b9 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetStatusPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetStatus; + +class AssetStatusPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_status.view-any', + denyResponse: 'You do not have permission to view asset statuses.' + ); + } + + public function view(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.view', "asset_status.{$assetStatus->id}.view"], + denyResponse: 'You do not have permission to view this asset status.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_status.create', + denyResponse: 'You do not have permission to create asset statuses.' + ); + } + + public function update(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.update', "asset_status.{$assetStatus->id}.update"], + denyResponse: 'You do not have permission to update this asset status.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.delete', "asset_status.{$assetStatus->id}.delete"], + denyResponse: 'You do not have permission to delete this asset status.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.restore', "asset_status.{$assetStatus->id}.restore"], + denyResponse: 'You do not have permission to restore this asset status.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.force-delete', "asset_status.{$assetStatus->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset status.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/AssetTypePolicy.php b/app-modules/inventory-management/src/Policies/AssetTypePolicy.php new file mode 100644 index 0000000000..952f9140ad --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetTypePolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetType; + +class AssetTypePolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_type.view-any', + denyResponse: 'You do not have permission to view asset types.' + ); + } + + public function view(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.view', "asset_type.{$assetType->id}.view"], + denyResponse: 'You do not have permission to view this asset type.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_type.create', + denyResponse: 'You do not have permission to create asset types.' + ); + } + + public function update(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.update', "asset_type.{$assetType->id}.update"], + denyResponse: 'You do not have permission to update this asset type.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.delete', "asset_type.{$assetType->id}.delete"], + denyResponse: 'You do not have permission to delete this asset type.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.restore', "asset_type.{$assetType->id}.restore"], + denyResponse: 'You do not have permission to restore this asset type.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.force-delete', "asset_type.{$assetType->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset type.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/MaintenanceActivityPolicy.php b/app-modules/inventory-management/src/Policies/MaintenanceActivityPolicy.php new file mode 100644 index 0000000000..fe5911d6c3 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/MaintenanceActivityPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\MaintenanceActivity; + +class MaintenanceActivityPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'maintenance_activity.view-any', + denyResponse: 'You do not have permission to view maintenance activities.' + ); + } + + public function view(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.view', "maintenance_activity.{$maintenanceActivity->id}.view"], + denyResponse: 'You do not have permission to view this maintenance activity.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'maintenance_activity.create', + denyResponse: 'You do not have permission to create maintenance activities.' + ); + } + + public function update(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.update', "maintenance_activity.{$maintenanceActivity->id}.update"], + denyResponse: 'You do not have permission to update this maintenance activity.' + ); + } + + public function delete(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.delete', "maintenance_activity.{$maintenanceActivity->id}.delete"], + denyResponse: 'You do not have permission to delete this maintenance activity.' + ); + } + + public function restore(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.restore', "maintenance_activity.{$maintenanceActivity->id}.restore"], + denyResponse: 'You do not have permission to restore this maintenance activity.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.force-delete', "maintenance_activity.{$maintenanceActivity->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this maintenance activity.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/MaintenanceProviderPolicy.php b/app-modules/inventory-management/src/Policies/MaintenanceProviderPolicy.php new file mode 100644 index 0000000000..fab3fb32a0 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/MaintenanceProviderPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\MaintenanceProvider; + +class MaintenanceProviderPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'maintenance_provider.view-any', + denyResponse: 'You do not have permission to view maintenance providers.' + ); + } + + public function view(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.view', "maintenance_provider.{$maintenanceProvider->id}.view"], + denyResponse: 'You do not have permission to view this maintenance provider.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'maintenance_provider.create', + denyResponse: 'You do not have permission to create maintenance providers.' + ); + } + + public function update(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.update', "maintenance_provider.{$maintenanceProvider->id}.update"], + denyResponse: 'You do not have permission to update this maintenance provider.' + ); + } + + public function delete(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.delete', "maintenance_provider.{$maintenanceProvider->id}.delete"], + denyResponse: 'You do not have permission to delete this maintenance provider.' + ); + } + + public function restore(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.restore', "maintenance_provider.{$maintenanceProvider->id}.restore"], + denyResponse: 'You do not have permission to restore this maintenance provider.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.force-delete', "maintenance_provider.{$maintenanceProvider->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this maintenance provider.' + ); + } +} From e1997b46bcc1469eb13f31444020d56cce948610 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Tue, 2 Jan 2024 13:45:43 -0500 Subject: [PATCH 004/152] Utilize two model system. --- .../factories/AssetCheckInFactory.php | 45 ++++++++++++++ .../factories/AssetCheckOutFactory.php | 53 ++++++++++++++++ .../database/factories/AssetStatusFactory.php | 2 + ...8_174428_create_asset_check_ins_table.php} | 13 ++-- ...8_174437_create_asset_check_outs_table.php | 25 ++++++++ .../database/seeders/AssetSeeder.php | 11 +++- .../database/seeders/AssetStatusSeeder.php | 8 ++- .../src/Enums/AssetExchangeType.php | 50 --------------- .../inventory-management/src/Models/Asset.php | 22 +++---- .../src/Models/AssetCheckIn.php | 59 ++++++++++++++++++ .../src/Models/AssetCheckOut.php | 61 +++++++++++++++++++ .../src/Models/AssetExchange.php | 45 -------------- .../src/Models/AssetStatus.php | 8 +-- .../InventoryManagementServiceProvider.php | 4 ++ 14 files changed, 285 insertions(+), 121 deletions(-) create mode 100644 app-modules/inventory-management/database/factories/AssetCheckInFactory.php create mode 100644 app-modules/inventory-management/database/factories/AssetCheckOutFactory.php rename app-modules/inventory-management/database/migrations/{2023_12_28_131317_create_asset_exchanges_table.php => 2023_12_28_174428_create_asset_check_ins_table.php} (52%) create mode 100644 app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php delete mode 100644 app-modules/inventory-management/src/Enums/AssetExchangeType.php create mode 100644 app-modules/inventory-management/src/Models/AssetCheckIn.php create mode 100644 app-modules/inventory-management/src/Models/AssetCheckOut.php delete mode 100644 app-modules/inventory-management/src/Models/AssetExchange.php diff --git a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php new file mode 100644 index 0000000000..793d21673d --- /dev/null +++ b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php @@ -0,0 +1,45 @@ + + */ +class AssetCheckInFactory extends Factory +{ + public function definition(): array + { + $checkedOutBy = User::factory()->create(); + + return [ + 'asset_id' => Asset::factory(), + 'checked_in_by_type' => $checkedOutBy->getMorphClass(), + 'checked_in_by_id' => $checkedOutBy->getKey(), + 'checked_in_from_type' => fake()->randomElement([ + (new Student())->getMorphClass(), + (new Prospect())->getMorphClass(), + ]), + 'checked_in_from_id' => function (array $attributes) { + $checkedInFromClass = Relation::getMorphedModel($attributes['checked_in_from_type']); + + /** @var Student|Prospect $senderModel */ + $checkedInFromModel = new $checkedInFromClass(); + + $checkedInFromModel = $checkedInFromClass === Student::class + ? Student::inRandomOrder()->first() ?? Student::factory()->create() + : $checkedInFromModel::factory()->create(); + + return $checkedInFromModel->getKey(); + }, + 'checked_in_at' => fake()->dateTimeBetween('-1 year', 'now'), + 'notes' => fake()->paragraph(), + ]; + } +} diff --git a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php new file mode 100644 index 0000000000..f4e1d061c3 --- /dev/null +++ b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php @@ -0,0 +1,53 @@ + + */ +class AssetCheckOutFactory extends Factory +{ + public function definition(): array + { + $checkedOutBy = User::factory()->create(); + + return [ + 'asset_id' => Asset::factory(), + // TODO Add variance to this column so that some check outs do not have corresponding check ins + 'asset_check_in_id' => null, + 'checked_out_by_type' => $checkedOutBy->getMorphClass(), + 'checked_out_by_id' => $checkedOutBy->getKey(), + 'checked_out_to_type' => fake()->randomElement([ + (new Student())->getMorphClass(), + (new Prospect())->getMorphClass(), + ]), + 'checked_out_to_id' => function (array $attributes) { + $checkedOutToClass = Relation::getMorphedModel($attributes['checked_out_to_type']); + + /** @var Student|Prospect $senderModel */ + $checkedOutToModel = new $checkedOutToClass(); + + $checkedOutToModel = $checkedOutToClass === Student::class + ? Student::inRandomOrder()->first() ?? Student::factory()->create() + : $checkedOutToModel::factory()->create(); + + return $checkedOutToModel->getKey(); + }, + 'checked_out_at' => fake()->dateTimeBetween('-1 year', 'now'), + 'expected_check_in_at' => function (array $attributes) { + $checkedOutAt = Carbon::parse($attributes['checked_out_at']); + + return fake()->dateTimeBetween($checkedOutAt->addDays(1), $checkedOutAt->addDays(50)); + }, + 'notes' => fake()->paragraph(), + ]; + } +} diff --git a/app-modules/inventory-management/database/factories/AssetStatusFactory.php b/app-modules/inventory-management/database/factories/AssetStatusFactory.php index 75ea75e646..412da2f51c 100644 --- a/app-modules/inventory-management/database/factories/AssetStatusFactory.php +++ b/app-modules/inventory-management/database/factories/AssetStatusFactory.php @@ -37,6 +37,7 @@ namespace AdvisingApp\InventoryManagement\Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\AdvisingApp\InventoryManagement\Models\AssetStatus> @@ -46,6 +47,7 @@ class AssetStatusFactory extends Factory public function definition(): array { return [ + 'classification' => SystemAssetStatusClassification::Unavailable, 'name' => fake()->word(), ]; } diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php similarity index 52% rename from app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php rename to app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php index d474c186f1..08c435f4bb 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php @@ -7,14 +7,15 @@ return new class () extends Migration { public function up(): void { - Schema::create('asset_exchanges', function (Blueprint $table) { + Schema::create('asset_check_ins', function (Blueprint $table) { $table->uuid('id')->primary(); $table->foreignUuid('asset_id')->constrained('assets'); - $table->string('type'); - $table->string('performed_by_type')->nullable(); - $table->string('performed_by_id')->nullable(); - $table->string('for_type'); - $table->string('for_id'); + $table->string('checked_in_by_type')->nullable(); + $table->string('checked_in_by_id')->nullable(); + $table->string('checked_in_from_type'); + $table->string('checked_in_from_id'); + $table->timestamp('checked_in_at'); + $table->longText('notes')->nullable(); $table->timestamps(); $table->softDeletes(); }); diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php new file mode 100644 index 0000000000..a37094dcd4 --- /dev/null +++ b/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php @@ -0,0 +1,25 @@ +uuid('id')->primary(); + $table->foreignUuid('asset_id')->constrained('assets'); + $table->foreignUuid('asset_check_in_id')->nullable()->constrained('asset_check_ins'); + $table->string('checked_out_by_type')->nullable(); + $table->string('checked_out_by_id')->nullable(); + $table->string('checked_out_to_type'); + $table->string('checked_out_to_id'); + $table->timestamp('checked_out_at'); + $table->timestamp('expected_check_in_at')->nullable(); + $table->longText('notes')->nullable(); + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/inventory-management/database/seeders/AssetSeeder.php b/app-modules/inventory-management/database/seeders/AssetSeeder.php index d5638da918..4baa6c6f61 100644 --- a/app-modules/inventory-management/database/seeders/AssetSeeder.php +++ b/app-modules/inventory-management/database/seeders/AssetSeeder.php @@ -38,6 +38,8 @@ use Illuminate\Database\Seeder; use AdvisingApp\InventoryManagement\Models\Asset; +use AdvisingApp\InventoryManagement\Models\AssetCheckIn; +use AdvisingApp\InventoryManagement\Models\AssetCheckOut; use AdvisingApp\InventoryManagement\Models\MaintenanceActivity; class AssetSeeder extends Seeder @@ -48,13 +50,18 @@ public function run(): void ->count(10) ->create() ->each(function (Asset $asset) { - $maintenanceActivitiesCount = rand(0, 10); + $entityCount = rand(0, 10); - for ($i = 0; $i < $maintenanceActivitiesCount; $i++) { + for ($i = 0; $i < $entityCount; $i++) { MaintenanceActivity::factory() ->randomizeState() ->for($asset, 'asset') ->create(); + + AssetCheckOut::factory() + ->has(AssetCheckIn::factory(), 'checkIn') + ->for($asset, 'asset') + ->create(); } }); } diff --git a/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php b/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php index 5ae922356b..16ddff9f5e 100644 --- a/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php +++ b/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php @@ -38,6 +38,7 @@ use Illuminate\Database\Seeder; use AdvisingApp\InventoryManagement\Models\AssetStatus; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; class AssetStatusSeeder extends Seeder { @@ -46,16 +47,17 @@ public function run(): void AssetStatus::factory() ->createMany( [ + [ + 'name' => 'Available', + 'classification' => SystemAssetStatusClassification::Available, + ], ['name' => 'In Use'], - ['name' => 'Available'], ['name' => 'Under Maintenance'], ['name' => 'Out of Service'], ['name' => 'Reserved'], - ['name' => 'On Loan'], ['name' => 'Awaiting Repair'], ['name' => 'Lost'], ['name' => 'Damaged'], - ['name' => 'New'], ] ); } diff --git a/app-modules/inventory-management/src/Enums/AssetExchangeType.php b/app-modules/inventory-management/src/Enums/AssetExchangeType.php deleted file mode 100644 index 9af8a53029..0000000000 --- a/app-modules/inventory-management/src/Enums/AssetExchangeType.php +++ /dev/null @@ -1,50 +0,0 @@ - - - Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. - - Advising App™ is licensed under the Elastic License 2.0. For more details, - see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. - - Notice: - - - You may not provide the software to third parties as a hosted or managed - service, where the service provides users with access to any substantial set of - the features or functionality of the software. - - You may not move, change, disable, or circumvent the license key functionality - in the software, and you may not remove or obscure any functionality in the - software that is protected by the license key. - - You may not alter, remove, or obscure any licensing, copyright, or other notices - of the licensor in the software. Any use of the licensor’s trademarks is subject - to applicable law. - - Canyon GBS LLC respects the intellectual property rights of others and expects the - same in return. Canyon GBS™ and Advising App™ are registered trademarks of - Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks - vigorously. - - The software solution, including services, infrastructure, and code, is offered as a - Software as a Service (SaaS) by Canyon GBS LLC. - - Use of this software implies agreement to the license terms and conditions as stated - in the Elastic License 2.0. - - For more information or inquiries please visit our website at - https://www.canyongbs.com or contact us via email at legal@canyongbs.com. - - -*/ - -namespace AdvisingApp\InventoryManagement\Enums; - -use Filament\Support\Contracts\HasLabel; - -enum AssetExchangeType: string implements HasLabel -{ - case CheckIn = 'check_in'; - case CheckOut = 'check_out'; - - public function getLabel(): ?string - { - return $this->name; - } -} diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index 45da1846ba..fa678c544a 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -36,13 +36,13 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; -use AdvisingApp\InventoryManagement\Enums\AssetExchangeType; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; class Asset extends BaseModel implements Auditable { @@ -79,18 +79,18 @@ public function maintenanceActivities(): HasMany return $this->hasMany(MaintenanceActivity::class, 'asset_id'); } - public function exchanges(): HasMany + public function checkOuts(): HasMany { - return $this->hasMany(AssetExchange::class, 'asset_id'); + return $this->hasMany(AssetCheckOut::class, 'asset_id'); } - public function checkOuts(): HasMany + public function checkIns(): HasMany { - return $this->exchanges()->where('type', AssetExchangeType::CheckOut); + return $this->hasMany(AssetCheckIn::class, 'asset_id'); } - public function checkIns(): HasMany + public function isAvailable(): bool { - return $this->exchanges()->where('type', AssetExchangeType::CheckIn); + return $this->status->classification === SystemAssetStatusClassification::Available; } } diff --git a/app-modules/inventory-management/src/Models/AssetCheckIn.php b/app-modules/inventory-management/src/Models/AssetCheckIn.php new file mode 100644 index 0000000000..edd1f6dca2 --- /dev/null +++ b/app-modules/inventory-management/src/Models/AssetCheckIn.php @@ -0,0 +1,59 @@ + 'datetime', + ]; + + public function asset(): BelongsTo + { + return $this->belongsTo(Asset::class, 'asset_id'); + } + + public function checkedInBy(): MorphTo + { + return $this->morphTo( + name: 'checked_in_by', + type: 'checked_in_by_type', + id: 'checked_in_by_id', + ); + } + + public function checkedInFrom(): MorphTo + { + return $this->morphTo( + name: 'checked_in_from', + type: 'checked_in_from_type', + id: 'checked_in_from_id', + ); + } + + public function checkOut(): HasOne + { + return $this->hasOne(AssetCheckOut::class); + } +} diff --git a/app-modules/inventory-management/src/Models/AssetCheckOut.php b/app-modules/inventory-management/src/Models/AssetCheckOut.php new file mode 100644 index 0000000000..dad253e8c2 --- /dev/null +++ b/app-modules/inventory-management/src/Models/AssetCheckOut.php @@ -0,0 +1,61 @@ + 'datetime', + 'expected_check_in_at' => 'datetime', + ]; + + public function asset(): BelongsTo + { + return $this->belongsTo(Asset::class, 'asset_id'); + } + + public function checkedOutBy(): MorphTo + { + return $this->morphTo( + name: 'checked_out_by', + type: 'checked_out_by_type', + id: 'checked_out_by_id', + ); + } + + public function checkedOutTo(): MorphTo + { + return $this->morphTo( + name: 'checked_out_to', + type: 'checked_out_to_type', + id: 'checked_out_to_id', + ); + } + + public function checkIn(): BelongsTo + { + return $this->belongsTo(AssetCheckIn::class); + } +} diff --git a/app-modules/inventory-management/src/Models/AssetExchange.php b/app-modules/inventory-management/src/Models/AssetExchange.php deleted file mode 100644 index 41107d7e83..0000000000 --- a/app-modules/inventory-management/src/Models/AssetExchange.php +++ /dev/null @@ -1,45 +0,0 @@ - AssetExchangeType::class, - ]; - - public function asset(): BelongsTo - { - return $this->belongsTo(Asset::class, 'asset_id'); - } - - public function scopeCheckIn(Builder $query): void - { - $query->where('type', AssetExchangeType::CheckIn); - } - - public function scopeCheckOut(Builder $query): void - { - $query->where('type', AssetExchangeType::CheckOut); - } -} diff --git a/app-modules/inventory-management/src/Models/AssetStatus.php b/app-modules/inventory-management/src/Models/AssetStatus.php index 5767cf0959..57308169a6 100644 --- a/app-modules/inventory-management/src/Models/AssetStatus.php +++ b/app-modules/inventory-management/src/Models/AssetStatus.php @@ -36,12 +36,12 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; -use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasMany; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; class AssetStatus extends BaseModel implements Auditable { diff --git a/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php b/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php index ee84ace5b0..52739c94ec 100644 --- a/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php +++ b/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php @@ -43,6 +43,8 @@ use AdvisingApp\InventoryManagement\Models\AssetType; use AdvisingApp\InventoryManagement\Models\AssetStatus; use AdvisingApp\Authorization\AuthorizationRoleRegistry; +use AdvisingApp\InventoryManagement\Models\AssetCheckIn; +use AdvisingApp\InventoryManagement\Models\AssetCheckOut; use AdvisingApp\InventoryManagement\Models\AssetLocation; use AdvisingApp\Authorization\AuthorizationPermissionRegistry; use AdvisingApp\InventoryManagement\InventoryManagementPlugin; @@ -59,6 +61,8 @@ public function register() public function boot() { Relation::morphMap([ + 'asset_check_in' => AssetCheckIn::class, + 'asset_check_out' => AssetCheckOut::class, 'asset_location' => AssetLocation::class, 'asset_status' => AssetStatus::class, 'asset_type' => AssetType::class, From c60bc2124ea66d1cf4a82095b8370c262bfb26d9 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 13:56:54 -0500 Subject: [PATCH 005/152] Setup the separate column licenses Signed-off-by: Kevin Ullyott --- .../LicenseManagement/LicenseLimitsData.php | 5 +++-- app/Filament/Pages/ManageLicenseSettings.php | 12 ++++++++---- .../2023_11_29_192230_create_license_settings.php | 5 +++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/app/DataTransferObjects/LicenseManagement/LicenseLimitsData.php b/app/DataTransferObjects/LicenseManagement/LicenseLimitsData.php index 21d04a3972..884e07af48 100644 --- a/app/DataTransferObjects/LicenseManagement/LicenseLimitsData.php +++ b/app/DataTransferObjects/LicenseManagement/LicenseLimitsData.php @@ -44,8 +44,9 @@ class LicenseLimitsData extends Data { public function __construct( - public int $crmSeats, - public int $analyticsSeats, + public int $conversationalAiSeats, + public int $retentionCrmSeats, + public int $recruitmentCrmSeats, public int $emails, public int $sms, public string $resetDate, diff --git a/app/Filament/Pages/ManageLicenseSettings.php b/app/Filament/Pages/ManageLicenseSettings.php index 60c226c862..b6c94c6005 100644 --- a/app/Filament/Pages/ManageLicenseSettings.php +++ b/app/Filament/Pages/ManageLicenseSettings.php @@ -96,12 +96,16 @@ public function form(Form $form): Form ->columns() ->schema( [ - TextInput::make('data.limits.crmSeats') - ->label('CRM Seats') + TextInput::make('data.limits.conversationalAiSeats') + ->label('Artificial Intelligence Seats') ->numeric() ->required(), - TextInput::make('data.limits.analyticsSeats') - ->label('Analytics Seats') + TextInput::make('data.limits.retentionCrmSeats') + ->label('Student Success / Retention Seats') + ->numeric() + ->required(), + TextInput::make('data.limits.recruitmentCrmSeats') + ->label('Recruitment CRM Seats') ->numeric() ->required(), TextInput::make('data.limits.emails') diff --git a/database/settings/2023_11_29_192230_create_license_settings.php b/database/settings/2023_11_29_192230_create_license_settings.php index 7f487669cc..cfb3e6bbb4 100644 --- a/database/settings/2023_11_29_192230_create_license_settings.php +++ b/database/settings/2023_11_29_192230_create_license_settings.php @@ -55,8 +55,9 @@ public function up(): void 'end_date' => now()->addYear(), ], 'limits' => [ - 'crm_seats' => 30, - 'analytics_seats' => 15, + 'conversational_ai_seats' => 50, + 'retention_crm_seats' => 25, + 'recruitment_crm_seats' => 10, 'emails' => 1000, 'sms' => 1000, 'reset_date' => now()->format('m-d'), From fd2998c7c8e3865f6ea38025ec0be5f3ea1b6302 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 16:31:00 -0500 Subject: [PATCH 006/152] Update LicenseSettings with addon changes Signed-off-by: Kevin Ullyott --- .../LicenseManagement/LicenseAddonsData.php | 10 +++++----- app/Filament/Pages/ManageLicenseSettings.php | 20 +++++++++---------- ...3_11_29_192230_create_license_settings.php | 10 +++++----- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/DataTransferObjects/LicenseManagement/LicenseAddonsData.php b/app/DataTransferObjects/LicenseManagement/LicenseAddonsData.php index 4f131c4bdf..add8d67d58 100644 --- a/app/DataTransferObjects/LicenseManagement/LicenseAddonsData.php +++ b/app/DataTransferObjects/LicenseManagement/LicenseAddonsData.php @@ -44,13 +44,13 @@ class LicenseAddonsData extends Data { public function __construct( + public bool $onlineForms, + public bool $onlineSurveys, public bool $onlineAdmissions, - public bool $realtimeChat, - public bool $dynamicForms, - public bool $conductSurveys, - public bool $personalAssistant, public bool $serviceManagement, public bool $knowledgeManagement, - public bool $studentAndProspectPortal, + public bool $eventManagement, + public bool $realtimeChat, + public bool $mobileApps, ) {} } diff --git a/app/Filament/Pages/ManageLicenseSettings.php b/app/Filament/Pages/ManageLicenseSettings.php index b6c94c6005..60ac1625a5 100644 --- a/app/Filament/Pages/ManageLicenseSettings.php +++ b/app/Filament/Pages/ManageLicenseSettings.php @@ -125,22 +125,22 @@ public function form(Form $form): Form ->columns() ->schema( [ + Toggle::make('data.addons.onlineForms') + ->label('Online Forms'), + Toggle::make('data.addons.onlineSurveys') + ->label('Online Surveys'), Toggle::make('data.addons.onlineAdmissions') ->label('Online Admissions'), - Toggle::make('data.addons.realtimeChat') - ->label('Realtime Chat'), - Toggle::make('data.addons.dynamicForms') - ->label('Dynamic Forms'), - Toggle::make('data.addons.conductSurveys') - ->label('Conduct Surveys'), - Toggle::make('data.addons.personalAssistant') - ->label('Personal Assistant'), Toggle::make('data.addons.serviceManagement') ->label('Service Management'), Toggle::make('data.addons.knowledgeManagement') ->label('Knowledge Management'), - Toggle::make('data.addons.studentAndProspectPortal') - ->label('Student and Prospect Portal'), + Toggle::make('data.addons.eventManagement') + ->label('Event Management'), + Toggle::make('data.addons.realtimeChat') + ->label('Realtime Chat'), + Toggle::make('data.addons.mobileApps') + ->label('Mobile Apps'), ] ), ]); diff --git a/database/settings/2023_11_29_192230_create_license_settings.php b/database/settings/2023_11_29_192230_create_license_settings.php index cfb3e6bbb4..3d3af1ade5 100644 --- a/database/settings/2023_11_29_192230_create_license_settings.php +++ b/database/settings/2023_11_29_192230_create_license_settings.php @@ -63,14 +63,14 @@ public function up(): void 'reset_date' => now()->format('m-d'), ], 'addons' => [ + 'online_forms' => true, + 'online_surveys' => true, 'online_admissions' => true, - 'realtime_chat' => true, - 'dynamic_forms' => true, - 'conduct_surveys' => true, - 'personal_assistant' => true, 'service_management' => true, 'knowledge_management' => true, - 'student_and_prospect_portal' => true, + 'event_management' => true, + 'realtime_chat' => true, + 'mobileApps' => true, ], ] ); From 454b72865babfeadc108e8a35fe38b15c9ad148b Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 17:00:00 -0500 Subject: [PATCH 007/152] Update and remove old references Signed-off-by: Kevin Ullyott --- .../src/Filament/Pages/ManageAiSettings.php | 9 ++++++--- .../src/Filament/Pages/PersonalAssistant.php | 8 ++++---- .../Policies/AssistantChatMessageLogPolicy.php | 6 ++---- .../Pages/ListConsentAgreements.php | 5 +++-- .../src/Policies/ConsentAgreementPolicy.php | 6 ++---- app-modules/form/src/Policies/FormPolicy.php | 2 +- .../src/Filament/Pages/ManagePortalSettings.php | 4 ++-- .../Middleware/EnsureSurveysFeatureIsActive.php | 2 +- app/Enums/Feature.php | 15 +++++++-------- .../Resources/UserResource/Pages/ListUsers.php | 13 ++++++------- app/Policies/UserPolicy.php | 10 ---------- 11 files changed, 34 insertions(+), 46 deletions(-) diff --git a/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php b/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php index f2b7567936..5297dc5be9 100644 --- a/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php +++ b/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php @@ -37,7 +37,6 @@ namespace AdvisingApp\Assistant\Filament\Pages; use App\Models\User; -use App\Enums\Feature; use Filament\Forms\Form; use Filament\Pages\SettingsPage; use Filament\Forms\Components\Textarea; @@ -58,7 +57,9 @@ public static function shouldRegisterNavigation(): bool /** @var User $user */ $user = auth()->user(); - return $user->can([Feature::PersonalAssistant->getGateName(), 'assistant.access_ai_settings']); + // TODO: Feature/License Gate | if has AI License + + return $user->can(['assistant.access_ai_settings']); } public function mount(): void @@ -66,7 +67,9 @@ public function mount(): void /** @var User $user */ $user = auth()->user(); - abort_unless($user->can([Feature::PersonalAssistant->getGateName(), 'assistant.access_ai_settings']), 403); + // TODO: Feature/License Gate | if has AI License + + abort_unless($user->can(['assistant.access_ai_settings']), 403); parent::mount(); } diff --git a/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php b/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php index 1683ec61f8..286e93fd51 100644 --- a/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php +++ b/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php @@ -37,7 +37,6 @@ namespace AdvisingApp\Assistant\Filament\Pages; use App\Models\User; -use App\Enums\Feature; use Filament\Forms\Get; use Filament\Pages\Page; use Livewire\Attributes\On; @@ -49,7 +48,6 @@ use Filament\Actions\StaticAction; use Illuminate\Support\Collection; use Filament\Forms\Components\Radio; -use Illuminate\Support\Facades\Gate; use Filament\Forms\Components\Select; use Filament\Support\Enums\Alignment; use Filament\Support\Enums\ActionSize; @@ -110,12 +108,14 @@ public static function shouldRegisterNavigation(): bool /** @var User $user */ $user = auth()->user(); - return Gate::check(Feature::PersonalAssistant->getGateName()) && $user->can('assistant.access'); + // TODO: Feature/License Gate | if has AI License + + return $user->can('assistant.access'); } public function mount(): void { - $this->authorize(Feature::PersonalAssistant->getGateName()); + // TODO: Feature/License Gate | if has AI License $this->authorize('assistant.access'); $this->consentAgreement = ConsentAgreement::where('type', ConsentAgreementType::AzureOpenAI)->first(); diff --git a/app-modules/assistant/src/Policies/AssistantChatMessageLogPolicy.php b/app-modules/assistant/src/Policies/AssistantChatMessageLogPolicy.php index 5addc25240..f0489b5ea9 100644 --- a/app-modules/assistant/src/Policies/AssistantChatMessageLogPolicy.php +++ b/app-modules/assistant/src/Policies/AssistantChatMessageLogPolicy.php @@ -36,7 +36,6 @@ namespace AdvisingApp\Assistant\Policies; -use App\Enums\Feature; use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; use App\Concerns\FeatureAccessEnforcedPolicyBefore; @@ -90,8 +89,7 @@ public function forceDelete(Authenticatable $authenticatable, AssistantChatMessa protected function requiredFeatures(): array { - return [ - Feature::PersonalAssistant, - ]; + // TODO: Feature/License Gate | if has AI License + return []; } } diff --git a/app-modules/consent/src/Filament/Resources/ConsentAgreementResource/Pages/ListConsentAgreements.php b/app-modules/consent/src/Filament/Resources/ConsentAgreementResource/Pages/ListConsentAgreements.php index 60a743fc28..93bc6bc87c 100644 --- a/app-modules/consent/src/Filament/Resources/ConsentAgreementResource/Pages/ListConsentAgreements.php +++ b/app-modules/consent/src/Filament/Resources/ConsentAgreementResource/Pages/ListConsentAgreements.php @@ -37,7 +37,6 @@ namespace AdvisingApp\Consent\Filament\Resources\ConsentAgreementResource\Pages; use App\Models\User; -use App\Enums\Feature; use Filament\Forms\Form; use Filament\Tables\Table; use App\Filament\Columns\IdColumn; @@ -72,7 +71,9 @@ public static function shouldRegisterNavigation(array $parameters = []): bool /** @var User $user */ $user = auth()->user(); - return $user->can([Feature::PersonalAssistant->getGateName(), 'consent_agreement.view-any', 'consent_agreement.*.view', 'consent_agreement.*.update']); + // TODO: Feature/License Gate | if has AI License, may need to prevent mount as well + + return $user->can(['consent_agreement.view-any', 'consent_agreement.*.view', 'consent_agreement.*.update']); } public function form(Form $form): Form diff --git a/app-modules/consent/src/Policies/ConsentAgreementPolicy.php b/app-modules/consent/src/Policies/ConsentAgreementPolicy.php index c1fab30e1c..1f8a71b82f 100644 --- a/app-modules/consent/src/Policies/ConsentAgreementPolicy.php +++ b/app-modules/consent/src/Policies/ConsentAgreementPolicy.php @@ -36,7 +36,6 @@ namespace AdvisingApp\Consent\Policies; -use App\Enums\Feature; use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; use AdvisingApp\Consent\Models\ConsentAgreement; @@ -93,8 +92,7 @@ public function forceDelete(Authenticatable $authenticatable, ConsentAgreement $ protected function requiredFeatures(): array { - return [ - Feature::PersonalAssistant, - ]; + // TODO: Feature/License Gate | if has AI License + return []; } } diff --git a/app-modules/form/src/Policies/FormPolicy.php b/app-modules/form/src/Policies/FormPolicy.php index d6d72f6300..14c33e8645 100644 --- a/app-modules/form/src/Policies/FormPolicy.php +++ b/app-modules/form/src/Policies/FormPolicy.php @@ -105,6 +105,6 @@ public function forceDelete(Authenticatable $authenticatable, Form $form): Respo protected function requiredFeatures(): array { - return [Feature::DynamicForms]; + return [Feature::OnlineForms]; } } diff --git a/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php b/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php index 3b49e86f09..ae234b0eab 100644 --- a/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php +++ b/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php @@ -135,12 +135,12 @@ public function form(Form $form): Form ->label('Files and Documents'), Toggle::make('has_forms') ->label('Forms') - ->disabled(! Gate::check(Feature::DynamicForms->getGateName())) + ->disabled(! Gate::check(Feature::OnlineForms->getGateName())) ->hintIcon(fn (Toggle $component) => $component->isDisabled() ? 'heroicon-m-lock-closed' : null) ->hintIconTooltip('Forms are not a part of your current subscription.'), Toggle::make('has_surveys') ->label('Surveys') - ->disabled(! Gate::check(Feature::ConductSurveys->getGateName())) + ->disabled(! Gate::check(Feature::OnlineSurveys->getGateName())) ->hintIcon(fn (Toggle $component) => $component->isDisabled() ? 'heroicon-m-lock-closed' : null) ->hintIconTooltip('Surveys are not a part of your current subscription.'), ]) diff --git a/app-modules/survey/src/Http/Middleware/EnsureSurveysFeatureIsActive.php b/app-modules/survey/src/Http/Middleware/EnsureSurveysFeatureIsActive.php index 2c0d37c894..9c211af70a 100644 --- a/app-modules/survey/src/Http/Middleware/EnsureSurveysFeatureIsActive.php +++ b/app-modules/survey/src/Http/Middleware/EnsureSurveysFeatureIsActive.php @@ -45,7 +45,7 @@ class EnsureSurveysFeatureIsActive { public function handle(Request $request, Closure $next): Response { - if (! app(LicenseSettings::class)->data->addons->conductSurveys) { + if (! app(LicenseSettings::class)->data->addons->onlineSurveys) { return response()->json(['error' => 'Surveys is not enabled.'], 403); } diff --git a/app/Enums/Feature.php b/app/Enums/Feature.php index 188146291c..a7e8914c0a 100644 --- a/app/Enums/Feature.php +++ b/app/Enums/Feature.php @@ -42,21 +42,20 @@ enum Feature: string { - case OnlineAdmissions = 'online-admissions'; - - case RealtimeChat = 'realtime-chat'; - - case DynamicForms = 'dynamic-forms'; + case OnlineForms = 'online-forms'; - case ConductSurveys = 'conduct-surveys'; + case OnlineSurveys = 'online-surveys'; - case PersonalAssistant = 'personal-assistant'; + case OnlineAdmissions = 'online-admissions'; case ServiceManagement = 'service-management'; case KnowledgeManagement = 'knowledge-management'; - case StudentAndProspectPortal = 'student-and-prospect-portal'; + case EventManagement = 'event-management'; + case RealtimeChat = 'realtime-chat'; + + case MobileApps = 'mobile-apps'; public function generateGate(): void { diff --git a/app/Filament/Resources/UserResource/Pages/ListUsers.php b/app/Filament/Resources/UserResource/Pages/ListUsers.php index 287c793daa..2ec58227e3 100644 --- a/app/Filament/Resources/UserResource/Pages/ListUsers.php +++ b/app/Filament/Resources/UserResource/Pages/ListUsers.php @@ -36,10 +36,7 @@ namespace App\Filament\Resources\UserResource\Pages; -use App\Models\User; -use App\Settings\LicenseSettings; use Filament\Actions\CreateAction; -use Illuminate\Support\HtmlString; use App\Filament\Resources\UserResource; use Filament\Resources\Pages\ListRecords; use Illuminate\Contracts\Support\Htmlable; @@ -50,10 +47,12 @@ class ListUsers extends ListRecords public function getSubheading(): string | Htmlable | null { - return new HtmlString(view('crm-seats', [ - 'count' => User::count(), - 'max' => app(LicenseSettings::class)->data->limits->crmSeats, - ])->render()); + // TODO: Either remove or change to show all possible seats + + //return new HtmlString(view('crm-seats', [ + // 'count' => User::count(), + // 'max' => app(LicenseSettings::class)->data->limits->crmSeats, + //])->render()); } protected function getHeaderActions(): array diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index 120acf24fc..93eb31eb33 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -38,9 +38,7 @@ use App\Models\User; use App\Models\Authenticatable; -use App\Settings\LicenseSettings; use Illuminate\Auth\Access\Response; -use App\Support\FeatureAccessResponse; class UserPolicy { @@ -62,10 +60,6 @@ public function view(Authenticatable $authenticatable, User $model): Response public function create(Authenticatable $authenticatable): Response { - if (User::count() >= app(LicenseSettings::class)->data->limits->crmSeats) { - return FeatureAccessResponse::deny('You have reached the maximum number of users allowed by your license.'); - } - return $authenticatable->canOrElse( abilities: 'user.create', denyResponse: 'You do not have permission to create users.' @@ -90,10 +84,6 @@ public function delete(Authenticatable $authenticatable, User $model): Response public function restore(Authenticatable $authenticatable, User $model): Response { - if (User::count() >= app(LicenseSettings::class)->data->limits->crmSeats) { - return FeatureAccessResponse::deny('You have reached the maximum number of users allowed by your license.'); - } - return $authenticatable->canOrElse( abilities: ['user.*.restore', "user.{$model->id}.restore"], denyResponse: 'You do not have permission to restore this user.' From 4714ef4b5b700cf1be901159eaae2247b26b679f Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 17:11:56 -0500 Subject: [PATCH 008/152] Fix bug with ListUsers header Signed-off-by: Kevin Ullyott --- app/Filament/Resources/UserResource/Pages/ListUsers.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Filament/Resources/UserResource/Pages/ListUsers.php b/app/Filament/Resources/UserResource/Pages/ListUsers.php index 2ec58227e3..3edd59677c 100644 --- a/app/Filament/Resources/UserResource/Pages/ListUsers.php +++ b/app/Filament/Resources/UserResource/Pages/ListUsers.php @@ -53,6 +53,8 @@ public function getSubheading(): string | Htmlable | null // 'count' => User::count(), // 'max' => app(LicenseSettings::class)->data->limits->crmSeats, //])->render()); + + return null; } protected function getHeaderActions(): array From a109bb88b47de308c2ca45b51d4244706d46c5df Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Tue, 2 Jan 2024 17:21:04 -0500 Subject: [PATCH 009/152] wip --- app-modules/analytics/composer.json | 26 ++++++ .../config/permissions/api/custom.php | 15 +-- .../config/permissions/web/custom.php | 37 ++++++++ .../config/roles/api/analytics_management.php | 37 ++++++++ .../config/roles/web/analytics_management.php | 46 ++++++++++ .../factories/AnalyticsResourceFactory.php | 38 ++++++++ .../AnalyticsResourceSourceFactory.php | 22 +++++ ...reate_analytics_resource_sources_table.php | 17 ++++ ...72758_create_analytics_resources_table.php | 25 +++++ .../seeders/AnalyticsResourceSeeder.php | 16 ++++ .../seeders/AnalyticsResourceSourceSeeder.php | 20 ++++ app-modules/analytics/src/AnalyticsPlugin.php | 58 ++++++++++++ .../src/Enums/AnalyticsResourceCategory.php | 19 ++++ .../Resources/AnalyticsResourceResource.php | 38 ++++++++ .../Pages/CreateAnalyticsResource.php | 52 +++++++++++ .../Pages/EditAnalyticsResource.php | 60 ++++++++++++ .../Pages/ListAnalyticsResources.php | 81 +++++++++++++++++ .../AnalyticsResourceSourceResource.php | 37 ++++++++ .../Pages/CreateAnalyticsResourceSource.php | 25 +++++ .../Pages/EditAnalyticsResourceSource.php | 35 +++++++ .../Pages/ListAnalyticsResourceSources.php | 53 +++++++++++ .../Pages/ViewAnalyticsResourceSource.php | 34 +++++++ .../src/Models/AnalyticsResource.php | 42 +++++++++ .../src/Models/AnalyticsResourceSource.php | 24 +++++ .../Providers/AnalyticsServiceProvider.php | 91 +++++++++++++++++++ app-modules/analytics/tests/.gitkeep | 0 composer.json | 1 + composer.lock | 39 +++++++- database/seeders/DatabaseSeeder.php | 7 +- 29 files changed, 976 insertions(+), 19 deletions(-) create mode 100644 app-modules/analytics/composer.json rename app/Filament/Pages/AnalyticsPortal.php => app-modules/analytics/config/permissions/api/custom.php (81%) create mode 100644 app-modules/analytics/config/permissions/web/custom.php create mode 100644 app-modules/analytics/config/roles/api/analytics_management.php create mode 100644 app-modules/analytics/config/roles/web/analytics_management.php create mode 100644 app-modules/analytics/database/factories/AnalyticsResourceFactory.php create mode 100644 app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php create mode 100644 app-modules/analytics/database/migrations/2024_01_02_165407_create_analytics_resource_sources_table.php create mode 100644 app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php create mode 100644 app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php create mode 100644 app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php create mode 100644 app-modules/analytics/src/AnalyticsPlugin.php create mode 100644 app-modules/analytics/src/Enums/AnalyticsResourceCategory.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ViewAnalyticsResourceSource.php create mode 100644 app-modules/analytics/src/Models/AnalyticsResource.php create mode 100644 app-modules/analytics/src/Models/AnalyticsResourceSource.php create mode 100644 app-modules/analytics/src/Providers/AnalyticsServiceProvider.php create mode 100644 app-modules/analytics/tests/.gitkeep diff --git a/app-modules/analytics/composer.json b/app-modules/analytics/composer.json new file mode 100644 index 0000000000..c90f3340de --- /dev/null +++ b/app-modules/analytics/composer.json @@ -0,0 +1,26 @@ +{ + "name": "canyon-gbs/analytics", + "description": "", + "type": "library", + "version": "1.0", + "license": "proprietary", + "require": { + "filament/filament": "^3.0.0" + }, + "autoload": { + "psr-4": { + "AdvisingApp\\Analytics\\": "src/", + "AdvisingApp\\Analytics\\Tests\\": "tests/", + "AdvisingApp\\Analytics\\Database\\Factories\\": "database/factories/", + "AdvisingApp\\Analytics\\Database\\Seeders\\": "database/seeders/" + } + }, + "minimum-stability": "dev", + "extra": { + "laravel": { + "providers": [ + "AdvisingApp\\Analytics\\Providers\\AnalyticsServiceProvider" + ] + } + } +} diff --git a/app/Filament/Pages/AnalyticsPortal.php b/app-modules/analytics/config/permissions/api/custom.php similarity index 81% rename from app/Filament/Pages/AnalyticsPortal.php rename to app-modules/analytics/config/permissions/api/custom.php index 6b0149815e..2c194089ba 100644 --- a/app/Filament/Pages/AnalyticsPortal.php +++ b/app-modules/analytics/config/permissions/api/custom.php @@ -34,17 +34,4 @@ */ -namespace App\Filament\Pages; - -use Filament\Pages\Page; - -class AnalyticsPortal extends Page -{ - protected static ?string $navigationIcon = 'heroicon-o-arrow-trending-up'; - - protected static string $view = 'filament.pages.coming-soon'; - - protected static ?string $navigationGroup = 'Data and Analytics'; - - protected static ?int $navigationSort = 1; -} +return []; diff --git a/app-modules/analytics/config/permissions/web/custom.php b/app-modules/analytics/config/permissions/web/custom.php new file mode 100644 index 0000000000..2c194089ba --- /dev/null +++ b/app-modules/analytics/config/permissions/web/custom.php @@ -0,0 +1,37 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +return []; diff --git a/app-modules/analytics/config/roles/api/analytics_management.php b/app-modules/analytics/config/roles/api/analytics_management.php new file mode 100644 index 0000000000..2c194089ba --- /dev/null +++ b/app-modules/analytics/config/roles/api/analytics_management.php @@ -0,0 +1,37 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +return []; diff --git a/app-modules/analytics/config/roles/web/analytics_management.php b/app-modules/analytics/config/roles/web/analytics_management.php new file mode 100644 index 0000000000..cbbeacab9d --- /dev/null +++ b/app-modules/analytics/config/roles/web/analytics_management.php @@ -0,0 +1,46 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +return [ + 'model' => [ + 'analytics_resource_source' => [ + '*', + ], + 'analytics_resource' => [ + '*', + ], + ], +]; diff --git a/app-modules/analytics/database/factories/AnalyticsResourceFactory.php b/app-modules/analytics/database/factories/AnalyticsResourceFactory.php new file mode 100644 index 0000000000..8b69e09d73 --- /dev/null +++ b/app-modules/analytics/database/factories/AnalyticsResourceFactory.php @@ -0,0 +1,38 @@ + + */ +class AnalyticsResourceFactory extends Factory +{ + /** + * @return array + */ + public function definition(): array + { + return [ + 'name' => str(fake()->unique()->word())->ucfirst(), + 'description' => fake()->sentences(asText: true), + 'url' => fake()->optional()->url(), + 'category' => fake()->randomElement(AnalyticsResourceCategory::cases()), + 'is_active' => fake()->boolean(), + 'is_included_in_data_portal' => fake()->boolean(), + ]; + } + + public function configure(): AnalyticsResourceFactory|Factory + { + return $this->afterMaking(function (AnalyticsResource $analyticsResource) { + $analyticsResource + ->source() + ->associate(fake()->optional()->randomElement([AnalyticsResourceSource::inRandomOrder()->first() ?? AnalyticsResourceSource::factory()->create()])); + }); + } +} diff --git a/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php b/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php new file mode 100644 index 0000000000..dd0dafcdbc --- /dev/null +++ b/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php @@ -0,0 +1,22 @@ + + */ +class AnalyticsResourceSourceFactory extends Factory +{ + /** + * @return array + */ + public function definition(): array + { + return [ + 'name' => str(fake()->unique()->word())->ucfirst(), + ]; + } +} diff --git a/app-modules/analytics/database/migrations/2024_01_02_165407_create_analytics_resource_sources_table.php b/app-modules/analytics/database/migrations/2024_01_02_165407_create_analytics_resource_sources_table.php new file mode 100644 index 0000000000..b3a8069a5a --- /dev/null +++ b/app-modules/analytics/database/migrations/2024_01_02_165407_create_analytics_resource_sources_table.php @@ -0,0 +1,17 @@ +uuid('id')->primary(); + $table->string('name')->unique(); + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php b/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php new file mode 100644 index 0000000000..327bb0c4f1 --- /dev/null +++ b/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php @@ -0,0 +1,25 @@ +uuid('id')->primary(); + + $table->string('name')->unique(); + $table->longText('description')->nullable(); + $table->string('url')->nullable(); + $table->string('category'); + $table->boolean('is_active'); + $table->boolean('is_included_in_data_portal'); + + $table->foreignUuid('source_id')->nullable()->constrained('analytics_resource_sources'); + + $table->timestamps(); + }); + } +}; diff --git a/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php b/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php new file mode 100644 index 0000000000..1eba30282c --- /dev/null +++ b/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php @@ -0,0 +1,16 @@ +count(25) + ->create(); + } +} diff --git a/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php b/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php new file mode 100644 index 0000000000..b9e1d26511 --- /dev/null +++ b/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php @@ -0,0 +1,20 @@ +createMany([ + ['name' => 'Power BI'], + ['name' => 'Tableau'], + ['name' => 'Spreadsheet'], + ]); + } +} diff --git a/app-modules/analytics/src/AnalyticsPlugin.php b/app-modules/analytics/src/AnalyticsPlugin.php new file mode 100644 index 0000000000..f879de3d3f --- /dev/null +++ b/app-modules/analytics/src/AnalyticsPlugin.php @@ -0,0 +1,58 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Analytics; + +use Filament\Panel; +use Filament\Contracts\Plugin; + +class AnalyticsPlugin implements Plugin +{ + public function getId(): string + { + return 'analytics'; + } + + public function register(Panel $panel): void + { + $panel->discoverResources( + in: __DIR__ . '/Filament/Resources', + for: 'AdvisingApp\\Analytics\\Filament\\Resources' + ); + } + + public function boot(Panel $panel): void {} +} diff --git a/app-modules/analytics/src/Enums/AnalyticsResourceCategory.php b/app-modules/analytics/src/Enums/AnalyticsResourceCategory.php new file mode 100644 index 0000000000..ea55b15827 --- /dev/null +++ b/app-modules/analytics/src/Enums/AnalyticsResourceCategory.php @@ -0,0 +1,19 @@ +name)->headline(); + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php new file mode 100644 index 0000000000..21004506fc --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php @@ -0,0 +1,38 @@ + ListAnalyticsResources::route('/'), + 'create' => CreateAnalyticsResource::route('/create'), + 'edit' => EditAnalyticsResource::route('/{record}/edit'), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php new file mode 100644 index 0000000000..ac32db271e --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php @@ -0,0 +1,52 @@ +schema([ + Section::make() + ->columns() + ->schema([ + TextInput::make('name') + ->required() + ->string() + ->unique(ignoreRecord: true), + Textarea::make('description') + ->nullable() + ->string(), + Select::make('category') + ->required() + ->options(AnalyticsResourceCategory::class) + ->enum(AnalyticsResourceCategory::class), + Select::make('source') + ->relationship(titleAttribute: 'name'), + TextInput::make('Url') + ->nullable() + ->url(), + SpatieMediaLibraryFileUpload::make('thumbnail') + ->nullable(), + Checkbox::make('is_active') + ->label('Active'), + Checkbox::make('is_included_in_data_portal') + ->label('Included in Data Portal'), + ]), + ]); + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php new file mode 100644 index 0000000000..ab81ee88e7 --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php @@ -0,0 +1,60 @@ +schema([ + Section::make() + ->columns() + ->schema([ + TextInput::make('name') + ->required() + ->string() + ->unique(ignoreRecord: true), + Textarea::make('description') + ->nullable() + ->string(), + Select::make('category') + ->required() + ->options(AnalyticsResourceCategory::class) + ->enum(AnalyticsResourceCategory::class), + Select::make('source') + ->relationship(titleAttribute: 'name'), + TextInput::make('Url') + ->nullable() + ->url(), + SpatieMediaLibraryFileUpload::make('thumbnail') + ->nullable(), + Checkbox::make('is_active') + ->label('Active'), + Checkbox::make('is_included_in_data_portal') + ->label('Included in Data Portal'), + ]), + ]); + } + + protected function getHeaderActions(): array + { + return [ + DeleteAction::make(), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php new file mode 100644 index 0000000000..90563b4fef --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php @@ -0,0 +1,81 @@ +columns([ + IdColumn::make(), + TextColumn::make('name') + ->sortable() + ->searchable(), + TextColumn::make('description') + ->searchable() + ->limit(60), + TextColumn::make('url') + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('source.name') + ->sortable() + ->searchable(), + TextColumn::make('category') + ->sortable(), + IconColumn::make('is_active') + ->boolean() + ->label('Active') + ->sortable(), + IconColumn::make('is_included_in_data_portal') + ->boolean() + ->label('Included in Data Portal') + ->sortable(), + ]) + ->filters([ + TernaryFilter::make('is_active') + ->label('Active'), + TernaryFilter::make('is_included_in_data_portal') + ->label('Included in Data Portal'), + SelectFilter::make('category') + ->options(AnalyticsResourceCategory::class) + ->multiple(), + SelectFilter::make('source') + ->relationship('source', 'name') + ->preload() + ->multiple(), + ]) + ->actions([ + EditAction::make(), + ]) + ->bulkActions([ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]); + } + + protected function getHeaderActions(): array + { + return [ + CreateAction::make(), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php new file mode 100644 index 0000000000..ea55f45616 --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php @@ -0,0 +1,37 @@ + ListAnalyticsResourceSources::route('/'), + 'create' => CreateAnalyticsResourceSource::route('/create'), + 'view' => ViewAnalyticsResourceSource::route('/{record}'), + 'edit' => EditAnalyticsResourceSource::route('/{record}/edit'), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php new file mode 100644 index 0000000000..2a179bea12 --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php @@ -0,0 +1,25 @@ +schema([ + TextInput::make('name') + ->required() + ->string() + ->unique(), + ]); + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php new file mode 100644 index 0000000000..fbab96ae45 --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php @@ -0,0 +1,35 @@ +schema([ + TextInput::make('name') + ->required() + ->string() + ->unique(ignoreRecord: true), + ]); + } + + protected function getHeaderActions(): array + { + return [ + ViewAction::make(), + DeleteAction::make(), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php new file mode 100644 index 0000000000..a94ab9dd01 --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php @@ -0,0 +1,53 @@ +columns([ + IdColumn::make(), + TextColumn::make('name') + ->searchable() + ->sortable(), + TextColumn::make('resources_count') + ->label('# of Analytics Resources') + ->counts('resources') + ->sortable(), + ]) + ->filters([ + ]) + ->actions([ + ViewAction::make(), + EditAction::make(), + ]) + ->bulkActions([ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]); + } + + protected function getHeaderActions(): array + { + return [ + CreateAction::make(), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ViewAnalyticsResourceSource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ViewAnalyticsResourceSource.php new file mode 100644 index 0000000000..58d0f9d66a --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ViewAnalyticsResourceSource.php @@ -0,0 +1,34 @@ +schema([ + Section::make() + ->schema([ + TextEntry::make('name'), + ]) + ->columns(), + ]); + } + + protected function getHeaderActions(): array + { + return [ + EditAction::make(), + ]; + } +} diff --git a/app-modules/analytics/src/Models/AnalyticsResource.php b/app-modules/analytics/src/Models/AnalyticsResource.php new file mode 100644 index 0000000000..88efbdfe55 --- /dev/null +++ b/app-modules/analytics/src/Models/AnalyticsResource.php @@ -0,0 +1,42 @@ + AnalyticsResourceCategory::class, + 'is_active' => 'boolean', + 'is_included_in_data_portal' => 'boolean', + ]; + + public function registerMediaCollections(): void + { + $this->addMediaCollection('thumbnail') + ->singleFile(); + } + + public function source(): BelongsTo + { + return $this->belongsTo(AnalyticsResourceSource::class); + } +} diff --git a/app-modules/analytics/src/Models/AnalyticsResourceSource.php b/app-modules/analytics/src/Models/AnalyticsResourceSource.php new file mode 100644 index 0000000000..4f7a3447ee --- /dev/null +++ b/app-modules/analytics/src/Models/AnalyticsResourceSource.php @@ -0,0 +1,24 @@ +hasMany(AnalyticsResource::class, 'source_id'); + } +} diff --git a/app-modules/analytics/src/Providers/AnalyticsServiceProvider.php b/app-modules/analytics/src/Providers/AnalyticsServiceProvider.php new file mode 100644 index 0000000000..0487400ab6 --- /dev/null +++ b/app-modules/analytics/src/Providers/AnalyticsServiceProvider.php @@ -0,0 +1,91 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Analytics\Providers; + +use AdvisingApp\Analytics\Models\AnalyticsResource; +use Filament\Panel; +use Illuminate\Support\ServiceProvider; +use AdvisingApp\Analytics\AnalyticsPlugin; +use Illuminate\Database\Eloquent\Relations\Relation; +use AdvisingApp\Authorization\AuthorizationRoleRegistry; +use AdvisingApp\Analytics\Models\AnalyticsResourceSource; +use AdvisingApp\Authorization\AuthorizationPermissionRegistry; + +class AnalyticsServiceProvider extends ServiceProvider +{ + public function register(): void + { + Panel::configureUsing(fn (Panel $panel) => $panel->plugin(new AnalyticsPlugin())); + } + + public function boot(): void + { + Relation::morphMap([ + 'analytics_resource_source' => AnalyticsResourceSource::class, + 'analytics_resource' => AnalyticsResource::class, + ]); + + $this->registerRolesAndPermissions(); + } + + protected function registerRolesAndPermissions(): void + { + $permissionRegistry = app(AuthorizationPermissionRegistry::class); + + $permissionRegistry->registerApiPermissions( + module: 'analytics', + path: 'permissions/api/custom' + ); + + $permissionRegistry->registerWebPermissions( + module: 'analytics', + path: 'permissions/web/custom' + ); + + $roleRegistry = app(AuthorizationRoleRegistry::class); + + $roleRegistry->registerApiRoles( + module: 'analytics', + path: 'roles/api' + ); + + $roleRegistry->registerWebRoles( + module: 'analytics', + path: 'roles/web' + ); + } +} diff --git a/app-modules/analytics/tests/.gitkeep b/app-modules/analytics/tests/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/composer.json b/composer.json index 9ac9e26dce..5e20816f02 100644 --- a/composer.json +++ b/composer.json @@ -51,6 +51,7 @@ "canyon-gbs/advising-app-theme": "*", "canyon-gbs/advising-app-timeline": "*", "canyon-gbs/advising-app-webhook": "*", + "canyon-gbs/analytics": "*", "canyon-gbs/inventory-management": "*", "composer/composer": "^2.6.4", "filament/filament": "^3.1", diff --git a/composer.lock b/composer.lock index 7f43c3aa26..3545dbac72 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4135a59df44c5333303e7a1b6f1ff947", + "content-hash": "c6799688b6b1dc6fe5f3e65ef7767624", "packages": [ { "name": "amphp/amp", @@ -2379,6 +2379,41 @@ "relative": true } }, + { + "name": "canyon-gbs/analytics", + "version": "1.0", + "dist": { + "type": "path", + "url": "app-modules/analytics", + "reference": "ee7fa00ee78ce3e31c49566043aaf89cca68ad6b" + }, + "require": { + "filament/filament": "^3.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "AdvisingApp\\Analytics\\Providers\\AnalyticsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "AdvisingApp\\Analytics\\": "src/", + "AdvisingApp\\Analytics\\Tests\\": "tests/", + "AdvisingApp\\Analytics\\Database\\Factories\\": "database/factories/", + "AdvisingApp\\Analytics\\Database\\Seeders\\": "database/seeders/" + } + }, + "license": [ + "proprietary" + ], + "transport-options": { + "symlink": true, + "relative": true + } + }, { "name": "canyon-gbs/inventory-management", "version": "1.0", @@ -21202,5 +21237,5 @@ "ext-pdo": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index ea3c4a913d..07be7b1d92 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -46,19 +46,18 @@ use AdvisingApp\Division\Database\Seeders\DivisionSeeder; use AdvisingApp\Prospect\Database\Seeders\ProspectSeeder; use AdvisingApp\MeetingCenter\Database\Seeders\EventSeeder; -use AdvisingApp\Engagement\Database\Seeders\EngagementSeeder; use AdvisingApp\Interaction\Database\Seeders\InteractionSeeder; use AdvisingApp\Prospect\Database\Seeders\ProspectSourceSeeder; use AdvisingApp\Prospect\Database\Seeders\ProspectStatusSeeder; use AdvisingApp\Consent\Database\Seeders\ConsentAgreementSeeder; use AdvisingApp\InventoryManagement\Database\Seeders\AssetSeeder; -use AdvisingApp\Engagement\Database\Seeders\EngagementResponseSeeder; +use AdvisingApp\Analytics\Database\Seeders\AnalyticsResourceSeeder; use AdvisingApp\Authorization\Console\Commands\SyncRolesAndPermissions; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseItemSeeder; use AdvisingApp\ServiceManagement\Database\Seeders\ServiceRequestSeeder; +use AdvisingApp\Analytics\Database\Seeders\AnalyticsResourceSourceSeeder; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseStatusSeeder; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseQualitySeeder; -use AdvisingApp\Engagement\Database\Seeders\DemoEducatableEngagementSeeder; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseCategorySeeder; use AdvisingApp\ServiceManagement\Database\Seeders\ServiceRequestTypeSeeder; use AdvisingApp\Application\Database\Seeders\ApplicationSubmissionStateSeeder; @@ -111,6 +110,8 @@ public function run(): void ...AssetSeeder::metadataSeeders(), AssetSeeder::class, MaintenanceProviderSeeder::class, + AnalyticsResourceSourceSeeder::class, + AnalyticsResourceSeeder::class, ]); } } From 6dd1dff81ab0f01d79255719ca70875abd7a156c Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 18:52:21 -0500 Subject: [PATCH 010/152] Create a license management processes Signed-off-by: Kevin Ullyott --- .../config/roles/web/license_management.php | 43 ++++++++++++++ ...024_01_02_225406_create_licenses_table.php | 20 +++++++ .../authorization/src/Enums/LicenseType.php | 40 +++++++++++++ .../authorization/src/Models/License.php | 24 ++++++++ .../src/Rules/LicenseTypeUsageRule.php | 19 ++++++ app/Filament/Resources/UserResource.php | 2 + .../LicensesRelationManager.php | 59 +++++++++++++++++++ app/Models/User.php | 6 ++ 8 files changed, 213 insertions(+) create mode 100644 app-modules/authorization/config/roles/web/license_management.php create mode 100644 app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php create mode 100644 app-modules/authorization/src/Enums/LicenseType.php create mode 100644 app-modules/authorization/src/Models/License.php create mode 100644 app-modules/authorization/src/Rules/LicenseTypeUsageRule.php create mode 100644 app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php diff --git a/app-modules/authorization/config/roles/web/license_management.php b/app-modules/authorization/config/roles/web/license_management.php new file mode 100644 index 0000000000..ac07305bb6 --- /dev/null +++ b/app-modules/authorization/config/roles/web/license_management.php @@ -0,0 +1,43 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +return [ + 'model' => [ + 'license' => [ + '*', + ], + ], +]; diff --git a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php new file mode 100644 index 0000000000..475a106a2a --- /dev/null +++ b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php @@ -0,0 +1,20 @@ +uuid('id')->primary(); + $table->foreignUuid('user_id')->constrained('users')->cascadeOnDelete(); + $table->string('type'); + $table->timestamps(); + $table->softDeletes(); + + $table->unique(['user_id', 'type']); + }); + } +}; diff --git a/app-modules/authorization/src/Enums/LicenseType.php b/app-modules/authorization/src/Enums/LicenseType.php new file mode 100644 index 0000000000..b8d00a8293 --- /dev/null +++ b/app-modules/authorization/src/Enums/LicenseType.php @@ -0,0 +1,40 @@ + 'Conversational AI', + LicenseType::RetentionCrm => 'Retention CRM', + LicenseType::RecruitmentCrm => 'Recruitment CRM', + }; + } + + public function hasAvailableLicenses(): bool + { + $totalLicensesInUse = License::query()->where('type', $this)->count(); + + $licenseSettings = app(LicenseSettings::class); + + $licenseLimit = match ($this) { + LicenseType::ConversationalAi => $licenseSettings->data->limits->conversationalAiSeats, + LicenseType::RetentionCrm => $licenseSettings->data->limits->retentionCrmSeats, + LicenseType::RecruitmentCrm => $licenseSettings->data->limits->recruitmentCrmSeats, + }; + + return $totalLicensesInUse < $licenseLimit; + } +} diff --git a/app-modules/authorization/src/Models/License.php b/app-modules/authorization/src/Models/License.php new file mode 100644 index 0000000000..2bd1c9e128 --- /dev/null +++ b/app-modules/authorization/src/Models/License.php @@ -0,0 +1,24 @@ + LicenseType::class, + ]; + + public function user(): BelongsTo + { + return $this->belongsTo(User::class, 'user_id'); + } +} diff --git a/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php b/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php new file mode 100644 index 0000000000..9eaf5bb06f --- /dev/null +++ b/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php @@ -0,0 +1,19 @@ +hasAvailableLicenses()) { + $fail("There are no available {$licenseType->getLabel()} licenses."); + } + } +} diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php index 4ef2fd43ee..e799e88286 100644 --- a/app/Filament/Resources/UserResource.php +++ b/app/Filament/Resources/UserResource.php @@ -55,6 +55,7 @@ use App\Filament\Resources\UserResource\Pages\ListUsers; use App\Filament\Resources\UserResource\Pages\CreateUser; use App\Filament\Resources\UserResource\RelationManagers\RolesRelationManager; +use App\Filament\Resources\UserResource\RelationManagers\LicensesRelationManager; use App\Filament\Resources\UserResource\RelationManagers\RoleGroupsRelationManager; use App\Filament\Resources\UserResource\RelationManagers\PermissionsRelationManager; @@ -128,6 +129,7 @@ public static function getRelations(): array RoleGroupsRelationManager::class, RolesRelationManager::class, PermissionsRelationManager::class, + LicensesRelationManager::class, ]; } diff --git a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php new file mode 100644 index 0000000000..0e83fbc945 --- /dev/null +++ b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php @@ -0,0 +1,59 @@ +schema([ + Select::make('type') + ->options(LicenseType::class) + ->enum(LicenseType::class) + ->rule(Rule::unique('licenses', 'type')->where('user_id', $this->getOwnerRecord()->getKey())) + ->rule(new LicenseTypeUsageRule()) + ->required(), + ]); + } + + public function table(Table $table): Table + { + return $table + ->recordTitleAttribute('type') + ->columns([ + TextColumn::make('type'), + TextColumn::make('created_at') + ->dateTime(), + ]) + ->headerActions([ + CreateAction::make(), + ]) + ->actions([ + DeleteAction::make(), + ]) + ->bulkActions([ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]) + ->emptyStateActions([ + CreateAction::make(), + ]); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 798a326208..d68162d962 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -53,6 +53,7 @@ use Filament\Models\Contracts\FilamentUser; use Spatie\MediaLibrary\InteractsWithMedia; use Illuminate\Database\Eloquent\SoftDeletes; +use AdvisingApp\Authorization\Models\License; use AdvisingApp\MeetingCenter\Models\Calendar; use AdvisingApp\Assistant\Models\AssistantChat; use AdvisingApp\StudentDataModel\Models\Student; @@ -195,6 +196,11 @@ public function caseloads(): HasMany return $this->hasMany(Caseload::class); } + public function licenses(): HasMany + { + return $this->hasMany(License::class, 'user_id'); + } + public function subscriptions(): HasMany { return $this->hasMany(Subscription::class); From 1df8e83a99b0715aed155764de231e847d945756 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 19:05:29 -0500 Subject: [PATCH 011/152] Setup rules and auditing Signed-off-by: Kevin Ullyott --- .../2024_01_02_225406_create_licenses_table.php | 7 ++++--- app-modules/authorization/src/Models/License.php | 8 +++++++- .../RelationManagers/LicensesRelationManager.php | 6 +++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php index 475a106a2a..3dee0c08e4 100644 --- a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php +++ b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php @@ -1,8 +1,9 @@ timestamps(); $table->softDeletes(); - $table->unique(['user_id', 'type']); + $table->uniqueIndex(['user_id', 'type'])->where(fn (Builder $condition) => $condition->whereNull('deleted_at')); }); } }; diff --git a/app-modules/authorization/src/Models/License.php b/app-modules/authorization/src/Models/License.php index 2bd1c9e128..6d9872477d 100644 --- a/app-modules/authorization/src/Models/License.php +++ b/app-modules/authorization/src/Models/License.php @@ -4,11 +4,17 @@ use App\Models\User; use App\Models\BaseModel; +use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; use AdvisingApp\Authorization\Enums\LicenseType; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableConcern; -class License extends BaseModel +class License extends BaseModel implements Auditable { + use AuditableConcern; + use SoftDeletes; + protected $fillable = [ 'type', ]; diff --git a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php index 0e83fbc945..d5b64554b1 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php @@ -26,7 +26,11 @@ public function form(Form $form): Form Select::make('type') ->options(LicenseType::class) ->enum(LicenseType::class) - ->rule(Rule::unique('licenses', 'type')->where('user_id', $this->getOwnerRecord()->getKey())) + ->rule( + Rule::unique('licenses', 'type') + ->where('user_id', $this->getOwnerRecord()->getKey()) + ->whereNull('deleted_at'), + ) ->rule(new LicenseTypeUsageRule()) ->required(), ]); From 7fbc76780487afe24f5ad4f2621c4df6c1b2f615 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 19:22:19 -0500 Subject: [PATCH 012/152] helpers and disables Signed-off-by: Kevin Ullyott --- _ide_helper_models.php | 290 +++++++++++++++--- .../authorization/src/Models/License.php | 3 + .../src/Observers/LicenseObserver.php | 16 + .../AuthorizationServiceProvider.php | 10 + .../inventory-management/src/Models/Asset.php | 3 + .../src/Models/AssetLocation.php | 3 + .../src/Models/AssetStatus.php | 3 + .../src/Models/AssetType.php | 3 + .../src/Models/MaintenanceActivity.php | 3 + .../src/Models/MaintenanceProvider.php | 3 + .../meeting-center/src/Models/Event.php | 3 + .../LicensesRelationManager.php | 7 + app/Models/User.php | 2 +- 13 files changed, 310 insertions(+), 39 deletions(-) create mode 100644 app-modules/authorization/src/Observers/LicenseObserver.php diff --git a/_ide_helper_models.php b/_ide_helper_models.php index 8414883ba6..450515d50f 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -1,39 +1,5 @@ - - Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. - - Advising App™ is licensed under the Elastic License 2.0. For more details, - see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. - - Notice: - - - You may not provide the software to third parties as a hosted or managed - service, where the service provides users with access to any substantial set of - the features or functionality of the software. - - You may not move, change, disable, or circumvent the license key functionality - in the software, and you may not remove or obscure any functionality in the - software that is protected by the license key. - - You may not alter, remove, or obscure any licensing, copyright, or other notices - of the licensor in the software. Any use of the licensor’s trademarks is subject - to applicable law. - - Canyon GBS LLC respects the intellectual property rights of others and expects the - same in return. Canyon GBS™ and Advising App™ are registered trademarks of - Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks - vigorously. - - The software solution, including services, infrastructure, and code, is offered as a - Software as a Service (SaaS) by Canyon GBS LLC. - - Use of this software implies agreement to the license terms and conditions as stated - in the Elastic License 2.0. - - For more information or inquiries please visit our website at - https://www.canyongbs.com or contact us via email at legal@canyongbs.com. - - -*/ - // @formatter:off /** * A helper file for your Eloquent Models @@ -330,6 +296,8 @@ class IdeHelperSystemUser {} * @property-read \Illuminate\Database\Eloquent\Collection $events * @property-read int|null $events_count * @property-read mixed $is_admin + * @property-read \Illuminate\Database\Eloquent\Collection $licenses + * @property-read int|null $licenses_count * @property-read \Spatie\MediaLibrary\MediaCollections\Models\Collections\MediaCollection $media * @property-read int|null $media_count * @property-read \Illuminate\Notifications\DatabaseNotificationCollection $notifications @@ -820,6 +788,35 @@ class IdeHelperAssistantChatMessageLog {} class IdeHelperAudit {} } +namespace AdvisingApp\Authorization\Models{ +/** + * AdvisingApp\Authorization\Models\License + * + * @property string $id + * @property string $user_id + * @property \AdvisingApp\Authorization\Enums\LicenseType $type + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at + * @property-read \App\Models\User $user + * @method static \Illuminate\Database\Eloquent\Builder|License newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|License newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|License onlyTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|License query() + * @method static \Illuminate\Database\Eloquent\Builder|License whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereDeletedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereType($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereUserId($value) + * @method static \Illuminate\Database\Eloquent\Builder|License withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|License withoutTrashed() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperLicense {} +} + namespace AdvisingApp\Authorization\Models{ /** * AdvisingApp\Authorization\Models\Permission @@ -1011,7 +1008,7 @@ class IdeHelperCampaign {} * @property string $campaign_id * @property \AdvisingApp\Campaign\Enums\CampaignActionType $type * @property array $data - * @property string $execute_at + * @property \Illuminate\Support\Carbon $execute_at * @property string|null $last_execution_attempt_at * @property string|null $last_execution_attempt_error * @property string|null $successfully_executed_at @@ -1311,6 +1308,7 @@ class IdeHelperEmailTemplate {} * @method static \AdvisingApp\Engagement\Database\Factories\EngagementFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|Engagement hasBeenDelivered() * @method static \Illuminate\Database\Eloquent\Builder|Engagement hasNotBeenDelivered() + * @method static \Illuminate\Database\Eloquent\Builder|Engagement isAwaitingDelivery() * @method static \Illuminate\Database\Eloquent\Builder|Engagement isNotPartOfABatch() * @method static \Illuminate\Database\Eloquent\Builder|Engagement isScheduled() * @method static \Illuminate\Database\Eloquent\Builder|Engagement newModelQuery() @@ -1984,6 +1982,189 @@ class IdeHelperInteractionStatus {} class IdeHelperInteractionType {} } +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\Asset + * + * @property string $id + * @property string $serial_number + * @property string $name + * @property string $description + * @property string $type_id + * @property string $status_id + * @property string $location_id + * @property string $purchase_date + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @property-read \AdvisingApp\InventoryManagement\Models\AssetLocation $location + * @property-read \Illuminate\Database\Eloquent\Collection $maintenanceActivities + * @property-read int|null $maintenance_activities_count + * @property-read \AdvisingApp\InventoryManagement\Models\AssetStatus $status + * @property-read \AdvisingApp\InventoryManagement\Models\AssetType $type + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Asset newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Asset newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Asset query() + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereDescription($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereLocationId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset wherePurchaseDate($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereSerialNumber($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereStatusId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereTypeId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAsset {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\AssetLocation + * + * @property string $id + * @property string $name + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $assets + * @property-read int|null $assets_count + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetLocationFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation query() + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAssetLocation {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\AssetStatus + * + * @property string $id + * @property string $name + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $assets + * @property-read int|null $assets_count + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetStatusFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus query() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAssetStatus {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\AssetType + * + * @property string $id + * @property string $name + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $assets + * @property-read int|null $assets_count + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetTypeFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetType newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetType query() + * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAssetType {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\MaintenanceActivity + * + * @property string $id + * @property string $asset_id + * @property string|null $maintenance_provider_id + * @property string $details + * @property \Illuminate\Support\Carbon|null $scheduled_date + * @property \Illuminate\Support\Carbon|null $completed_date + * @property \AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus $status + * @property string|null $notes + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \AdvisingApp\InventoryManagement\Models\Asset $asset + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @property-read \AdvisingApp\InventoryManagement\Models\MaintenanceProvider|null $maintenanceProvider + * @method static \AdvisingApp\InventoryManagement\Database\Factories\MaintenanceActivityFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity query() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereAssetId($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereCompletedDate($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereDetails($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereMaintenanceProviderId($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereNotes($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereScheduledDate($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereStatus($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperMaintenanceActivity {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\MaintenanceProvider + * + * @property string $id + * @property string $name + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @property-read \Illuminate\Database\Eloquent\Collection $maintenanceActivities + * @property-read int|null $maintenance_activities_count + * @method static \AdvisingApp\InventoryManagement\Database\Factories\MaintenanceProviderFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider query() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperMaintenanceProvider {} +} + namespace AdvisingApp\KnowledgeBase\Models{ /** * AdvisingApp\KnowledgeBase\Models\KnowledgeBaseCategory @@ -2022,8 +2203,8 @@ class IdeHelperKnowledgeBaseCategory {} * @property string $id * @property string $question * @property bool $public - * @property string|null $solution - * @property string|null $notes + * @property array|null $solution + * @property array|null $notes * @property string|null $quality_id * @property string|null $status_id * @property string|null $category_id @@ -2194,6 +2375,38 @@ class IdeHelperCalendar {} class IdeHelperCalendarEvent {} } +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\Event + * + * @property string $id + * @property string $title + * @property string|null $description + * @property string|null $location + * @property int|null $capacity + * @property \Illuminate\Support\Carbon $starts_at + * @property \Illuminate\Support\Carbon $ends_at + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @method static \AdvisingApp\MeetingCenter\Database\Factories\EventFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Event newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Event newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Event query() + * @method static \Illuminate\Database\Eloquent\Builder|Event whereCapacity($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereDescription($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereEndsAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereLocation($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereStartsAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereTitle($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEvent {} +} + namespace AdvisingApp\Notification\Models{ /** * AdvisingApp\Notification\Models\OutboundDeliverable @@ -2290,7 +2503,7 @@ class IdeHelperSubscription {} * @property string|null $phone * @property string|null $address * @property string|null $address_2 - * @property string|null $birthdate + * @property \Illuminate\Support\Carbon|null $birthdate * @property string|null $hsgrad * @property string|null $assigned_to_id * @property string|null $created_by_id @@ -2744,6 +2957,7 @@ class IdeHelperProgram {} * AdvisingApp\StudentDataModel\Models\Student * * @property string $display_name + * @property string $mobile * @property-read \Illuminate\Database\Eloquent\Collection $alerts * @property-read int|null $alerts_count * @property-read \Illuminate\Database\Eloquent\Collection $applicationSubmissions diff --git a/app-modules/authorization/src/Models/License.php b/app-modules/authorization/src/Models/License.php index 6d9872477d..209491a7d3 100644 --- a/app-modules/authorization/src/Models/License.php +++ b/app-modules/authorization/src/Models/License.php @@ -10,6 +10,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableConcern; +/** + * @mixin IdeHelperLicense + */ class License extends BaseModel implements Auditable { use AuditableConcern; diff --git a/app-modules/authorization/src/Observers/LicenseObserver.php b/app-modules/authorization/src/Observers/LicenseObserver.php new file mode 100644 index 0000000000..a06f90af0a --- /dev/null +++ b/app-modules/authorization/src/Observers/LicenseObserver.php @@ -0,0 +1,16 @@ +type->hasAvailableLicenses()) { + throw new Exception("There are no available {$license->type->getLabel()} licenses."); + } + } +} diff --git a/app-modules/authorization/src/Providers/AuthorizationServiceProvider.php b/app-modules/authorization/src/Providers/AuthorizationServiceProvider.php index 22a4eba828..ce36123f8b 100644 --- a/app-modules/authorization/src/Providers/AuthorizationServiceProvider.php +++ b/app-modules/authorization/src/Providers/AuthorizationServiceProvider.php @@ -40,6 +40,7 @@ use Illuminate\Support\Facades\Event; use Illuminate\Support\ServiceProvider; use AdvisingApp\Authorization\Models\Role; +use AdvisingApp\Authorization\Models\License; use AdvisingApp\Authorization\Models\RoleGroup; use AdvisingApp\Authorization\Models\Permission; use AdvisingApp\Authorization\AuthorizationPlugin; @@ -48,6 +49,7 @@ use Illuminate\Database\Eloquent\Relations\Relation; use SocialiteProviders\Google\GoogleExtendSocialite; use AdvisingApp\Authorization\AuthorizationRoleRegistry; +use AdvisingApp\Authorization\Observers\LicenseObserver; use AdvisingApp\Authorization\AuthorizationPermissionRegistry; class AuthorizationServiceProvider extends ServiceProvider @@ -73,8 +75,11 @@ public function boot(AuthorizationPermissionRegistry $permissionRegistry, Author 'role' => Role::class, 'permission' => Permission::class, 'role_group' => RoleGroup::class, + 'license' => License::class, ]); + $this->registerObservers(); + $permissionRegistry->registerApiPermissions( module: 'authorization', path: 'permissions/api/custom' @@ -105,4 +110,9 @@ public function boot(AuthorizationPermissionRegistry $permissionRegistry, Author listener: GoogleExtendSocialite::class . '@handle' ); } + + public function registerObservers(): void + { + License::observe(LicenseObserver::class); + } } diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index a2d9dca12d..0c47192b9e 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -42,6 +42,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAsset + */ class Asset extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/AssetLocation.php b/app-modules/inventory-management/src/Models/AssetLocation.php index 37c656e292..d310c7f8b9 100644 --- a/app-modules/inventory-management/src/Models/AssetLocation.php +++ b/app-modules/inventory-management/src/Models/AssetLocation.php @@ -41,6 +41,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAssetLocation + */ class AssetLocation extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/AssetStatus.php b/app-modules/inventory-management/src/Models/AssetStatus.php index da1000a351..5214a52f50 100644 --- a/app-modules/inventory-management/src/Models/AssetStatus.php +++ b/app-modules/inventory-management/src/Models/AssetStatus.php @@ -41,6 +41,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAssetStatus + */ class AssetStatus extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/AssetType.php b/app-modules/inventory-management/src/Models/AssetType.php index e00d56af4e..f1a9bde9f0 100644 --- a/app-modules/inventory-management/src/Models/AssetType.php +++ b/app-modules/inventory-management/src/Models/AssetType.php @@ -41,6 +41,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAssetType + */ class AssetType extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/MaintenanceActivity.php b/app-modules/inventory-management/src/Models/MaintenanceActivity.php index 71c75c3ad5..7431ad186f 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceActivity.php +++ b/app-modules/inventory-management/src/Models/MaintenanceActivity.php @@ -42,6 +42,9 @@ use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus; +/** + * @mixin IdeHelperMaintenanceActivity + */ class MaintenanceActivity extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/MaintenanceProvider.php b/app-modules/inventory-management/src/Models/MaintenanceProvider.php index c319b8eec9..79c81e28e8 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceProvider.php +++ b/app-modules/inventory-management/src/Models/MaintenanceProvider.php @@ -41,6 +41,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperMaintenanceProvider + */ class MaintenanceProvider extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/meeting-center/src/Models/Event.php b/app-modules/meeting-center/src/Models/Event.php index 401917e9be..6484c5341e 100644 --- a/app-modules/meeting-center/src/Models/Event.php +++ b/app-modules/meeting-center/src/Models/Event.php @@ -38,6 +38,9 @@ use App\Models\BaseModel; +/** + * @mixin IdeHelperEvent + */ class Event extends BaseModel { protected $fillable = [ diff --git a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php index d5b64554b1..62e5dd8653 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php @@ -2,6 +2,7 @@ namespace App\Filament\Resources\UserResource\RelationManagers; +use App\Models\User; use Filament\Forms\Form; use Filament\Tables\Table; use Illuminate\Validation\Rule; @@ -32,6 +33,12 @@ public function form(Form $form): Form ->whereNull('deleted_at'), ) ->rule(new LicenseTypeUsageRule()) + ->disableOptionWhen(function (string $value) { + /** @var User $ownerRecord */ + $ownerRecord = $this->getOwnerRecord(); + + return ! LicenseType::from($value)->hasAvailableLicenses() || $ownerRecord->licenses()->where('type', $value)->exists(); + }) ->required(), ]); } diff --git a/app/Models/User.php b/app/Models/User.php index d68162d962..08cb1dc89b 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -52,8 +52,8 @@ use Lab404\Impersonate\Models\Impersonate; use Filament\Models\Contracts\FilamentUser; use Spatie\MediaLibrary\InteractsWithMedia; -use Illuminate\Database\Eloquent\SoftDeletes; use AdvisingApp\Authorization\Models\License; +use Illuminate\Database\Eloquent\SoftDeletes; use AdvisingApp\MeetingCenter\Models\Calendar; use AdvisingApp\Assistant\Models\AssistantChat; use AdvisingApp\StudentDataModel\Models\Student; From 8e964fa72a662e0232d78c0c59270ce9f097fb80 Mon Sep 17 00:00:00 2001 From: Orrison Date: Wed, 3 Jan 2024 00:27:06 +0000 Subject: [PATCH 013/152] chore: fix enforcement of copyright on all files --- _ide_helper_models.php | 34 +++++++++++++++++++ ...024_01_02_225406_create_licenses_table.php | 34 +++++++++++++++++++ .../authorization/src/Enums/LicenseType.php | 34 +++++++++++++++++++ .../authorization/src/Models/License.php | 34 +++++++++++++++++++ .../src/Observers/LicenseObserver.php | 34 +++++++++++++++++++ .../src/Rules/LicenseTypeUsageRule.php | 34 +++++++++++++++++++ .../LicensesRelationManager.php | 34 +++++++++++++++++++ 7 files changed, 238 insertions(+) diff --git a/_ide_helper_models.php b/_ide_helper_models.php index 450515d50f..520c0c5be7 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + // @formatter:off /** * A helper file for your Eloquent Models diff --git a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php index 3dee0c08e4..eac079e191 100644 --- a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php +++ b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use Illuminate\Database\Query\Builder; use Illuminate\Database\Migrations\Migration; use Tpetry\PostgresqlEnhanced\Schema\Blueprint; diff --git a/app-modules/authorization/src/Enums/LicenseType.php b/app-modules/authorization/src/Enums/LicenseType.php index b8d00a8293..5e7e9d06db 100644 --- a/app-modules/authorization/src/Enums/LicenseType.php +++ b/app-modules/authorization/src/Enums/LicenseType.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Authorization\Enums; use App\Settings\LicenseSettings; diff --git a/app-modules/authorization/src/Models/License.php b/app-modules/authorization/src/Models/License.php index 209491a7d3..91dc3f04c9 100644 --- a/app-modules/authorization/src/Models/License.php +++ b/app-modules/authorization/src/Models/License.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Authorization\Models; use App\Models\User; diff --git a/app-modules/authorization/src/Observers/LicenseObserver.php b/app-modules/authorization/src/Observers/LicenseObserver.php index a06f90af0a..c1280f5f78 100644 --- a/app-modules/authorization/src/Observers/LicenseObserver.php +++ b/app-modules/authorization/src/Observers/LicenseObserver.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Authorization\Observers; use Exception; diff --git a/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php b/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php index 9eaf5bb06f..16ed3c0982 100644 --- a/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php +++ b/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Authorization\Rules; use Closure; diff --git a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php index 62e5dd8653..1487568274 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace App\Filament\Resources\UserResource\RelationManagers; use App\Models\User; From 8aa66502912c559ee8b6b6a3ac53df2007833ab6 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 07:39:00 -0500 Subject: [PATCH 014/152] Add check out action. --- .../database/seeders/AssetStatusSeeder.php | 5 +- .../Enums/SystemAssetStatusClassification.php | 8 +- .../Actions/CheckOutAssetHeaderAction.php | 95 +++++++++++++++++++ .../AssetResource/Pages/ViewAsset.php | 9 ++ .../inventory-management/src/Models/Asset.php | 16 +++- 5 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php diff --git a/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php b/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php index 16ddff9f5e..e722caff2b 100644 --- a/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php +++ b/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php @@ -51,7 +51,10 @@ public function run(): void 'name' => 'Available', 'classification' => SystemAssetStatusClassification::Available, ], - ['name' => 'In Use'], + [ + 'name' => 'In Use', + 'classification' => SystemAssetStatusClassification::CheckedOut, + ], ['name' => 'Under Maintenance'], ['name' => 'Out of Service'], ['name' => 'Reserved'], diff --git a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php index d1b153e600..7d4447615d 100644 --- a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php +++ b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php @@ -42,12 +42,18 @@ enum SystemAssetStatusClassification: string implements HasLabel { case Available = 'available'; + // TODO Implement a rule that only one asset status can be classified as this + case CheckedOut = 'checked_out'; + case Unavailable = 'unavailable'; case Custom = 'custom'; public function getLabel(): ?string { - return $this->name; + return match ($this) { + self::CheckedOut => 'Checked Out', + default => $this->name + }; } } diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php new file mode 100644 index 0000000000..b65d222e75 --- /dev/null +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -0,0 +1,95 @@ +button(); + + $this->label(__('Check Out')); + + /** @var Asset $asset */ + $asset = $this->getRecord(); + + $this->modalHeading(__("Check out {$asset->name}")); + + $this->modalSubmitActionLabel(__('Done')); + + $this->successNotificationTitle(__("Successfully checked out {$asset->name}")); + + $this->form([ + Radio::make('checked_out_to_type') + ->label('Check out to') + ->options([ + Student::class => 'Student', + Prospect::class => 'Prospect', + ]) + ->default(Student::class) + ->required() + ->live(), + Select::make('checked_out_to_id') + ->label(fn (Get $get): string => match ($get('checked_out_to_type')) { + Student::class => 'Select Student', + Prospect::class => 'Select Prospect', + }) + ->visible(fn (Get $get): bool => filled($get('checked_out_to_type'))) + ->getSearchResultsUsing(function (string $search, Get $get) { + return match ($get('checked_out_to_type')) { + Student::class => Student::where('full_name', 'like', "%{$search}%")->pluck('full_name', 'sisid')->toArray(), + Prospect::class => Prospect::where('full_name', 'like', "%{$search}%")->pluck('full_name', 'id')->toArray(), + }; + }) + ->searchable() + ->required(), + Textarea::make('notes') + ->autofocus() + ->required(), + DateTimePicker::make('expected_check_in_at') + ->label('Expected Return Date'), + ]); + + $this->action(function (array $data): void { + /** @var Asset $asset */ + $asset = $this->getRecord(); + + if (! $asset->isAvailable()) { + $this->failure(); + } + + $asset->checkOuts()->create([ + 'checked_out_by_type' => auth()->user()?->getMorphClass(), + 'checked_out_by_id' => auth()->user()?->id, + 'checked_out_to_type' => (new $data['checked_out_to_type']())->getMorphClass(), + 'checked_out_to_id' => $data['checked_out_to_id'], + 'notes' => $data['notes'], + 'checked_out_at' => now(), + 'expected_check_in_at' => $data['expected_check_in_at'], + ]); + + // TODO We may want to move this to an observer in order to clean up... + $checkedOutStatus = AssetStatus::where('classification', SystemAssetStatusClassification::CheckedOut)->first(); + + $asset->update([ + 'status_id' => $checkedOutStatus->id, + ]); + + $this->success(); + }); + } +} diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php b/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php index aaaa2de57b..deedb2c68d 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php @@ -41,7 +41,9 @@ use Filament\Resources\Pages\ViewRecord; use Filament\Infolists\Components\Section; use Filament\Infolists\Components\TextEntry; +use AdvisingApp\InventoryManagement\Models\Asset; use AdvisingApp\InventoryManagement\Filament\Resources\AssetResource; +use AdvisingApp\InventoryManagement\Filament\Actions\CheckOutAssetHeaderAction; class ViewAsset extends ViewRecord { @@ -71,6 +73,13 @@ protected function getHeaderActions(): array { return [ EditAction::make(), + CheckOutAssetHeaderAction::make('check-out') + ->visible(function () { + /** @var Asset $asset */ + $asset = $this->getRecord(); + + return $asset->isAvailable(); + }), ]; } } diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index fa678c544a..657f4d5658 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -39,6 +39,7 @@ use App\Models\BaseModel; use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; @@ -84,6 +85,18 @@ public function checkOuts(): HasMany return $this->hasMany(AssetCheckOut::class, 'asset_id'); } + public function latestCheckOut(): HasOne + { + return $this->hasOne(AssetCheckOut::class, 'asset_id') + ->oldest('checked_out_at'); + } + + public function latestCheckIn(): HasOne + { + return $this->hasOne(AssetCheckIn::class, 'asset_id') + ->latest('checked_in_at'); + } + public function checkIns(): HasMany { return $this->hasMany(AssetCheckIn::class, 'asset_id'); @@ -91,6 +104,7 @@ public function checkIns(): HasMany public function isAvailable(): bool { - return $this->status->classification === SystemAssetStatusClassification::Available; + return $this->status->classification === SystemAssetStatusClassification::Available + && is_null($this->latestCheckOut->asset_check_in_id); } } From d93ec83179e36ce5c875b93f4bf39312b41d5e71 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:06:33 -0500 Subject: [PATCH 015/152] Add check in action. --- .../Providers/EngagementServiceProvider.php | 4 +- .../Enums/SystemAssetStatusClassification.php | 1 + .../Actions/CheckInAssetHeaderAction.php | 64 +++++++++++++++++++ .../AssetResource/Pages/ViewAsset.php | 8 +++ .../inventory-management/src/Models/Asset.php | 13 +++- .../src/Observers/AssetCheckInObserver.php | 52 +++++++++++++++ .../InventoryManagementServiceProvider.php | 8 +++ 7 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php create mode 100644 app-modules/inventory-management/src/Observers/AssetCheckInObserver.php diff --git a/app-modules/engagement/src/Providers/EngagementServiceProvider.php b/app-modules/engagement/src/Providers/EngagementServiceProvider.php index c37579c893..5f9f784093 100644 --- a/app-modules/engagement/src/Providers/EngagementServiceProvider.php +++ b/app-modules/engagement/src/Providers/EngagementServiceProvider.php @@ -84,9 +84,9 @@ public function boot(): void ->withoutOverlapping(); }); - $this->registerRolesAndPermissions(); - $this->registerObservers(); + + $this->registerRolesAndPermissions(); } public function registerObservers(): void diff --git a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php index 7d4447615d..ba9704cb95 100644 --- a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php +++ b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php @@ -40,6 +40,7 @@ enum SystemAssetStatusClassification: string implements HasLabel { + // TODO Implement a rule that only one asset status can be classified as this case Available = 'available'; // TODO Implement a rule that only one asset status can be classified as this diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php new file mode 100644 index 0000000000..e14ef6b132 --- /dev/null +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -0,0 +1,64 @@ +button(); + + $this->label(__('Check In')); + + /** @var Asset $asset */ + $asset = $this->getRecord(); + + $this->modalHeading(__("Check in {$asset->name}")); + + $this->modalSubmitActionLabel(__('Done')); + + $this->successNotificationTitle(__("Successfully checked in {$asset->name}")); + + $this->form([ + Textarea::make('notes') + ->autofocus() + ->required(), + ]); + + $this->action(function (array $data): void { + /** @var Asset $asset */ + $asset = $this->getRecord(); + + if (! $asset->isAvailable()) { + $this->failure(); + } + + $asset->checkIns()->create([ + 'checked_in_by_type' => auth()->user()?->getMorphClass(), + 'checked_in_by_id' => auth()->user()?->id, + // TODO Should we still have this be configurable? Or should the expectation be that this information is the same as the latest check out? + 'checked_in_from_type' => $asset->latestCheckOut->checked_out_to_type, + 'checked_in_from_id' => $asset->latestCheckOut->checked_out_to_id, + 'notes' => $data['notes'], + 'checked_in_at' => now(), + ]); + + // TODO We may want to move this to an observer in order to clean up... + $checkedInStatus = AssetStatus::where('classification', SystemAssetStatusClassification::Available)->first(); + + $asset->update([ + 'status_id' => $checkedInStatus->id, + ]); + + $this->success(); + }); + } +} diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php b/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php index deedb2c68d..db278be7fb 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php @@ -43,6 +43,7 @@ use Filament\Infolists\Components\TextEntry; use AdvisingApp\InventoryManagement\Models\Asset; use AdvisingApp\InventoryManagement\Filament\Resources\AssetResource; +use AdvisingApp\InventoryManagement\Filament\Actions\CheckInAssetHeaderAction; use AdvisingApp\InventoryManagement\Filament\Actions\CheckOutAssetHeaderAction; class ViewAsset extends ViewRecord @@ -80,6 +81,13 @@ protected function getHeaderActions(): array return $asset->isAvailable(); }), + CheckInAssetHeaderAction::make('check-in') + ->visible(function () { + /** @var Asset $asset */ + $asset = $this->getRecord(); + + return $asset->isCheckedOut(); + }), ]; } } diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index 657f4d5658..4ad9567445 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -105,6 +105,17 @@ public function checkIns(): HasMany public function isAvailable(): bool { return $this->status->classification === SystemAssetStatusClassification::Available - && is_null($this->latestCheckOut->asset_check_in_id); + && ! is_null($this->latestCheckOut?->asset_check_in_id); + } + + public function isNotAvailable(): bool + { + return ! $this->isAvailable(); + } + + public function isCheckedOut(): bool + { + return $this->status->classification === SystemAssetStatusClassification::CheckedOut + && is_null($this->latestCheckOut?->asset_check_in_id); } } diff --git a/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php b/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php new file mode 100644 index 0000000000..54d9e4fa18 --- /dev/null +++ b/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php @@ -0,0 +1,52 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Observers; + +use AdvisingApp\InventoryManagement\Models\AssetCheckIn; + +class AssetCheckInObserver +{ + public function created(AssetCheckIn $checkIn): void + { + ray('AssetCheckInObserver::created()'); + ray($checkIn->asset->latestCheckOut); + + $checkIn->asset->latestCheckOut->update([ + 'asset_check_in_id' => $checkIn->id, + ]); + } +} diff --git a/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php b/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php index 52739c94ec..bed4974244 100644 --- a/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php +++ b/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php @@ -50,6 +50,7 @@ use AdvisingApp\InventoryManagement\InventoryManagementPlugin; use AdvisingApp\InventoryManagement\Models\MaintenanceActivity; use AdvisingApp\InventoryManagement\Models\MaintenanceProvider; +use AdvisingApp\InventoryManagement\Observers\AssetCheckInObserver; class InventoryManagementServiceProvider extends ServiceProvider { @@ -71,9 +72,16 @@ public function boot() 'maintenance_provider' => MaintenanceProvider::class, ]); + $this->registerObservers(); + $this->registerRolesAndPermissions(); } + public function registerObservers(): void + { + AssetCheckIn::observe(AssetCheckInObserver::class); + } + protected function registerRolesAndPermissions() { $permissionRegistry = app(AuthorizationPermissionRegistry::class); From 55d8d012a3f53191e1ab5fafa43e836db4e82895 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:15:54 -0500 Subject: [PATCH 016/152] Make status configurable on check in. --- .../Actions/CheckInAssetHeaderAction.php | 18 +++++++++++++----- .../Actions/CheckOutAssetHeaderAction.php | 3 +-- .../src/Models/AssetStatus.php | 10 ++++++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php index e14ef6b132..4b7161533f 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -3,10 +3,11 @@ namespace AdvisingApp\InventoryManagement\Filament\Actions; use Filament\Actions\Action; +use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\DateTimePicker; use AdvisingApp\InventoryManagement\Models\Asset; use AdvisingApp\InventoryManagement\Models\AssetStatus; -use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; class CheckInAssetHeaderAction extends Action { @@ -31,6 +32,16 @@ protected function setUp(): void Textarea::make('notes') ->autofocus() ->required(), + Select::make('status_id') + ->relationship('status', 'name') + ->preload() + ->label('Status') + ->default(AssetStatus::available()->first()->id) + ->required() + ->exists((new AssetStatus())->getTable(), 'id'), + DateTimePicker::make('checked_in_at') + ->label('Checked in at') + ->default(now()), ]); $this->action(function (array $data): void { @@ -51,11 +62,8 @@ protected function setUp(): void 'checked_in_at' => now(), ]); - // TODO We may want to move this to an observer in order to clean up... - $checkedInStatus = AssetStatus::where('classification', SystemAssetStatusClassification::Available)->first(); - $asset->update([ - 'status_id' => $checkedInStatus->id, + 'status_id' => $data['status_id'], ]); $this->success(); diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php index b65d222e75..9bb252cdd5 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -12,7 +12,6 @@ use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\InventoryManagement\Models\Asset; use AdvisingApp\InventoryManagement\Models\AssetStatus; -use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; class CheckOutAssetHeaderAction extends Action { @@ -83,7 +82,7 @@ protected function setUp(): void ]); // TODO We may want to move this to an observer in order to clean up... - $checkedOutStatus = AssetStatus::where('classification', SystemAssetStatusClassification::CheckedOut)->first(); + $checkedOutStatus = AssetStatus::checkedOut()->first(); $asset->update([ 'status_id' => $checkedOutStatus->id, diff --git a/app-modules/inventory-management/src/Models/AssetStatus.php b/app-modules/inventory-management/src/Models/AssetStatus.php index 57308169a6..c697f60838 100644 --- a/app-modules/inventory-management/src/Models/AssetStatus.php +++ b/app-modules/inventory-management/src/Models/AssetStatus.php @@ -61,4 +61,14 @@ public function assets(): HasMany { return $this->hasMany(Asset::class, 'status_id'); } + + public function scopeAvailable(): void + { + $this->where('classification', SystemAssetStatusClassification::Available); + } + + public function scopeCheckedOut(): void + { + $this->where('classification', SystemAssetStatusClassification::CheckedOut); + } } From 190df3db52de5316ad779eb10edac81c4909ffed Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Wed, 3 Jan 2024 13:16:21 +0000 Subject: [PATCH 017/152] start educatable select --- .../AlertResource/Pages/ListAlerts.php | 10 +- .../Concerns/HasSharedFormConfiguration.php | 24 ++-- .../Pages/CreateEngagement.php | 10 +- .../Pages/EditEngagement.php | 12 +- .../Concerns/HasSharedFormConfiguration.php | 26 ++-- .../Pages/CreateInteraction.php | 8 +- .../Pages/EditInteraction.php | 8 +- .../prospect/src/Policies/ProspectPolicy.php | 4 + .../Pages/CreateServiceRequest.php | 10 +- .../Pages/EditServiceRequest.php | 12 +- .../src/Policies/StudentPolicy.php | 4 + .../Concerns/HasSharedFormConfiguration.php | 24 ++-- .../src/Filament/Concerns/TaskEditForm.php | 12 +- .../TaskResource/Pages/CreateTask.php | 12 +- .../Fields}/ColorSelect.php | 4 +- app/Filament/Fields/EducatableSelect.php | 123 ++++++++++++++++++ .../Pages/CreateNotificationSetting.php | 10 +- .../Pages/EditNotificationSetting.php | 10 +- app/Livewire/TaskKanban.php | 12 +- app/Models/User.php | 10 ++ 20 files changed, 219 insertions(+), 126 deletions(-) rename app/{Forms/Components => Filament/Fields}/ColorSelect.php (98%) create mode 100644 app/Filament/Fields/EducatableSelect.php diff --git a/app-modules/alert/src/Filament/Resources/AlertResource/Pages/ListAlerts.php b/app-modules/alert/src/Filament/Resources/AlertResource/Pages/ListAlerts.php index c0f0bee3b0..f34dc91f50 100644 --- a/app-modules/alert/src/Filament/Resources/AlertResource/Pages/ListAlerts.php +++ b/app-modules/alert/src/Filament/Resources/AlertResource/Pages/ListAlerts.php @@ -36,6 +36,7 @@ namespace AdvisingApp\Alert\Filament\Resources\AlertResource\Pages; +use App\Filament\Fields\EducatableSelect; use Filament\Tables\Table; use Filament\Infolists\Infolist; use App\Filament\Columns\IdColumn; @@ -174,15 +175,8 @@ protected function getHeaderActions(): array return [ CreateAction::make() ->form([ - MorphToSelect::make('concern') + EducatableSelect::make('concern') ->label('Related To') - ->types([ - Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), - ]) - ->searchable() ->required(), Group::make() ->schema([ diff --git a/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/Concerns/HasSharedFormConfiguration.php b/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/Concerns/HasSharedFormConfiguration.php index 7114f3fe24..d1741b2aa2 100644 --- a/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/Concerns/HasSharedFormConfiguration.php +++ b/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/Concerns/HasSharedFormConfiguration.php @@ -36,24 +36,24 @@ namespace AdvisingApp\Application\Filament\Resources\ApplicationResource\Pages\Concerns; -use Filament\Forms\Get; -use Filament\Forms\Components\Grid; +use AdvisingApp\Application\Models\Application; +use AdvisingApp\Application\Models\ApplicationField; +use AdvisingApp\Application\Models\ApplicationStep; use AdvisingApp\Form\Enums\Rounding; +use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use AdvisingApp\Form\Rules\IsDomain; -use App\Forms\Components\ColorSelect; -use Filament\Forms\Components\Select; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Components\Section; -use FilamentTiptapEditor\TiptapEditor; +use App\Filament\Fields\ColorSelect; +use Filament\Forms\Components\Grid; use Filament\Forms\Components\Repeater; -use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\Section; +use Filament\Forms\Components\Select; use Filament\Forms\Components\TagsInput; +use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; +use Filament\Forms\Components\Toggle; +use Filament\Forms\Get; use FilamentTiptapEditor\Enums\TiptapOutput; -use AdvisingApp\Application\Models\Application; -use AdvisingApp\Application\Models\ApplicationStep; -use AdvisingApp\Application\Models\ApplicationField; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use FilamentTiptapEditor\TiptapEditor; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; trait HasSharedFormConfiguration diff --git a/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/CreateEngagement.php b/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/CreateEngagement.php index c4963b4539..78e54aa8c5 100644 --- a/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/CreateEngagement.php +++ b/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/CreateEngagement.php @@ -36,6 +36,7 @@ namespace AdvisingApp\Engagement\Filament\Resources\EngagementResource\Pages; +use App\Filament\Fields\EducatableSelect; use Filament\Forms\Get; use Filament\Forms\Set; use Filament\Forms\Form; @@ -151,16 +152,9 @@ public function form(Form $form): Form ->columnSpanFull(), EngagementSmsBodyField::make(context: 'create', form: $form), ]), - MorphToSelect::make('recipient') + EducatableSelect::make('recipient') ->label('Recipient') - ->searchable() ->required() - ->types([ - MorphToSelect\Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - MorphToSelect\Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), - ]) ->hiddenOn([RelationManager::class, ManageRelatedRecords::class]), Fieldset::make('Send your email or text') ->schema([ diff --git a/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/EditEngagement.php b/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/EditEngagement.php index 75e8ce6a44..55f96ef382 100644 --- a/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/EditEngagement.php +++ b/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/EditEngagement.php @@ -36,6 +36,7 @@ namespace AdvisingApp\Engagement\Filament\Resources\EngagementResource\Pages; +use App\Filament\Fields\EducatableSelect; use Filament\Forms\Get; use Filament\Forms\Set; use Filament\Forms\Form; @@ -143,16 +144,9 @@ public function form(Form $form): Form ->helperText('You can insert student information by typing {{ and choosing a merge value to insert.') ->columnSpanFull(), EngagementSmsBodyField::make(context: 'edit', form: $form), - MorphToSelect::make('recipient') + EducatableSelect::make('recipient') ->label('Recipient') - ->searchable() - ->required() - ->types([ - MorphToSelect\Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - MorphToSelect\Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), - ]), + ->required(), Fieldset::make('Send your engagement') ->schema([ Toggle::make('send_later') diff --git a/app-modules/form/src/Filament/Resources/FormResource/Pages/Concerns/HasSharedFormConfiguration.php b/app-modules/form/src/Filament/Resources/FormResource/Pages/Concerns/HasSharedFormConfiguration.php index c0108b6b7f..74b78db340 100644 --- a/app-modules/form/src/Filament/Resources/FormResource/Pages/Concerns/HasSharedFormConfiguration.php +++ b/app-modules/form/src/Filament/Resources/FormResource/Pages/Concerns/HasSharedFormConfiguration.php @@ -36,26 +36,26 @@ namespace AdvisingApp\Form\Filament\Resources\FormResource\Pages\Concerns; -use Filament\Forms\Get; -use AdvisingApp\Form\Models\Form; -use Filament\Forms\Components\Grid; use AdvisingApp\Form\Enums\Rounding; -use AdvisingApp\Form\Rules\IsDomain; -use AdvisingApp\Form\Models\FormStep; -use App\Forms\Components\ColorSelect; -use Filament\Forms\Components\Select; -use Filament\Forms\Components\Toggle; +use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use AdvisingApp\Form\Models\Form; use AdvisingApp\Form\Models\FormField; -use Filament\Forms\Components\Section; -use FilamentTiptapEditor\TiptapEditor; +use AdvisingApp\Form\Models\FormStep; +use AdvisingApp\Form\Rules\IsDomain; +use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; +use App\Filament\Fields\ColorSelect; +use Filament\Forms\Components\Grid; use Filament\Forms\Components\Repeater; -use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\Section; +use Filament\Forms\Components\Select; use Filament\Forms\Components\TagsInput; +use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; +use Filament\Forms\Components\Toggle; +use Filament\Forms\Get; use FilamentTiptapEditor\Enums\TiptapOutput; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use FilamentTiptapEditor\TiptapEditor; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; -use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; trait HasSharedFormConfiguration { diff --git a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php index b0474ba94f..0b44739cdc 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php @@ -72,10 +72,10 @@ public function form(Form $form): Form ->searchable() ->required() ->types([ - MorphToSelect\Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - MorphToSelect\Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), + ...(auth()->user()->canAccessStudents() ? [MorphToSelect\Type::make(Student::class) + ->titleAttribute(Student::displayNameKey())] : []), + ...(auth()->user()->canAccessProspects() ? [MorphToSelect\Type::make(Prospect::class) + ->titleAttribute(Prospect::displayNameKey())] : []), MorphToSelect\Type::make(ServiceRequest::class) ->label('Service Request') ->titleAttribute('service_request_number'), diff --git a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php index 8671cdfbc4..5e03823ca2 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php @@ -71,10 +71,10 @@ public function form(Form $form): Form ->searchable() ->required() ->types([ - MorphToSelect\Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - MorphToSelect\Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), + ...(auth()->user()->canAccessStudents() ? [MorphToSelect\Type::make(Student::class) + ->titleAttribute(Student::displayNameKey())] : []), + ...(auth()->user()->canAccessProspects() ? [MorphToSelect\Type::make(Prospect::class) + ->titleAttribute(Prospect::displayNameKey())] : []), MorphToSelect\Type::make(ServiceRequest::class) ->label('Service Request') ->titleAttribute('service_request_number'), diff --git a/app-modules/prospect/src/Policies/ProspectPolicy.php b/app-modules/prospect/src/Policies/ProspectPolicy.php index 3845a82148..a3fb6742fb 100644 --- a/app-modules/prospect/src/Policies/ProspectPolicy.php +++ b/app-modules/prospect/src/Policies/ProspectPolicy.php @@ -44,6 +44,10 @@ class ProspectPolicy { public function viewAny(Authenticatable $authenticatable): Response { + if (! $authenticatable->canAccessProspects()) { + return Response::deny('You do not have permission to view prospects.'); + } + return $authenticatable->canOrElse( abilities: 'prospect.view-any', denyResponse: 'You do not have permission to view prospects.' diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/CreateServiceRequest.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/CreateServiceRequest.php index 941e49a2f7..f2ec035cb4 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/CreateServiceRequest.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/CreateServiceRequest.php @@ -36,6 +36,7 @@ namespace AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestResource\Pages; +use App\Filament\Fields\EducatableSelect; use Filament\Forms\Form; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; @@ -94,15 +95,8 @@ public function form(Form $form): Form ->label('Internal Service Request Details') ->nullable() ->string(), - MorphToSelect::make('respondent') + EducatableSelect::make('respondent') ->label('Related To') - ->searchable() - ->types([ - MorphToSelect\Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - MorphToSelect\Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), - ]) ->hiddenOn([RelationManager::class, ManageRelatedRecords::class]), ]); } diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/EditServiceRequest.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/EditServiceRequest.php index b0a83ff483..4ff35982b6 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/EditServiceRequest.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/EditServiceRequest.php @@ -36,6 +36,7 @@ namespace AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestResource\Pages; +use App\Filament\Fields\EducatableSelect; use Filament\Actions; use Filament\Forms\Form; use Filament\Forms\Components\Select; @@ -93,15 +94,8 @@ public function form(Form $form): Form ->label('Internal Service Request Details') ->nullable() ->string(), - MorphToSelect::make('respondent') - ->label('Related To') - ->searchable() - ->types([ - MorphToSelect\Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - MorphToSelect\Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), - ]), + EducatableSelect::make('respondent') + ->label('Related To'), ]); } diff --git a/app-modules/student-data-model/src/Policies/StudentPolicy.php b/app-modules/student-data-model/src/Policies/StudentPolicy.php index d64427fd47..7157a5d018 100644 --- a/app-modules/student-data-model/src/Policies/StudentPolicy.php +++ b/app-modules/student-data-model/src/Policies/StudentPolicy.php @@ -44,6 +44,10 @@ class StudentPolicy { public function viewAny(Authenticatable $authenticatable): Response { + if (! $authenticatable->canAccessStudents()) { + return Response::deny('You do not have permission to view students.'); + } + return $authenticatable->canOrElse( abilities: 'student.view-any', denyResponse: 'You do not have permission to view students.' diff --git a/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/Concerns/HasSharedFormConfiguration.php b/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/Concerns/HasSharedFormConfiguration.php index 8999527271..4cd81fc8c5 100644 --- a/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/Concerns/HasSharedFormConfiguration.php +++ b/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/Concerns/HasSharedFormConfiguration.php @@ -36,26 +36,26 @@ namespace AdvisingApp\Survey\Filament\Resources\SurveyResource\Pages\Concerns; -use Filament\Forms\Get; -use Filament\Forms\Components\Grid; use AdvisingApp\Form\Enums\Rounding; +use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use AdvisingApp\Form\Rules\IsDomain; +use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; use AdvisingApp\Survey\Models\Survey; -use App\Forms\Components\ColorSelect; -use Filament\Forms\Components\Select; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Components\Section; -use FilamentTiptapEditor\TiptapEditor; +use AdvisingApp\Survey\Models\SurveyField; +use AdvisingApp\Survey\Models\SurveyStep; +use App\Filament\Fields\ColorSelect; +use Filament\Forms\Components\Grid; use Filament\Forms\Components\Repeater; -use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\Section; +use Filament\Forms\Components\Select; use Filament\Forms\Components\TagsInput; +use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; -use AdvisingApp\Survey\Models\SurveyStep; -use AdvisingApp\Survey\Models\SurveyField; +use Filament\Forms\Components\Toggle; +use Filament\Forms\Get; use FilamentTiptapEditor\Enums\TiptapOutput; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use FilamentTiptapEditor\TiptapEditor; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; -use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; trait HasSharedFormConfiguration { diff --git a/app-modules/task/src/Filament/Concerns/TaskEditForm.php b/app-modules/task/src/Filament/Concerns/TaskEditForm.php index ab979ce1f3..5340f9c8bd 100644 --- a/app-modules/task/src/Filament/Concerns/TaskEditForm.php +++ b/app-modules/task/src/Filament/Concerns/TaskEditForm.php @@ -36,6 +36,7 @@ namespace AdvisingApp\Task\Filament\Concerns; +use App\Filament\Fields\EducatableSelect; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; @@ -66,15 +67,8 @@ public function editFormFields(): array ->nullable() ->searchable(['name', 'email']) ->default(auth()->id()), - MorphToSelect::make('concern') - ->label('Related To') - ->searchable() - ->types([ - Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), - ]), + EducatableSelect::make('concern') + ->label('Related To'), ]; } } diff --git a/app-modules/task/src/Filament/Resources/TaskResource/Pages/CreateTask.php b/app-modules/task/src/Filament/Resources/TaskResource/Pages/CreateTask.php index e22833cc6e..62a9ffeced 100644 --- a/app-modules/task/src/Filament/Resources/TaskResource/Pages/CreateTask.php +++ b/app-modules/task/src/Filament/Resources/TaskResource/Pages/CreateTask.php @@ -36,6 +36,7 @@ namespace AdvisingApp\Task\Filament\Resources\TaskResource\Pages; +use App\Filament\Fields\EducatableSelect; use Filament\Forms\Form; use Illuminate\Support\Arr; use AdvisingApp\Task\Models\Task; @@ -75,15 +76,8 @@ public function form(Form $form): Form ->nullable() ->searchable(['name', 'email']) ->default(auth()->id()), - MorphToSelect::make('concern') - ->label('Related To') - ->searchable() - ->types([ - Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), - ]), + EducatableSelect::make('concern') + ->label('Related To'), ]); } diff --git a/app/Forms/Components/ColorSelect.php b/app/Filament/Fields/ColorSelect.php similarity index 98% rename from app/Forms/Components/ColorSelect.php rename to app/Filament/Fields/ColorSelect.php index 4f6ea2e82f..51ca0c0638 100644 --- a/app/Forms/Components/ColorSelect.php +++ b/app/Filament/Fields/ColorSelect.php @@ -34,10 +34,10 @@ */ -namespace App\Forms\Components; +namespace App\Filament\Fields; -use Filament\Support\Colors\Color; use Filament\Forms\Components\Select; +use Filament\Support\Colors\Color; class ColorSelect extends Select { diff --git a/app/Filament/Fields/EducatableSelect.php b/app/Filament/Fields/EducatableSelect.php new file mode 100644 index 0000000000..4b4dc8ad2c --- /dev/null +++ b/app/Filament/Fields/EducatableSelect.php @@ -0,0 +1,123 @@ +name($name); + } + + public static function make(string $name): EducatableSelect | MorphToSelect + { + if (auth()->user()->canAccessStudents() && auth()->user()->canAccessProspects()) { + return MorphToSelect::make($name) + ->searchable() + ->types([ + static::getStudentType(), + static::getProspectType(), + ]); + } + + $static = app(static::class, ['name' => $name]); + $static->configure(); + + return $static; + } + + public static function getStudentType(): Type + { + return MorphToSelect\Type::make(Student::class) + ->titleAttribute(Student::displayNameKey()); + } + + public static function getProspectType(): Type + { + return MorphToSelect\Type::make(Prospect::class) + ->titleAttribute(Prospect::displayNameKey()); + } + + public function getChildComponents(): array + { + $relationship = $this->getRelationship(); + $typeColumn = $relationship->getMorphType(); + $keyColumn = $relationship->getForeignKeyName(); + + $canAccessStudents = auth()->user()->canAccessStudents(); + $canAccessProspects = auth()->user()->canAccessProspects(); + + $type = match (true) { + $canAccessStudents => static::getStudentType(), + $canAccessProspects => static::getProspectType(), + default => null, + }; + + if (! $type) { + return []; + } + + return [ + Hidden::make($typeColumn) + ->dehydrateStateUsing(fn (): string => $type->getAlias()), + Select::make($keyColumn) + ->label($this->getLabel()) + ->options($type->getOptionsUsing) + ->getSearchResultsUsing($type->getSearchResultsUsing) + ->getOptionLabelUsing($type->getOptionLabelUsing) + ->required($this->isRequired()) + ->searchable(), + ]; + } + + public function required(bool | Closure $condition = true): static + { + $this->isRequired = $condition; + + return $this; + } + + public function getRelationship(): MorphTo + { + return $this->getModelInstance()->{$this->getName()}(); + } + + public function isRequired(): bool + { + return (bool) $this->evaluate($this->isRequired); + } + + public function isHidden(): bool + { + if (parent::isHidden()) { + return true; + } + + if (! $this->isRequired()) { + return false; + } + + return ! (auth()->user()->canAccessProspects() || auth()->user()->canAccessStudents()); + } +} diff --git a/app/Filament/Resources/NotificationSettingResource/Pages/CreateNotificationSetting.php b/app/Filament/Resources/NotificationSettingResource/Pages/CreateNotificationSetting.php index 02fa1d29e4..b269579e47 100644 --- a/app/Filament/Resources/NotificationSettingResource/Pages/CreateNotificationSetting.php +++ b/app/Filament/Resources/NotificationSettingResource/Pages/CreateNotificationSetting.php @@ -36,14 +36,14 @@ namespace App\Filament\Resources\NotificationSettingResource\Pages; -use Filament\Forms\Form; -use App\Forms\Components\ColorSelect; -use Filament\Forms\Components\Textarea; -use Filament\Forms\Components\TextInput; +use App\Filament\Fields\ColorSelect; use App\Filament\Pages\EmailConfiguration; -use Filament\Resources\Pages\CreateRecord; use App\Filament\Resources\NotificationSettingResource; use Filament\Forms\Components\SpatieMediaLibraryFileUpload; +use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TextInput; +use Filament\Forms\Form; +use Filament\Resources\Pages\CreateRecord; class CreateNotificationSetting extends CreateRecord { diff --git a/app/Filament/Resources/NotificationSettingResource/Pages/EditNotificationSetting.php b/app/Filament/Resources/NotificationSettingResource/Pages/EditNotificationSetting.php index d6c6fcc526..57cbf5dcc4 100644 --- a/app/Filament/Resources/NotificationSettingResource/Pages/EditNotificationSetting.php +++ b/app/Filament/Resources/NotificationSettingResource/Pages/EditNotificationSetting.php @@ -36,15 +36,15 @@ namespace App\Filament\Resources\NotificationSettingResource\Pages; -use Filament\Forms\Form; +use App\Filament\Fields\ColorSelect; +use App\Filament\Pages\EmailConfiguration; +use App\Filament\Resources\NotificationSettingResource; use Filament\Actions\DeleteAction; -use App\Forms\Components\ColorSelect; +use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; +use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; -use App\Filament\Pages\EmailConfiguration; -use App\Filament\Resources\NotificationSettingResource; -use Filament\Forms\Components\SpatieMediaLibraryFileUpload; class EditNotificationSetting extends EditRecord { diff --git a/app/Livewire/TaskKanban.php b/app/Livewire/TaskKanban.php index fa2cb96147..f31b227225 100644 --- a/app/Livewire/TaskKanban.php +++ b/app/Livewire/TaskKanban.php @@ -36,6 +36,7 @@ namespace App\Livewire; +use App\Filament\Fields\EducatableSelect; use Exception; use Livewire\Component; use Illuminate\Support\Arr; @@ -153,15 +154,8 @@ public function createTaskAction(): Action ->nullable() ->searchable(['name', 'email']) ->default(auth()->id()), - MorphToSelect::make('concern') - ->label('Related To') - ->searchable() - ->types([ - Type::make(Student::class) - ->titleAttribute(Student::displayNameKey()), - Type::make(Prospect::class) - ->titleAttribute(Prospect::displayNameKey()), - ]), + EducatableSelect::make('concern') + ->label('Related To'), ]) ->action(function (array $data, array $arguments) { $record = new Task(Arr::except($data, 'assigned_to')); diff --git a/app/Models/User.php b/app/Models/User.php index 798a326208..254333b2f8 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -372,4 +372,14 @@ protected function serializeDate(DateTimeInterface $date): string { return $date->format(config('project.datetime_format') ?? 'Y-m-d H:i:s'); } + + public function canAccessStudents(): bool + { + return false; + } + + public function canAccessProspects(): bool + { + return false; + } } From ec10c7cdbef2af331e4cb81f45462af901571ea1 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:24:17 -0500 Subject: [PATCH 018/152] Clean up action validation. --- .../inventory-management/database/seeders/AssetSeeder.php | 7 ------- .../src/Filament/Actions/CheckInAssetHeaderAction.php | 5 ++--- .../src/Filament/Actions/CheckOutAssetHeaderAction.php | 3 +-- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/app-modules/inventory-management/database/seeders/AssetSeeder.php b/app-modules/inventory-management/database/seeders/AssetSeeder.php index 4baa6c6f61..9dc2eab33c 100644 --- a/app-modules/inventory-management/database/seeders/AssetSeeder.php +++ b/app-modules/inventory-management/database/seeders/AssetSeeder.php @@ -38,8 +38,6 @@ use Illuminate\Database\Seeder; use AdvisingApp\InventoryManagement\Models\Asset; -use AdvisingApp\InventoryManagement\Models\AssetCheckIn; -use AdvisingApp\InventoryManagement\Models\AssetCheckOut; use AdvisingApp\InventoryManagement\Models\MaintenanceActivity; class AssetSeeder extends Seeder @@ -57,11 +55,6 @@ public function run(): void ->randomizeState() ->for($asset, 'asset') ->create(); - - AssetCheckOut::factory() - ->has(AssetCheckIn::factory(), 'checkIn') - ->for($asset, 'asset') - ->create(); } }); } diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php index 4b7161533f..2c2b3da131 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -30,8 +30,7 @@ protected function setUp(): void $this->form([ Textarea::make('notes') - ->autofocus() - ->required(), + ->autofocus(), Select::make('status_id') ->relationship('status', 'name') ->preload() @@ -59,7 +58,7 @@ protected function setUp(): void 'checked_in_from_type' => $asset->latestCheckOut->checked_out_to_type, 'checked_in_from_id' => $asset->latestCheckOut->checked_out_to_id, 'notes' => $data['notes'], - 'checked_in_at' => now(), + 'checked_in_at' => $data['checked_in_at'] ?? now(), ]); $asset->update([ diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php index 9bb252cdd5..59d59532a7 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -57,8 +57,7 @@ protected function setUp(): void ->searchable() ->required(), Textarea::make('notes') - ->autofocus() - ->required(), + ->autofocus(), DateTimePicker::make('expected_check_in_at') ->label('Expected Return Date'), ]); From b336e7e2629e1d81d30a5bd4dd15a9ade0ca9630 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:29:11 -0500 Subject: [PATCH 019/152] Update policies, roles. --- .../config/roles/api/inventory_management.php | 6 ++ .../config/roles/web/inventory_management.php | 6 ++ ...hangePolicy.php => AssetCheckInPolicy.php} | 42 ++++---- .../src/Policies/AssetCheckOutPolicy.php | 100 ++++++++++++++++++ 4 files changed, 133 insertions(+), 21 deletions(-) rename app-modules/inventory-management/src/Policies/{AssetExchangePolicy.php => AssetCheckInPolicy.php} (75%) create mode 100644 app-modules/inventory-management/src/Policies/AssetCheckOutPolicy.php diff --git a/app-modules/inventory-management/config/roles/api/inventory_management.php b/app-modules/inventory-management/config/roles/api/inventory_management.php index 268edc7499..d7c70b0afb 100644 --- a/app-modules/inventory-management/config/roles/api/inventory_management.php +++ b/app-modules/inventory-management/config/roles/api/inventory_management.php @@ -48,6 +48,12 @@ 'asset_type' => [ '*', ], + 'asset_check_in' => [ + '*', + ], + 'asset_check_out' => [ + '*', + ], 'maintenance_activity' => [ '*', ], diff --git a/app-modules/inventory-management/config/roles/web/inventory_management.php b/app-modules/inventory-management/config/roles/web/inventory_management.php index 268edc7499..d7c70b0afb 100644 --- a/app-modules/inventory-management/config/roles/web/inventory_management.php +++ b/app-modules/inventory-management/config/roles/web/inventory_management.php @@ -48,6 +48,12 @@ 'asset_type' => [ '*', ], + 'asset_check_in' => [ + '*', + ], + 'asset_check_out' => [ + '*', + ], 'maintenance_activity' => [ '*', ], diff --git a/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php b/app-modules/inventory-management/src/Policies/AssetCheckInPolicy.php similarity index 75% rename from app-modules/inventory-management/src/Policies/AssetExchangePolicy.php rename to app-modules/inventory-management/src/Policies/AssetCheckInPolicy.php index 031744e4f1..9e57d18e83 100644 --- a/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php +++ b/app-modules/inventory-management/src/Policies/AssetCheckInPolicy.php @@ -38,63 +38,63 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; -use AdvisingApp\InventoryManagement\Models\AssetExchange; +use AdvisingApp\InventoryManagement\Models\AssetCheckIn; -class AssetExchangePolicy +class AssetCheckInPolicy { public function viewAny(Authenticatable $authenticatable): Response { return $authenticatable->canOrElse( - abilities: 'asset_exchange.view-any', - denyResponse: 'You do not have permission to view asset exchanges.' + abilities: 'asset_check_in.view-any', + denyResponse: 'You do not have permission to view asset check ins.' ); } - public function view(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function view(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.view', "asset_exchange.{$assetExchange->id}.view"], - denyResponse: 'You do not have permission to view this asset exchange.' + abilities: ['asset_check_in.*.view', "asset_check_in.{$assetCheckIn->id}.view"], + denyResponse: 'You do not have permission to view this asset check in.' ); } public function create(Authenticatable $authenticatable): Response { return $authenticatable->canOrElse( - abilities: 'asset_exchange.create', - denyResponse: 'You do not have permission to create asset exchanges.' + abilities: 'asset_check_in.create', + denyResponse: 'You do not have permission to create asset check ins.' ); } - public function update(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function update(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.update', "asset_exchange.{$assetExchange->id}.update"], - denyResponse: 'You do not have permission to update this asset exchange.' + abilities: ['asset_check_in.*.update', "asset_check_in.{$assetCheckIn->id}.update"], + denyResponse: 'You do not have permission to update this asset check in.' ); } - public function delete(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function delete(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.delete', "asset_exchange.{$assetExchange->id}.delete"], - denyResponse: 'You do not have permission to delete this asset exchange.' + abilities: ['asset_check_in.*.delete', "asset_check_in.{$assetCheckIn->id}.delete"], + denyResponse: 'You do not have permission to delete this asset check in.' ); } - public function restore(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function restore(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.restore', "asset_exchange.{$assetExchange->id}.restore"], - denyResponse: 'You do not have permission to restore this asset exchange.' + abilities: ['asset_check_in.*.restore', "asset_check_in.{$assetCheckIn->id}.restore"], + denyResponse: 'You do not have permission to restore this asset check in.' ); } - public function forceDelete(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function forceDelete(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.force-delete', "asset_exchange.{$assetExchange->id}.force-delete"], - denyResponse: 'You do not have permission to permanently delete this asset exchange.' + abilities: ['asset_check_in.*.force-delete', "asset_check_in.{$assetCheckIn->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset check in.' ); } } diff --git a/app-modules/inventory-management/src/Policies/AssetCheckOutPolicy.php b/app-modules/inventory-management/src/Policies/AssetCheckOutPolicy.php new file mode 100644 index 0000000000..cd227de8ca --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetCheckOutPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetCheckOut; + +class AssetCheckOutPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_check_out.view-any', + denyResponse: 'You do not have permission to view asset check outs.' + ); + } + + public function view(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.view', "asset_check_out.{$assetCheckOut->id}.view"], + denyResponse: 'You do not have permission to view this asset check out.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_check_out.create', + denyResponse: 'You do not have permission to create asset check outs.' + ); + } + + public function update(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.update', "asset_check_out.{$assetCheckOut->id}.update"], + denyResponse: 'You do not have permission to update this asset check out.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.delete', "asset_check_out.{$assetCheckOut->id}.delete"], + denyResponse: 'You do not have permission to delete this asset check out.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.restore', "asset_check_out.{$assetCheckOut->id}.restore"], + denyResponse: 'You do not have permission to restore this asset check out.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.force-delete', "asset_check_out.{$assetCheckOut->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset check out.' + ); + } +} From 7c060018f4127e3ff2c15e485e0bfc440d295541 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Wed, 3 Jan 2024 13:37:46 +0000 Subject: [PATCH 020/152] Refactor to hasLicense() / hasAnyLicense() --- app/Filament/Fields/EducatableSelect.php | 22 +++++------- .../LicensesRelationManager.php | 2 +- app/Models/User.php | 34 +++++++++++++++++-- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/app/Filament/Fields/EducatableSelect.php b/app/Filament/Fields/EducatableSelect.php index 4b4dc8ad2c..cc324d878f 100644 --- a/app/Filament/Fields/EducatableSelect.php +++ b/app/Filament/Fields/EducatableSelect.php @@ -2,6 +2,7 @@ namespace App\Filament\Fields; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\StudentDataModel\Models\Student; use Closure; @@ -32,7 +33,7 @@ final public function __construct(string $name) public static function make(string $name): EducatableSelect | MorphToSelect { - if (auth()->user()->canAccessStudents() && auth()->user()->canAccessProspects()) { + if (auth()->user()->hasLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])) { return MorphToSelect::make($name) ->searchable() ->types([ @@ -61,16 +62,9 @@ public static function getProspectType(): Type public function getChildComponents(): array { - $relationship = $this->getRelationship(); - $typeColumn = $relationship->getMorphType(); - $keyColumn = $relationship->getForeignKeyName(); - - $canAccessStudents = auth()->user()->canAccessStudents(); - $canAccessProspects = auth()->user()->canAccessProspects(); - $type = match (true) { - $canAccessStudents => static::getStudentType(), - $canAccessProspects => static::getProspectType(), + auth()->user()->hasLicense(LicenseType::RetentionCrm) => static::getStudentType(), + auth()->user()->hasLicense(LicenseType::RecruitmentCrm) => static::getProspectType(), default => null, }; @@ -78,10 +72,12 @@ public function getChildComponents(): array return []; } + $relationship = $this->getRelationship(); + return [ - Hidden::make($typeColumn) + Hidden::make($relationship->getMorphType()) ->dehydrateStateUsing(fn (): string => $type->getAlias()), - Select::make($keyColumn) + Select::make($relationship->getForeignKeyName()) ->label($this->getLabel()) ->options($type->getOptionsUsing) ->getSearchResultsUsing($type->getSearchResultsUsing) @@ -118,6 +114,6 @@ public function isHidden(): bool return false; } - return ! (auth()->user()->canAccessProspects() || auth()->user()->canAccessStudents()); + return ! auth()->user()->hasAnyLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm]); } } diff --git a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php index 1487568274..5febb75f12 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php @@ -71,7 +71,7 @@ public function form(Form $form): Form /** @var User $ownerRecord */ $ownerRecord = $this->getOwnerRecord(); - return ! LicenseType::from($value)->hasAvailableLicenses() || $ownerRecord->licenses()->where('type', $value)->exists(); + return (! LicenseType::from($value)->hasAvailableLicenses()) || $ownerRecord->hasLicense($value); }) ->required(), ]); diff --git a/app/Models/User.php b/app/Models/User.php index 94eaaf5598..8d0a94f63b 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -36,10 +36,12 @@ namespace App\Models; +use AdvisingApp\Authorization\Enums\LicenseType; use Filament\Panel; use DateTimeInterface; use AdvisingApp\Task\Models\Task; use AdvisingApp\Team\Models\Team; +use Illuminate\Support\Arr; use Spatie\MediaLibrary\HasMedia; use App\Support\HasAdvancedFilter; use AdvisingApp\Team\Models\TeamUser; @@ -379,13 +381,39 @@ protected function serializeDate(DateTimeInterface $date): string return $date->format(config('project.datetime_format') ?? 'Y-m-d H:i:s'); } - public function canAccessStudents(): bool + /** + * @param LicenseType | string | array $type + */ + public function hasLicense(LicenseType | string | array $type): bool { - return false; + foreach (Arr::wrap($type) as $type) { + if (! ($type instanceof LicenseType)) { + $type = LicenseType::from($type); + } + + if ($this->licenses->doesntContain('type', $type)) { + return false; + } + } + + return true; } - public function canAccessProspects(): bool + /** + * @param LicenseType | string | array $type + */ + public function hasAnyLicense(LicenseType | string | array $type): bool { + foreach (Arr::wrap($type) as $type) { + if (! ($type instanceof LicenseType)) { + $type = LicenseType::from($type); + } + + if ($this->licenses->contains('type', $type)) { + return true; + } + } + return false; } } From 3d83b155866e96cc9cd0393bb6c8bd27fcda7252 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:46:22 -0500 Subject: [PATCH 021/152] Add classification controls to asset status resource. --- .../database/factories/AssetCheckInFactory.php | 6 +++--- .../database/factories/AssetCheckOutFactory.php | 1 - .../AssetStatusResource/Pages/CreateAssetStatus.php | 6 ++++++ .../AssetStatusResource/Pages/ListAssetStatuses.php | 3 +++ .../Resources/AssetStatusResource/Pages/ViewAssetStatus.php | 1 + 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php index 793d21673d..ec6cf59f3e 100644 --- a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php +++ b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php @@ -16,12 +16,12 @@ class AssetCheckInFactory extends Factory { public function definition(): array { - $checkedOutBy = User::factory()->create(); + $checkedInBy = User::factory()->create(); return [ 'asset_id' => Asset::factory(), - 'checked_in_by_type' => $checkedOutBy->getMorphClass(), - 'checked_in_by_id' => $checkedOutBy->getKey(), + 'checked_in_by_type' => $checkedInBy->getMorphClass(), + 'checked_in_by_id' => $checkedInBy->getKey(), 'checked_in_from_type' => fake()->randomElement([ (new Student())->getMorphClass(), (new Prospect())->getMorphClass(), diff --git a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php index f4e1d061c3..f1509098b2 100644 --- a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php +++ b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php @@ -21,7 +21,6 @@ public function definition(): array return [ 'asset_id' => Asset::factory(), - // TODO Add variance to this column so that some check outs do not have corresponding check ins 'asset_check_in_id' => null, 'checked_out_by_type' => $checkedOutBy->getMorphClass(), 'checked_out_by_id' => $checkedOutBy->getKey(), diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/CreateAssetStatus.php b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/CreateAssetStatus.php index 8e2facb1c2..62e4601954 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/CreateAssetStatus.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/CreateAssetStatus.php @@ -37,8 +37,10 @@ namespace AdvisingApp\InventoryManagement\Filament\Resources\AssetStatusResource\Pages; use Filament\Forms\Form; +use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\CreateRecord; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; use AdvisingApp\InventoryManagement\Filament\Resources\AssetStatusResource; class CreateAssetStatus extends CreateRecord @@ -51,6 +53,10 @@ public function form(Form $form): Form ->schema([ TextInput::make('name') ->required(), + Select::make('classification') + ->options(SystemAssetStatusClassification::class) + ->enum(SystemAssetStatusClassification::class) + ->required(), ]); } } diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ListAssetStatuses.php b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ListAssetStatuses.php index a67d22af3f..123fa8d625 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ListAssetStatuses.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ListAssetStatuses.php @@ -57,6 +57,9 @@ public function table(Table $table): Table TextColumn::make('name') ->searchable() ->sortable(), + TextColumn::make('classification') + ->searchable() + ->sortable(), ]) ->filters([ ]) diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ViewAssetStatus.php b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ViewAssetStatus.php index ed06f374c8..7eb133e489 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ViewAssetStatus.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ViewAssetStatus.php @@ -54,6 +54,7 @@ public function infolist(Infolist $infolist): Infolist Section::make() ->schema([ TextEntry::make('name'), + TextEntry::make('classification'), ]), ]); } From f048f987fcface7007ffdea91494bf46408a107f Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:59:10 -0500 Subject: [PATCH 022/152] Clean up. --- .../src/Filament/Actions/CheckInAssetHeaderAction.php | 5 +++-- .../src/Filament/Actions/CheckOutAssetHeaderAction.php | 5 +---- app-modules/inventory-management/src/Models/Asset.php | 10 +++++----- .../src/Observers/AssetCheckInObserver.php | 3 --- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php index 2c2b3da131..773cc1a23f 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -47,14 +47,15 @@ protected function setUp(): void /** @var Asset $asset */ $asset = $this->getRecord(); - if (! $asset->isAvailable()) { + if (! $asset->isCheckedOut()) { $this->failure(); } $asset->checkIns()->create([ 'checked_in_by_type' => auth()->user()?->getMorphClass(), 'checked_in_by_id' => auth()->user()?->id, - // TODO Should we still have this be configurable? Or should the expectation be that this information is the same as the latest check out? + // TODO Should this always simply be the latest check out, or do we want to support + // The possibility that the person checking in is different than whoever checked out? 'checked_in_from_type' => $asset->latestCheckOut->checked_out_to_type, 'checked_in_from_id' => $asset->latestCheckOut->checked_out_to_id, 'notes' => $data['notes'], diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php index 59d59532a7..fe64c51ed2 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -80,11 +80,8 @@ protected function setUp(): void 'expected_check_in_at' => $data['expected_check_in_at'], ]); - // TODO We may want to move this to an observer in order to clean up... - $checkedOutStatus = AssetStatus::checkedOut()->first(); - $asset->update([ - 'status_id' => $checkedOutStatus->id, + 'status_id' => AssetStatus::checkedOut()->first()->id, ]); $this->success(); diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index 4ad9567445..4c949fba87 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -85,6 +85,11 @@ public function checkOuts(): HasMany return $this->hasMany(AssetCheckOut::class, 'asset_id'); } + public function checkIns(): HasMany + { + return $this->hasMany(AssetCheckIn::class, 'asset_id'); + } + public function latestCheckOut(): HasOne { return $this->hasOne(AssetCheckOut::class, 'asset_id') @@ -97,11 +102,6 @@ public function latestCheckIn(): HasOne ->latest('checked_in_at'); } - public function checkIns(): HasMany - { - return $this->hasMany(AssetCheckIn::class, 'asset_id'); - } - public function isAvailable(): bool { return $this->status->classification === SystemAssetStatusClassification::Available diff --git a/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php b/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php index 54d9e4fa18..6909116d0b 100644 --- a/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php +++ b/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php @@ -42,9 +42,6 @@ class AssetCheckInObserver { public function created(AssetCheckIn $checkIn): void { - ray('AssetCheckInObserver::created()'); - ray($checkIn->asset->latestCheckOut); - $checkIn->asset->latestCheckOut->update([ 'asset_check_in_id' => $checkIn->id, ]); From 2b0c01c4ad0ebe7d45856e6fb81586dc735e79bb Mon Sep 17 00:00:00 2001 From: dgoetzit Date: Wed, 3 Jan 2024 14:02:35 +0000 Subject: [PATCH 023/152] chore: fix enforcement of copyright on all files --- .../factories/AssetCheckInFactory.php | 34 +++++++++++++++++++ .../factories/AssetCheckOutFactory.php | 34 +++++++++++++++++++ ...28_174428_create_asset_check_ins_table.php | 34 +++++++++++++++++++ ...8_174437_create_asset_check_outs_table.php | 34 +++++++++++++++++++ .../Actions/CheckInAssetHeaderAction.php | 34 +++++++++++++++++++ .../Actions/CheckOutAssetHeaderAction.php | 34 +++++++++++++++++++ .../src/Models/AssetCheckIn.php | 34 +++++++++++++++++++ .../src/Models/AssetCheckOut.php | 34 +++++++++++++++++++ 8 files changed, 272 insertions(+) diff --git a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php index ec6cf59f3e..aec0066bd4 100644 --- a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php +++ b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Database\Factories; use App\Models\User; diff --git a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php index f1509098b2..908cc3623d 100644 --- a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php +++ b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Database\Factories; use Carbon\Carbon; diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php index 08c435f4bb..f837c2993a 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php index a37094dcd4..4dd77f8ed2 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php index 773cc1a23f..9419287ff7 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Filament\Actions; use Filament\Actions\Action; diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php index fe64c51ed2..f417c58289 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Filament\Actions; use Filament\Forms\Get; diff --git a/app-modules/inventory-management/src/Models/AssetCheckIn.php b/app-modules/inventory-management/src/Models/AssetCheckIn.php index edd1f6dca2..cef99b06aa 100644 --- a/app-modules/inventory-management/src/Models/AssetCheckIn.php +++ b/app-modules/inventory-management/src/Models/AssetCheckIn.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Models; use App\Models\BaseModel; diff --git a/app-modules/inventory-management/src/Models/AssetCheckOut.php b/app-modules/inventory-management/src/Models/AssetCheckOut.php index dad253e8c2..121c9de71b 100644 --- a/app-modules/inventory-management/src/Models/AssetCheckOut.php +++ b/app-modules/inventory-management/src/Models/AssetCheckOut.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Models; use App\Models\BaseModel; From 6547f583043bfce08aa49f8cbe2a6655499a5372 Mon Sep 17 00:00:00 2001 From: joelicatajr Date: Wed, 3 Jan 2024 14:06:00 +0000 Subject: [PATCH 024/152] chore: fix code style --- .../inventory-management/src/Models/AssetLocation.php | 6 +++--- app-modules/inventory-management/src/Models/AssetType.php | 6 +++--- .../src/Models/MaintenanceActivity.php | 8 ++++---- .../src/Models/ServiceRequestStatus.php | 1 - 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app-modules/inventory-management/src/Models/AssetLocation.php b/app-modules/inventory-management/src/Models/AssetLocation.php index 3bd7826ec5..c7d4618523 100644 --- a/app-modules/inventory-management/src/Models/AssetLocation.php +++ b/app-modules/inventory-management/src/Models/AssetLocation.php @@ -36,11 +36,11 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasMany; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; class AssetLocation extends BaseModel implements Auditable { diff --git a/app-modules/inventory-management/src/Models/AssetType.php b/app-modules/inventory-management/src/Models/AssetType.php index 5c8c192a87..e9b523bab4 100644 --- a/app-modules/inventory-management/src/Models/AssetType.php +++ b/app-modules/inventory-management/src/Models/AssetType.php @@ -36,11 +36,11 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasMany; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; class AssetType extends BaseModel implements Auditable { diff --git a/app-modules/inventory-management/src/Models/MaintenanceActivity.php b/app-modules/inventory-management/src/Models/MaintenanceActivity.php index 91c4f8c04c..0d0421dda9 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceActivity.php +++ b/app-modules/inventory-management/src/Models/MaintenanceActivity.php @@ -36,12 +36,12 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; -use AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus; class MaintenanceActivity extends BaseModel implements Auditable { diff --git a/app-modules/service-management/src/Models/ServiceRequestStatus.php b/app-modules/service-management/src/Models/ServiceRequestStatus.php index 40bd3148b5..5250ece7c4 100644 --- a/app-modules/service-management/src/Models/ServiceRequestStatus.php +++ b/app-modules/service-management/src/Models/ServiceRequestStatus.php @@ -40,7 +40,6 @@ use App\Models\BaseModel; use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\ServiceManagement\Enums\ColumnColorOptions; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; From 2971b30371d0df3a04c8a9ee4bcaae8da078827f Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 17:51:41 -0500 Subject: [PATCH 025/152] Init event registration Signed-off-by: Kevin Ullyott --- .../src/Models/SubmissibleAuthentication.php | 2 +- ..._create_event_registration_forms_table.php | 60 ++++ ...27_194216_create_event_attendees_table.php | 56 ++++ ...7_create_event_attendee_entities_table.php | 52 ++++ ...te_event_registration_form_steps_table.php | 55 ++++ ...e_event_registration_form_fields_table.php | 58 ++++ ...egistration_form_authentications_table.php | 54 ++++ ...nt_registration_form_submissions_table.php | 59 ++++ ...0_create_survey_field_submission_table.php | 54 ++++ .../src/Enums/EventAttendeeStatus.php | 22 ++ .../EventRegistrationWidgetController.php | 263 ++++++++++++++++++ .../src/Models/EventAttendee.php | 61 ++++ .../src/Models/EventRegistrationForm.php | 89 ++++++ .../EventRegistrationFormAuthentication.php | 61 ++++ .../src/Models/EventRegistrationFormField.php | 71 +++++ .../src/Models/EventRegistrationFormStep.php | 71 +++++ .../EventRegistrationFormSubmission.php | 130 +++++++++ ...icateEventRegistrationFormNotification.php | 70 +++++ .../MeetingCenterServiceProvider.php | 12 + ...survey_roles.php => survey_management.php} | 0 20 files changed, 1299 insertions(+), 1 deletion(-) create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194215_create_event_registration_forms_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194216_create_event_attendees_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194217_create_event_attendee_entities_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194226_create_event_registration_form_steps_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194227_create_event_registration_form_fields_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194228_create_event_registration_form_authentications_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194230_create_survey_field_submission_table.php create mode 100644 app-modules/meeting-center/src/Enums/EventAttendeeStatus.php create mode 100644 app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php create mode 100644 app-modules/meeting-center/src/Models/EventAttendee.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationForm.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationFormAuthentication.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationFormField.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationFormStep.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php create mode 100644 app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php rename app-modules/survey/config/roles/web/{survey_roles.php => survey_management.php} (100%) diff --git a/app-modules/form/src/Models/SubmissibleAuthentication.php b/app-modules/form/src/Models/SubmissibleAuthentication.php index 9e6c8d5523..b5a0360f6f 100644 --- a/app-modules/form/src/Models/SubmissibleAuthentication.php +++ b/app-modules/form/src/Models/SubmissibleAuthentication.php @@ -66,7 +66,7 @@ public function prunable(): Builder ->where('created_at', '<', now()->subMonth()); } - public function author(): MorphTo + public function author(): MorphTo|BelongsTo { return $this->morphTo(); } diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194215_create_event_registration_forms_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194215_create_event_registration_forms_table.php new file mode 100644 index 0000000000..8571656d00 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194215_create_event_registration_forms_table.php @@ -0,0 +1,60 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_forms', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); + $table->boolean('embed_enabled')->default(false); + $table->json('allowed_domains')->nullable(); + $table->string('primary_color')->nullable(); + $table->string('rounding')->nullable(); + $table->boolean('is_wizard')->default(false); + $table->boolean('recaptcha_enabled')->default(false); + $table->json('content')->nullable(); + + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194216_create_event_attendees_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194216_create_event_attendees_table.php new file mode 100644 index 0000000000..2bcee55835 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194216_create_event_attendees_table.php @@ -0,0 +1,56 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_attendees', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->string('status'); + $table->string('email'); + $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); + + $table->timestamps(); + + $table->unique(['email', 'event_id']); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194217_create_event_attendee_entities_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194217_create_event_attendee_entities_table.php new file mode 100644 index 0000000000..45532122f7 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194217_create_event_attendee_entities_table.php @@ -0,0 +1,52 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_attendees_entities', function (Blueprint $table) { + $table->string('entity_id'); + $table->string('entity_type'); + $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); + + $table->unique(['entity_id', 'entity_type', 'event_attendee_id']); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194226_create_event_registration_form_steps_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194226_create_event_registration_form_steps_table.php new file mode 100644 index 0000000000..bae9ad05b1 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194226_create_event_registration_form_steps_table.php @@ -0,0 +1,55 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_steps', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->text('label'); + $table->json('content')->nullable(); + $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); + $table->integer('sort'); + + $table->timestamps(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194227_create_event_registration_form_fields_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194227_create_event_registration_form_fields_table.php new file mode 100644 index 0000000000..4b8f20c26a --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194227_create_event_registration_form_fields_table.php @@ -0,0 +1,58 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_fields', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->text('label'); + $table->text('type'); + $table->boolean('is_required'); + $table->json('config'); + + $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); + $table->foreignUuid('step_id')->nullable()->constrained('event_registration_form_steps')->cascadeOnDelete(); + + $table->timestamps(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194228_create_event_registration_form_authentications_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194228_create_event_registration_form_authentications_table.php new file mode 100644 index 0000000000..31216c9ba4 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194228_create_event_registration_form_authentications_table.php @@ -0,0 +1,54 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_authentications', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); + $table->string('code')->nullable(); + $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); + + $table->timestamps(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php new file mode 100644 index 0000000000..0165143dbd --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php @@ -0,0 +1,59 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_submissions', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); + $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); + $table->timestamp('submitted_at')->nullable(); + $table->timestamp('canceled_at')->nullable(); + $table->string('request_method')->nullable(); + $table->text('request_note')->nullable(); + $table->foreignUuid('requester_id')->nullable()->constrained('users')->nullOnDelete(); + + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194230_create_survey_field_submission_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194230_create_survey_field_submission_table.php new file mode 100644 index 0000000000..d5b0f6c326 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194230_create_survey_field_submission_table.php @@ -0,0 +1,54 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_field_submission', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->longText('response'); + $table->foreignUuid('field_id')->constrained('event_registration_form_fields')->cascadeOnDelete(); + $table->foreignUuid('submission_id')->constrained('event_registration_form_submissions')->cascadeOnDelete(); + + $table->timestamps(); + }); + } +}; diff --git a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php new file mode 100644 index 0000000000..f84db2a022 --- /dev/null +++ b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php @@ -0,0 +1,22 @@ + 'Not Attending', + default => $this->name, + }; + } +} diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php new file mode 100644 index 0000000000..39dd56722f --- /dev/null +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -0,0 +1,263 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Http\Controllers; + +use Closure; +use Illuminate\Support\Str; +use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use Filament\Support\Colors\Color; +use Illuminate\Support\Facades\URL; +use App\Http\Controllers\Controller; +use Illuminate\Support\Facades\Hash; +use AdvisingApp\Survey\Models\Survey; +use Illuminate\Support\Facades\Validator; +use Illuminate\Support\Facades\Notification; +use Symfony\Component\HttpFoundation\Response; +use AdvisingApp\Survey\Models\SurveySubmission; +use AdvisingApp\Form\Actions\GenerateFormKitSchema; +use AdvisingApp\MeetingCenter\Models\EventAttendee; +use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; +use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; +use AdvisingApp\Application\Models\ApplicationAuthentication; +use AdvisingApp\Form\Actions\ResolveSubmissionAuthorFromEmail; +use AdvisingApp\Form\Filament\Blocks\EducatableEmailFormFieldBlock; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; +use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; +use AdvisingApp\Form\Notifications\AuthenticateEventRegistrationFormNotification; + +class EventRegistrationWidgetController extends Controller +{ + public function view(GenerateFormKitSchema $generateSchema, EventRegistrationForm $form): JsonResponse + { + return response()->json( + [ + 'name' => $form->event->title, + 'description' => $form->event->description, + // TODO: Maybe get rid of this? It would never not be authenticated. + 'is_authenticated' => true, + 'authentication_url' => URL::signedRoute('event-registration.request-authentication', ['form' => $form]), + 'recaptcha_enabled' => $form->recaptcha_enabled, + ...($form->recaptcha_enabled ? [ + 'recaptcha_site_key' => app(GoogleRecaptchaSettings::class)->site_key, + ] : []), + 'schema' => $generateSchema($form), + 'primary_color' => Color::all()[$form->primary_color ?? 'blue'], + 'rounding' => $form->rounding, + ], + ); + } + + public function requestAuthentication(Request $request, EventRegistrationForm $form): JsonResponse + { + $data = $request->validate([ + 'email' => ['required', 'email'], + ]); + + $attendee = EventAttendee::firstOrNew( + [ + 'email' => $data['email'], + 'event_id' => $form->event_id, + ], + ); + + if (empty($attendee->status)) { + $attendee->status = EventAttendeeStatus::Pending; + } + + // TODO: When an EventAttendee is created, we should try and match it to an entity, perhaps in an observer. + $attendee->save(); + + $code = random_int(100000, 999999); + + $authentication = new EventRegistrationFormAuthentication(); + $authentication->author()->associate($attendee); + $authentication->submissible()->associate($form); + $authentication->code = Hash::make($code); + $authentication->save(); + + Notification::route('mail', $attendee->email)->notify(new AuthenticateEventRegistrationFormNotification($authentication, $code)); + + return response()->json([ + 'message' => "We've sent an authentication code to {$attendee->email}.", + 'authentication_url' => URL::signedRoute('event-registration.authenticate', [ + 'form' => $form, + 'authentication' => $authentication, + ]), + ]); + } + + public function authenticate(Request $request, Survey $survey, ApplicationAuthentication $authentication): JsonResponse + { + if ($authentication->isExpired()) { + return response()->json([ + 'is_expired' => true, + ]); + } + + $request->validate([ + 'code' => ['required', 'integer', 'digits:6', function (string $attribute, int $value, Closure $fail) use ($authentication) { + if (Hash::check($value, $authentication->code)) { + return; + } + + $fail('The provided code is invalid.'); + }], + ]); + + return response()->json([ + 'submission_url' => URL::signedRoute('surveys.submit', [ + 'survey' => $authentication, + 'application' => $authentication->submissible, + ]), + ]); + } + + public function store( + Request $request, + GenerateSubmissibleValidation $generateValidation, + ResolveSubmissionAuthorFromEmail $resolveSubmissionAuthorFromEmail, + Survey $survey, + ): JsonResponse { + $authentication = $request->query('authentication'); + + if (filled($authentication)) { + $authentication = ApplicationAuthentication::findOrFail($authentication); + } + + if ( + $survey->is_authenticated && + ($authentication?->isExpired() ?? true) + ) { + abort(Response::HTTP_UNAUTHORIZED); + } + + $validator = Validator::make( + $request->all(), + $generateValidation($survey) + ); + + if ($validator->fails()) { + return response()->json( + [ + 'errors' => (object) $validator->errors(), + ], + Response::HTTP_UNPROCESSABLE_ENTITY + ); + } + + /** @var SurveySubmission $submission */ + $submission = $survey->submissions()->make(); + + if ($authentication) { + $submission->author()->associate($authentication->author); + + $authentication->delete(); + } + + $submission->submitted_at = now(); + + $submission->save(); + + $data = $validator->validated(); + + unset($data['recaptcha-token']); + + if ($survey->is_wizard) { + foreach ($survey->steps as $step) { + $stepFields = $step->fields()->pluck('type', 'id')->all(); + + foreach ($data[$step->label] as $fieldId => $response) { + $submission->fields()->attach( + $fieldId, + ['id' => Str::orderedUuid(), 'response' => $response], + ); + + if ($submission->author) { + continue; + } + + if ($stepFields[$fieldId] !== EducatableEmailFormFieldBlock::type()) { + continue; + } + + $author = $resolveSubmissionAuthorFromEmail($response); + + if (! $author) { + continue; + } + + $submission->author()->associate($author); + } + } + } else { + $surveyFields = $survey->fields()->pluck('type', 'id')->all(); + + foreach ($data as $fieldId => $response) { + $submission->fields()->attach( + $fieldId, + ['id' => Str::orderedUuid(), 'response' => $response], + ); + + if ($submission->author) { + continue; + } + + if ($surveyFields[$fieldId] !== EducatableEmailFormFieldBlock::type()) { + continue; + } + + $author = $resolveSubmissionAuthorFromEmail($response); + + if (! $author) { + continue; + } + + $submission->author()->associate($author); + } + } + + $submission->save(); + + return response()->json( + [ + 'message' => 'Survey submitted successfully.', + ] + ); + } +} diff --git a/app-modules/meeting-center/src/Models/EventAttendee.php b/app-modules/meeting-center/src/Models/EventAttendee.php new file mode 100644 index 0000000000..fab1a5c640 --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventAttendee.php @@ -0,0 +1,61 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use App\Models\BaseModel; +use App\Models\Attributes\NoPermissions; +use Illuminate\Notifications\Notifiable; +use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; + +#[NoPermissions] +/** + * @mixin IdeHelperEventAttendee + */ +class EventAttendee extends BaseModel +{ + use Notifiable; + + protected $fillable = [ + 'status', + 'email', + 'event_id', + ]; + + protected $casts = [ + 'status' => EventAttendeeStatus::class, + ]; +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationForm.php b/app-modules/meeting-center/src/Models/EventRegistrationForm.php new file mode 100644 index 0000000000..672883ea58 --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationForm.php @@ -0,0 +1,89 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use AdvisingApp\Form\Enums\Rounding; +use AdvisingApp\Form\Models\Submissible; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; + +/** + * @mixin IdeHelperEventRegistrationForm + */ +class EventRegistrationForm extends Submissible +{ + protected $fillable = [ + 'form_id', + 'embed_enabled', + 'allowed_domains', + 'is_wizard', + 'recaptcha_enabled', + 'primary_color', + 'rounding', + 'content', + ]; + + protected $casts = [ + 'content' => 'array', + 'embed_enabled' => 'boolean', + 'allowed_domains' => 'array', + 'is_wizard' => 'boolean', + 'recaptcha_enabled' => 'boolean', + 'rounding' => Rounding::class, + ]; + + public function event(): BelongsTo + { + return $this + ->belongsTo(Event::class, 'event_id'); + } + + public function fields(): HasMany + { + return $this->hasMany(EventRegistrationFormField::class); + } + + public function steps(): HasMany + { + return $this->hasMany(EventRegistrationFormStep::class); + } + + public function submissions(): HasMany + { + return $this->hasMany(EventRegistrationFormSubmission::class); + } +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormAuthentication.php b/app-modules/meeting-center/src/Models/EventRegistrationFormAuthentication.php new file mode 100644 index 0000000000..d312ed5e03 --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormAuthentication.php @@ -0,0 +1,61 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use App\Models\Attributes\NoPermissions; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\Form\Models\SubmissibleAuthentication; + +#[NoPermissions] +/** + * @property-read EventRegistrationForm $submissible + * + * @mixin IdeHelperEventRegistrationFormAuthentication + */ +class EventRegistrationFormAuthentication extends SubmissibleAuthentication +{ + public function submissible(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationForm::class, 'form_id'); + } + + public function author(): BelongsTo + { + return $this->belongsTo(EventAttendee::class, 'event_attendee_id'); + } +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormField.php b/app-modules/meeting-center/src/Models/EventRegistrationFormField.php new file mode 100644 index 0000000000..7d1867c5c6 --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormField.php @@ -0,0 +1,71 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use AdvisingApp\Form\Models\SubmissibleField; +use Illuminate\Database\Eloquent\Relations\BelongsTo; + +/** + * @mixin IdeHelperEventRegistrationFormField + */ +class EventRegistrationFormField extends SubmissibleField +{ + protected $fillable = [ + 'config', + 'label', + 'type', + 'is_required', + 'form_id', + ]; + + protected $casts = [ + 'config' => 'array', + 'is_required' => 'bool', + ]; + + public function submissible(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationForm::class, 'form_id'); + } + + public function step(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationFormStep::class, 'step_id'); + } +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormStep.php b/app-modules/meeting-center/src/Models/EventRegistrationFormStep.php new file mode 100644 index 0000000000..89ed913a0f --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormStep.php @@ -0,0 +1,71 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use App\Models\Attributes\NoPermissions; +use AdvisingApp\Form\Models\SubmissibleStep; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; + +#[NoPermissions] +/** + * @mixin IdeHelperEventRegistrationFormStep + */ +class EventRegistrationFormStep extends SubmissibleStep +{ + protected $fillable = [ + 'label', + 'content', + 'sort', + ]; + + protected $casts = [ + 'content' => 'array', + 'sort' => 'integer', + ]; + + public function submissible(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationForm::class, 'form_id'); + } + + public function fields(): HasMany + { + return $this->hasMany(EventRegistrationFormField::class, 'step_id'); + } +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php new file mode 100644 index 0000000000..4a1392f1ae --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php @@ -0,0 +1,130 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use App\Models\User; +use AdvisingApp\Form\Models\Submission; +use Illuminate\Database\Eloquent\Builder; +use AdvisingApp\Form\Enums\FormSubmissionStatus; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use AdvisingApp\Form\Enums\FormSubmissionRequestDeliveryMethod; + +/** + * @mixin IdeHelperEventRegistrationFormSubmission + */ +class EventRegistrationFormSubmission extends Submission +{ + protected $fillable = [ + 'canceled_at', + 'form_id', + 'request_method', + 'request_note', + 'submitted_at', + ]; + + protected $casts = [ + 'submitted_at' => 'immutable_datetime', + 'canceled_at' => 'immutable_datetime', + 'request_method' => FormSubmissionRequestDeliveryMethod::class, + ]; + + public function submissible(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationForm::class, 'form_id'); + } + + public function requester(): BelongsTo + { + return $this->belongsTo(User::class, 'requester_id'); + } + + public function fields(): BelongsToMany + { + return $this->belongsToMany( + EventRegistrationFormField::class, + 'event_registration_form_field_submission', + 'submission_id', + 'field_id', + ) + ->withPivot(['id', 'response']); + } + + public function deliverRequest(): void + { + $this->request_method->deliver($this); + } + + public function scopeRequested(Builder $query): Builder + { + return $query->notSubmitted()->notCanceled(); + } + + public function scopeSubmitted(Builder $query): Builder + { + return $query->whereNotNull('submitted_at'); + } + + public function scopeCanceled(Builder $query): Builder + { + return $query->notSubmitted()->whereNotNull('canceled_at'); + } + + public function scopeNotSubmitted(Builder $query): Builder + { + return $query->whereNull('submitted_at'); + } + + public function scopeNotCanceled(Builder $query): Builder + { + return $query->whereNull('canceled_at'); + } + + public function getStatus(): FormSubmissionStatus + { + if ($this->submitted_at) { + return FormSubmissionStatus::Submitted; + } + + if ($this->canceled_at) { + return FormSubmissionStatus::Canceled; + } + + return FormSubmissionStatus::Requested; + } +} diff --git a/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php b/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php new file mode 100644 index 0000000000..6719016200 --- /dev/null +++ b/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php @@ -0,0 +1,70 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Form\Notifications; + +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Notification; +use Illuminate\Notifications\AnonymousNotifiable; +use AdvisingApp\Notification\Notifications\Messages\MailMessage; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; + +class AuthenticateEventRegistrationFormNotification extends Notification +{ + use Queueable; + + public function __construct( + public EventRegistrationFormAuthentication $authentication, + public int $code, + ) {} + + /** + * @return array + */ + public function via(object $notifiable): array + { + return ['mail']; + } + + public function toMail(AnonymousNotifiable $notifiable): MailMessage + { + return MailMessage::make() + ->subject("Your authentication code for {$this->authentication->submissible->event->title} registration") + ->line("Your code is: {$this->code}.") + ->line('You should type this code into the form to authenticate yourself.') + ->line('For security reasons, the code will expire in 24 hours, but you can always request another.'); + } +} diff --git a/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php b/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php index 4da3cd67f1..bc5e36b29c 100644 --- a/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php +++ b/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php @@ -44,10 +44,16 @@ use AdvisingApp\MeetingCenter\Jobs\SyncCalendars; use AdvisingApp\MeetingCenter\MeetingCenterPlugin; use AdvisingApp\MeetingCenter\Models\CalendarEvent; +use AdvisingApp\MeetingCenter\Models\EventAttendee; use Illuminate\Database\Eloquent\Relations\Relation; use AdvisingApp\Authorization\AuthorizationRoleRegistry; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; use AdvisingApp\Authorization\AuthorizationPermissionRegistry; use AdvisingApp\MeetingCenter\Observers\CalendarEventObserver; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; class MeetingCenterServiceProvider extends ServiceProvider { @@ -62,6 +68,12 @@ public function boot(): void 'calendar' => Calendar::class, 'calendar_event' => CalendarEvent::class, 'event' => Event::class, + 'event_attendee' => EventAttendee::class, + 'event_registration_form' => EventRegistrationForm::class, + 'event_registration_form_authentication' => EventRegistrationFormAuthentication::class, + 'event_registration_form_field' => EventRegistrationFormField::class, + 'event_registration_form_step' => EventRegistrationFormStep::class, + 'event_registration_form_submission' => EventRegistrationFormSubmission::class, ]); $this->callAfterResolving(Schedule::class, function (Schedule $schedule) { diff --git a/app-modules/survey/config/roles/web/survey_roles.php b/app-modules/survey/config/roles/web/survey_management.php similarity index 100% rename from app-modules/survey/config/roles/web/survey_roles.php rename to app-modules/survey/config/roles/web/survey_management.php From f63e8101d92db3c62ec77e5ca1bfe89391d8b9bb Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 17:57:07 -0500 Subject: [PATCH 026/152] Fix survey widget auth Signed-off-by: Kevin Ullyott --- .../src/Http/Controllers/SurveyWidgetController.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app-modules/survey/src/Http/Controllers/SurveyWidgetController.php b/app-modules/survey/src/Http/Controllers/SurveyWidgetController.php index 5c8a72a9ef..8a1c815907 100644 --- a/app-modules/survey/src/Http/Controllers/SurveyWidgetController.php +++ b/app-modules/survey/src/Http/Controllers/SurveyWidgetController.php @@ -53,7 +53,6 @@ use AdvisingApp\Form\Actions\GenerateFormKitSchema; use AdvisingApp\Survey\Models\SurveyAuthentication; use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; -use AdvisingApp\Application\Models\ApplicationAuthentication; use AdvisingApp\Form\Actions\ResolveSubmissionAuthorFromEmail; use AdvisingApp\Form\Notifications\AuthenticateFormNotification; use AdvisingApp\Form\Filament\Blocks\EducatableEmailFormFieldBlock; @@ -119,7 +118,7 @@ public function requestAuthentication(Request $request, ResolveSubmissionAuthorF ]); } - public function authenticate(Request $request, Survey $survey, ApplicationAuthentication $authentication): JsonResponse + public function authenticate(Request $request, Survey $survey, SurveyAuthentication $authentication): JsonResponse { if ($authentication->isExpired()) { return response()->json([ @@ -139,8 +138,8 @@ public function authenticate(Request $request, Survey $survey, ApplicationAuthen return response()->json([ 'submission_url' => URL::signedRoute('surveys.submit', [ - 'survey' => $authentication, - 'application' => $authentication->submissible, + 'authentication' => $authentication, + 'survey' => $authentication->submissible, ]), ]); } @@ -154,7 +153,7 @@ public function store( $authentication = $request->query('authentication'); if (filled($authentication)) { - $authentication = ApplicationAuthentication::findOrFail($authentication); + $authentication = SurveyAuthentication::findOrFail($authentication); } if ( From a6f253f3990319ac0c6e9daa996eb72060b7bdc3 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 18:07:51 -0500 Subject: [PATCH 027/152] Clear out all non-related code from Event Reg Widget Controller Signed-off-by: Kevin Ullyott --- .../EventRegistrationWidgetController.php | 74 +++++-------------- 1 file changed, 17 insertions(+), 57 deletions(-) diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index 39dd56722f..3bd79a987d 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -44,19 +44,16 @@ use Illuminate\Support\Facades\URL; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; -use AdvisingApp\Survey\Models\Survey; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Notification; use Symfony\Component\HttpFoundation\Response; -use AdvisingApp\Survey\Models\SurveySubmission; use AdvisingApp\Form\Actions\GenerateFormKitSchema; use AdvisingApp\MeetingCenter\Models\EventAttendee; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; -use AdvisingApp\Application\Models\ApplicationAuthentication; use AdvisingApp\Form\Actions\ResolveSubmissionAuthorFromEmail; -use AdvisingApp\Form\Filament\Blocks\EducatableEmailFormFieldBlock; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; use AdvisingApp\Form\Notifications\AuthenticateEventRegistrationFormNotification; @@ -122,7 +119,7 @@ public function requestAuthentication(Request $request, EventRegistrationForm $f ]); } - public function authenticate(Request $request, Survey $survey, ApplicationAuthentication $authentication): JsonResponse + public function authenticate(Request $request, EventRegistrationForm $form, EventRegistrationFormAuthentication $authentication): JsonResponse { if ($authentication->isExpired()) { return response()->json([ @@ -141,9 +138,9 @@ public function authenticate(Request $request, Survey $survey, ApplicationAuthen ]); return response()->json([ - 'submission_url' => URL::signedRoute('surveys.submit', [ - 'survey' => $authentication, - 'application' => $authentication->submissible, + 'submission_url' => URL::signedRoute('event-registration.submit', [ + 'authentication' => $authentication, + 'form' => $authentication->submissible, ]), ]); } @@ -152,16 +149,15 @@ public function store( Request $request, GenerateSubmissibleValidation $generateValidation, ResolveSubmissionAuthorFromEmail $resolveSubmissionAuthorFromEmail, - Survey $survey, + EventRegistrationForm $form, ): JsonResponse { $authentication = $request->query('authentication'); if (filled($authentication)) { - $authentication = ApplicationAuthentication::findOrFail($authentication); + $authentication = EventRegistrationFormAuthentication::findOrFail($authentication); } if ( - $survey->is_authenticated && ($authentication?->isExpired() ?? true) ) { abort(Response::HTTP_UNAUTHORIZED); @@ -169,7 +165,7 @@ public function store( $validator = Validator::make( $request->all(), - $generateValidation($survey) + $generateValidation($form) ); if ($validator->fails()) { @@ -181,74 +177,38 @@ public function store( ); } - /** @var SurveySubmission $submission */ - $submission = $survey->submissions()->make(); + /** @var EventRegistrationFormSubmission $submission */ + $submission = $form->submissions()->make(); - if ($authentication) { - $submission->author()->associate($authentication->author); + $submission->author()->associate($authentication->author); - $authentication->delete(); - } + $authentication->delete(); $submission->submitted_at = now(); + // TODO: Adjust the status of the EventAttendee to Attending or Not Attending based on the form submission. + $submission->save(); $data = $validator->validated(); unset($data['recaptcha-token']); - if ($survey->is_wizard) { - foreach ($survey->steps as $step) { - $stepFields = $step->fields()->pluck('type', 'id')->all(); - + if ($form->is_wizard) { + foreach ($form->steps as $step) { foreach ($data[$step->label] as $fieldId => $response) { $submission->fields()->attach( $fieldId, ['id' => Str::orderedUuid(), 'response' => $response], ); - - if ($submission->author) { - continue; - } - - if ($stepFields[$fieldId] !== EducatableEmailFormFieldBlock::type()) { - continue; - } - - $author = $resolveSubmissionAuthorFromEmail($response); - - if (! $author) { - continue; - } - - $submission->author()->associate($author); } } } else { - $surveyFields = $survey->fields()->pluck('type', 'id')->all(); - foreach ($data as $fieldId => $response) { $submission->fields()->attach( $fieldId, ['id' => Str::orderedUuid(), 'response' => $response], ); - - if ($submission->author) { - continue; - } - - if ($surveyFields[$fieldId] !== EducatableEmailFormFieldBlock::type()) { - continue; - } - - $author = $resolveSubmissionAuthorFromEmail($response); - - if (! $author) { - continue; - } - - $submission->author()->associate($author); } } @@ -256,7 +216,7 @@ public function store( return response()->json( [ - 'message' => 'Survey submitted successfully.', + 'message' => 'Event registration submitted successfully.', ] ); } From 7801f8774e06fb2c5996f1e24fb743e432467058 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 18:27:41 -0500 Subject: [PATCH 028/152] Setup EventRegistrationForm Controller and relations Signed-off-by: Kevin Ullyott --- .../Actions/GenerateSubmissibleEmbedCode.php | 10 +++ .../render-event-registration-form.blade.php | 42 +++++++++++++ app-modules/meeting-center/routes/api.php | 62 +++++++++++++++++++ app-modules/meeting-center/routes/web.php | 9 +++ .../Livewire/RenderEventRegistrationForm.php | 60 ++++++++++++++++++ 5 files changed, 183 insertions(+) create mode 100644 app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php create mode 100644 app-modules/meeting-center/routes/api.php create mode 100644 app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php diff --git a/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php b/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php index 41140906d9..ea28b94f01 100644 --- a/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php +++ b/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php @@ -42,6 +42,7 @@ use AdvisingApp\Survey\Models\Survey; use AdvisingApp\Form\Models\Submissible; use AdvisingApp\Application\Models\Application; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; class GenerateSubmissibleEmbedCode { @@ -75,6 +76,15 @@ public function handle(Submissible $submissible): string EOD; })(), + EventRegistrationForm::class => (function () use ($submissible) { + $scriptUrl = url('js/widgets/events/advising-app-event-registration-form-widget.js?'); + $formDefinitionUrl = URL::signedRoute('event-registration.define', ['form' => $submissible]); + + return << + + EOD; + })(), default => throw new Exception('Unsupported submissible type.'), }; } diff --git a/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php b/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php new file mode 100644 index 0000000000..26a5435918 --- /dev/null +++ b/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php @@ -0,0 +1,42 @@ +{{-- + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +--}} +@php + use AdvisingApp\Form\Actions\GenerateSubmissibleEmbedCode; +@endphp + +
+
+ {!! resolve(GenerateSubmissibleEmbedCode::class)->handle($this->eventRegistrationForm) !!} +
+
diff --git a/app-modules/meeting-center/routes/api.php b/app-modules/meeting-center/routes/api.php new file mode 100644 index 0000000000..13aa9a6000 --- /dev/null +++ b/app-modules/meeting-center/routes/api.php @@ -0,0 +1,62 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use AdvisingApp\Form\Http\Middleware\EnsureSubmissibleIsEmbeddableAndAuthorized; +use AdvisingApp\MeetingCenter\Http\Controllers\EventRegistrationWidgetController; + +Route::prefix('api') + ->middleware([ + 'api', + EnsureSubmissibleIsEmbeddableAndAuthorized::class . ':form', + ]) + ->group(function () { + Route::prefix('event-registration') + ->name('event-registration.') + ->group(function () { + Route::get('/{form}', [EventRegistrationWidgetController::class, 'view']) + ->middleware(['signed']) + ->name('define'); + Route::post('/{form}/authenticate/request', [EventRegistrationWidgetController::class, 'requestAuthentication']) + ->middleware(['signed']) + ->name('request-authentication'); + Route::post('/{form}/authenticate/{authentication}', [EventRegistrationWidgetController::class, 'authenticate']) + ->middleware(['signed']) + ->name('authenticate'); + Route::post('/{form}/submit', [EventRegistrationWidgetController::class, 'store']) + ->middleware(['signed']) + ->name('submit'); + }); + }); diff --git a/app-modules/meeting-center/routes/web.php b/app-modules/meeting-center/routes/web.php index 796a4317ab..a55eb2e6f2 100644 --- a/app-modules/meeting-center/routes/web.php +++ b/app-modules/meeting-center/routes/web.php @@ -35,6 +35,7 @@ */ use AdvisingApp\MeetingCenter\Enums\CalendarProvider; +use AdvisingApp\Survey\Livewire\RenderEventRegistrationForm; use AdvisingApp\MeetingCenter\Http\Controllers\GoogleCalendarController; use AdvisingApp\MeetingCenter\Http\Controllers\OutlookCalendarController; @@ -45,3 +46,11 @@ provider_routes(CalendarProvider::Google, GoogleCalendarController::class); provider_routes(CalendarProvider::Outlook, OutlookCalendarController::class); }); + +Route::middleware('web') + ->prefix('event-registration') + ->name('event-registration.') + ->group(function () { + Route::get('/{eventRegistrationForm}/respond', RenderEventRegistrationForm::class) + ->name('show'); + }); diff --git a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php new file mode 100644 index 0000000000..fbb4552603 --- /dev/null +++ b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php @@ -0,0 +1,60 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Survey\Livewire; + +use Livewire\Component; +use Illuminate\Contracts\View\View; +use Filament\Forms\Contracts\HasForms; +use Filament\Forms\Concerns\InteractsWithForms; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; + +class RenderEventRegistrationForm extends Component implements HasForms +{ + use InteractsWithForms; + + public bool $show = true; + + public EventRegistrationForm $eventRegistrationForm; + + public ?array $data = []; + + public function render(): View + { + return view('meeting-center::livewire.render-event-registration-form') + ->title("{$this->eventRegistrationForm->event->title} Registration"); + } +} From cdcdf628dde6e30f075b7f2e495747c48c2a9c02 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 18:37:26 -0500 Subject: [PATCH 029/152] Setup the event registration widget Signed-off-by: Kevin Ullyott --- package.json | 3 +- widgets/event-registration/postcss.config.js | 42 ++ widgets/event-registration/src/App.vue | 358 ++++++++++++++++++ .../event-registration/src/formkit.config.js | 47 +++ widgets/event-registration/src/widget.css | 38 ++ widgets/event-registration/src/widget.js | 62 +++ widgets/event-registration/tailwind.config.js | 39 ++ .../tailwind.config.preset.js | 69 ++++ widgets/event-registration/vite.config.js | 58 +++ 9 files changed, 715 insertions(+), 1 deletion(-) create mode 100644 widgets/event-registration/postcss.config.js create mode 100644 widgets/event-registration/src/App.vue create mode 100644 widgets/event-registration/src/formkit.config.js create mode 100644 widgets/event-registration/src/widget.css create mode 100644 widgets/event-registration/src/widget.js create mode 100644 widgets/event-registration/tailwind.config.js create mode 100644 widgets/event-registration/tailwind.config.preset.js create mode 100644 widgets/event-registration/vite.config.js diff --git a/package.json b/package.json index a189c50282..3b3beb6502 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,11 @@ "build:js-compile": "node ./bin/build.js", "build:filament": "php artisan filament:assets", "build:vite": "vite build", - "build": "npm run build:js-compile && npm run build:vite && npm run build:filament && npm run build:application && npm run build:form && npm run build:survey", "build:application": "(cd widgets/application && vite build)", "build:form": "(cd widgets/form && vite build)", "build:survey": "(cd widgets/survey && vite build)", + "build:event-registration": "(cd widgets/event-registration && vite build)", + "build": "npm run build:js-compile && npm run build:vite && npm run build:filament && npm run build:application && npm run build:form && npm run build:survey && npm run build:event-registration", "api-docs:generate": "export NODE_OPTIONS=--max_old_space_size=4096 && env-cmd spectaql spectaql.yml" }, "devDependencies": { diff --git a/widgets/event-registration/postcss.config.js b/widgets/event-registration/postcss.config.js new file mode 100644 index 0000000000..2f7f96d2ff --- /dev/null +++ b/widgets/event-registration/postcss.config.js @@ -0,0 +1,42 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +export default { + plugins: { + 'tailwindcss/nesting': {}, + tailwindcss: { + config: './tailwind.config.js', + }, + autoprefixer: {}, + }, +} diff --git a/widgets/event-registration/src/App.vue b/widgets/event-registration/src/App.vue new file mode 100644 index 0000000000..78579b05e8 --- /dev/null +++ b/widgets/event-registration/src/App.vue @@ -0,0 +1,358 @@ + + + + diff --git a/widgets/event-registration/src/formkit.config.js b/widgets/event-registration/src/formkit.config.js new file mode 100644 index 0000000000..26e2877b28 --- /dev/null +++ b/widgets/event-registration/src/formkit.config.js @@ -0,0 +1,47 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import { generateClasses } from '@formkit/themes'; +import { genesisIcons } from '@formkit/icons'; +import theme from '../../form/src/FormKit/theme'; +import inputs from '../../form/src/FormKit/Inputs/index'; + +export default { + icons: { + ...genesisIcons, + }, + inputs, + config: { + classes: generateClasses(theme), + }, +}; diff --git a/widgets/event-registration/src/widget.css b/widgets/event-registration/src/widget.css new file mode 100644 index 0000000000..e896335f42 --- /dev/null +++ b/widgets/event-registration/src/widget.css @@ -0,0 +1,38 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +@import '../../form/src/FormKit/index.css'; + +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/widgets/event-registration/src/widget.js b/widgets/event-registration/src/widget.js new file mode 100644 index 0000000000..53f8f4e47d --- /dev/null +++ b/widgets/event-registration/src/widget.js @@ -0,0 +1,62 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import { createApp, defineCustomElement, getCurrentInstance, h } from "vue"; +import "./widget.css"; +import App from "./App.vue"; +import { defaultConfig, plugin } from "@formkit/vue"; +import config from "./formkit.config.js"; +import VueSignaturePad from "vue-signature-pad"; + +customElements.define( + 'event-registration-embed', + defineCustomElement({ + setup(props) { + const app = createApp(); + + // install plugins + app.use(plugin, defaultConfig(config)); + + app.use(VueSignaturePad); + + app.config.devtools = true; + + const inst = getCurrentInstance(); + Object.assign(inst.appContext, app._context); + Object.assign(inst.provides, app._context.provides); + + return () => h(App, props); + }, + props: ['url'], + }), +); diff --git a/widgets/event-registration/tailwind.config.js b/widgets/event-registration/tailwind.config.js new file mode 100644 index 0000000000..9ab2129136 --- /dev/null +++ b/widgets/event-registration/tailwind.config.js @@ -0,0 +1,39 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import preset from './tailwind.config.preset.js'; + +export default { + presets: [preset], + content: ['./src/**/*.vue', './src/FormKit/theme.js'], +}; diff --git a/widgets/event-registration/tailwind.config.preset.js b/widgets/event-registration/tailwind.config.preset.js new file mode 100644 index 0000000000..f65aaf5496 --- /dev/null +++ b/widgets/event-registration/tailwind.config.preset.js @@ -0,0 +1,69 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import forms from '@tailwindcss/forms'; +import typography from '@tailwindcss/typography'; +import FormKitVariants from '@formkit/themes/tailwindcss'; + +export default { + theme: { + extend: { + colors: { + primary: { + 50: 'rgba(var(--primary-50), )', + 100: 'rgba(var(--primary-100), )', + 200: 'rgba(var(--primary-200), )', + 300: 'rgba(var(--primary-300), )', + 400: 'rgba(var(--primary-400), )', + 500: 'rgba(var(--primary-500), )', + 600: 'rgba(var(--primary-600), )', + 700: 'rgba(var(--primary-700), )', + 800: 'rgba(var(--primary-800), )', + 900: 'rgba(var(--primary-900), )', + 950: 'rgba(var(--primary-950), )', + }, + }, + borderRadius: { + sm: 'var(--rounding-sm)', + DEFAULT: 'var(--rounding)', + md: 'var(--rounding-md)', + lg: 'var(--rounding-lg)', + full: 'var(--rounding-sm)', + }, + fontFamily: { + signature: ['Satisfy', 'cursive'], + }, + }, + }, + plugins: [forms, typography, FormKitVariants], +} diff --git a/widgets/event-registration/vite.config.js b/widgets/event-registration/vite.config.js new file mode 100644 index 0000000000..72ee5f9760 --- /dev/null +++ b/widgets/event-registration/vite.config.js @@ -0,0 +1,58 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import { resolve } from "path"; +import { defineConfig } from "vite"; +import vue from "@vitejs/plugin-vue"; + +export default defineConfig({ + plugins: [vue()], + build: { + manifest: true, + lib: { + entry: resolve(__dirname, 'src/widget.js'), + name: 'AdvisingAppEventRegistrationFormWidget', + fileName: 'advising-app-event-registration-form-widget', + formats: ['es'], + }, + outDir: resolve(__dirname, '../../public/js/widgets/events'), + emptyOutDir: true, + sourcemap: true, + }, + resolve: { + alias: { + '@': resolve(__dirname, 'src'), + }, + }, + define: { 'process.env.NODE_ENV': '"production"' }, +}); From 6053e02aa5500826e7f160c7b18909c61d852750 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 19:01:41 -0500 Subject: [PATCH 030/152] Fix namespace Signed-off-by: Kevin Ullyott --- app-modules/meeting-center/routes/web.php | 2 +- .../meeting-center/src/Livewire/RenderEventRegistrationForm.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app-modules/meeting-center/routes/web.php b/app-modules/meeting-center/routes/web.php index a55eb2e6f2..d1b6d06442 100644 --- a/app-modules/meeting-center/routes/web.php +++ b/app-modules/meeting-center/routes/web.php @@ -35,7 +35,7 @@ */ use AdvisingApp\MeetingCenter\Enums\CalendarProvider; -use AdvisingApp\Survey\Livewire\RenderEventRegistrationForm; +use AdvisingApp\MeetingCenter\Livewire\RenderEventRegistrationForm; use AdvisingApp\MeetingCenter\Http\Controllers\GoogleCalendarController; use AdvisingApp\MeetingCenter\Http\Controllers\OutlookCalendarController; diff --git a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php index fbb4552603..60dc4d9cdf 100644 --- a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php +++ b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php @@ -34,7 +34,7 @@ */ -namespace AdvisingApp\Survey\Livewire; +namespace AdvisingApp\MeetingCenter\Livewire; use Livewire\Component; use Illuminate\Contracts\View\View; From e0c93d33af02ebd6424eb16253f556f2313fb1b8 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 19:44:35 -0500 Subject: [PATCH 031/152] Start adding the ability to add a Form to the Event edit page Signed-off-by: Kevin Ullyott --- .../EventResource/Pages/EditEvent.php | 186 +++++++++++ .../meeting-center/src/Models/Event.php | 6 + .../src/Models/EventRegistrationForm.php | 6 +- composer.json | 2 +- composer.lock | 288 ++++++++---------- 5 files changed, 323 insertions(+), 165 deletions(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index 7a1ac857ca..cda81e3d39 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -37,14 +37,33 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; use App\Models\User; +use Filament\Forms\Get; use Filament\Forms\Form; use Filament\Actions\ViewAction; use Filament\Actions\DeleteAction; +use Filament\Forms\Components\Grid; +use AdvisingApp\Form\Enums\Rounding; +use AdvisingApp\Form\Rules\IsDomain; +use App\Forms\Components\ColorSelect; +use Filament\Forms\Components\Select; +use Filament\Forms\Components\Toggle; +use Filament\Forms\Components\Section; +use FilamentTiptapEditor\TiptapEditor; +use Filament\Forms\Components\Fieldset; +use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TagsInput; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; +use AdvisingApp\MeetingCenter\Models\Event; +use FilamentTiptapEditor\Enums\TiptapOutput; use Filament\Forms\Components\DateTimePicker; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; +use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; class EditEvent extends EditRecord { @@ -75,9 +94,176 @@ public function form(Form $form): Form DateTimePicker::make('ends_at') ->timezone($user->timezone) ->required(), + Fieldset::make('Registration Form') + ->relationship('eventRegistrationForm') + ->schema([ + Grid::make() + ->schema([ + Toggle::make('embed_enabled') + ->label('Embed Enabled') + ->live() + ->helperText('If enabled, this form can be embedded on other websites.'), + TagsInput::make('allowed_domains') + ->label('Allowed Domains') + ->helperText('Only these domains will be allowed to embed this form.') + ->placeholder('example.com') + ->hidden(fn (Get $get) => ! $get('embed_enabled')) + ->disabled(fn (Get $get) => ! $get('embed_enabled')) + ->nestedRecursiveRules( + [ + 'string', + new IsDomain(), + ] + ), + ]) + ->columnSpanFull(), + Toggle::make('is_wizard') + ->label('Multi-step form') + ->live() + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), + Section::make('Fields') + ->schema([ + $this->fieldBuilder(), + ]) + ->hidden(fn (Get $get) => $get('is_wizard')) + ->disabled(fn (?EventRegistrationForm $record) => $record->submissions()->exists()), + Repeater::make('steps') + ->schema([ + TextInput::make('label') + ->required() + ->string() + ->maxLength(255) + ->autocomplete(false) + ->columnSpanFull() + ->lazy(), + $this->fieldBuilder(), + ]) + ->addActionLabel('New step') + ->itemLabel(fn (array $state): ?string => $state['label'] ?? null) + ->visible(fn (Get $get) => $get('is_wizard')) + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()) + ->relationship() + ->reorderable() + ->columnSpanFull(), + Section::make('Appearance') + ->schema([ + ColorSelect::make('primary_color'), + Select::make('rounding') + ->options(Rounding::class), + ]) + ->columns(), + ]), ]); } + public function fieldBuilder(): TiptapEditor + { + return TiptapEditor::make('content') + ->output(TiptapOutput::Json) + ->blocks(FormFieldBlockRegistry::get()) + ->tools(['bold', 'italic', 'small', '|', 'heading', 'bullet-list', 'ordered-list', 'hr', '|', 'link', 'grid', 'blocks']) + ->placeholder('Drag blocks here to build your form') + ->hiddenLabel() + ->saveRelationshipsUsing(function (TiptapEditor $component, EventRegistrationForm | EventRegistrationFormStep $record) { + if ($component->isDisabled()) { + return; + } + + $form = $record instanceof EventRegistrationForm ? $record : $record->submissible; + $formStep = $record instanceof EventRegistrationFormStep ? $record : null; + + EventRegistrationFormStep::query() + ->whereBelongsTo($form, 'submissible') + ->when($formStep, fn (EloquentBuilder $query) => $query->whereBelongsTo($formStep, 'step')) + ->delete(); + + $content = $component->decodeBlocksBeforeSave($component->getJSON(decoded: true)); + $content['content'] = $this->saveFieldsFromComponents( + $form, + $content['content'] ?? [], + $formStep, + ); + + $record->content = $content; + $record->save(); + }) + ->dehydrated(false) + ->columnSpanFull() + ->extraInputAttributes(['style' => 'min-height: 12rem;']); + } + + public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array + { + foreach ($components as $componentKey => $component) { + if (array_key_exists('content', $component)) { + $components[$componentKey]['content'] = $this->saveFieldsFromComponents($form, $component['content'], $eventRegistrationFormStep); + + continue; + } + + if ($component['type'] !== 'tiptapBlock') { + continue; + } + + $componentAttributes = $component['attrs'] ?? []; + + if (array_key_exists('id', $componentAttributes)) { + $id = $componentAttributes['id'] ?? null; + unset($componentAttributes['id']); + } + + if (array_key_exists('label', $componentAttributes['data'])) { + $label = $componentAttributes['data']['label'] ?? null; + unset($componentAttributes['data']['label']); + } + + if (array_key_exists('isRequired', $componentAttributes['data'])) { + $isRequired = $componentAttributes['data']['isRequired'] ?? null; + unset($componentAttributes['data']['isRequired']); + } + + /** @var EventRegistrationFormField $field */ + $field = $form->fields()->findOrNew($id ?? null); + $field->step()->associate($eventRegistrationFormStep); + $field->label = $label ?? $componentAttributes['type']; + $field->is_required = $isRequired ?? false; + $field->type = $componentAttributes['type']; + $field->config = $componentAttributes['data']; + $field->save(); + + $components[$componentKey]['attrs']['id'] = $field->id; + } + + return $components; + } + + protected function afterCreate(): void + { + $this->clearFormContentForWizard(); + } + + protected function afterSave(): void + { + $this->clearFormContentForWizard(); + } + + protected function clearFormContentForWizard(): void + { + /** @var Event $event */ + $event = $this->record; + + $form = $event->eventRegistrationForm; + + if ($form->is_wizard) { + $form->content = null; + $form->save(); + + return; + } + + $form->steps()->delete(); + } + protected function getHeaderActions(): array { return [ diff --git a/app-modules/meeting-center/src/Models/Event.php b/app-modules/meeting-center/src/Models/Event.php index 6484c5341e..e19a7706e9 100644 --- a/app-modules/meeting-center/src/Models/Event.php +++ b/app-modules/meeting-center/src/Models/Event.php @@ -37,6 +37,7 @@ namespace AdvisingApp\MeetingCenter\Models; use App\Models\BaseModel; +use Illuminate\Database\Eloquent\Relations\HasOne; /** * @mixin IdeHelperEvent @@ -56,4 +57,9 @@ class Event extends BaseModel 'starts_at' => 'datetime', 'ends_at' => 'datetime', ]; + + public function eventRegistrationForm(): HasOne + { + return $this->hasOne(EventRegistrationForm::class, 'event_id'); + } } diff --git a/app-modules/meeting-center/src/Models/EventRegistrationForm.php b/app-modules/meeting-center/src/Models/EventRegistrationForm.php index 672883ea58..e8ed9f9aa2 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationForm.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationForm.php @@ -74,16 +74,16 @@ public function event(): BelongsTo public function fields(): HasMany { - return $this->hasMany(EventRegistrationFormField::class); + return $this->hasMany(EventRegistrationFormField::class, 'form_id'); } public function steps(): HasMany { - return $this->hasMany(EventRegistrationFormStep::class); + return $this->hasMany(EventRegistrationFormStep::class, 'form_id'); } public function submissions(): HasMany { - return $this->hasMany(EventRegistrationFormSubmission::class); + return $this->hasMany(EventRegistrationFormSubmission::class, 'form_id'); } } diff --git a/composer.json b/composer.json index 9ac9e26dce..97e808d8fb 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "php": "8.2.*", "ext-gd": "*", "ext-pdo": "*", - "awcodes/filament-tiptap-editor": "^3.2.14", + "awcodes/filament-tiptap-editor": "^3.2.17", "aws/aws-php-sns-message-validator": "^1.8.0", "aws/aws-sdk-php": "^3.293", "barryvdh/laravel-debugbar": "^3.9", diff --git a/composer.lock b/composer.lock index 7f43c3aa26..2377067c69 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4135a59df44c5333303e7a1b6f1ff947", + "content-hash": "a7c988d45a8bf04ea377069a6dd7b23a", "packages": [ { "name": "amphp/amp", @@ -559,16 +559,16 @@ }, { "name": "awcodes/filament-tiptap-editor", - "version": "v3.2.18", + "version": "v3.2.17", "source": { "type": "git", "url": "https://github.com/awcodes/filament-tiptap-editor.git", - "reference": "7de016e723ba62908f979a39204955e1801b0967" + "reference": "0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/7de016e723ba62908f979a39204955e1801b0967", - "reference": "7de016e723ba62908f979a39204955e1801b0967", + "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f", + "reference": "0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f", "shasum": "" }, "require": { @@ -630,7 +630,7 @@ ], "support": { "issues": "https://github.com/awcodes/filament-tiptap-editor/issues", - "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.18" + "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.17" }, "funding": [ { @@ -638,7 +638,7 @@ "type": "github" } ], - "time": "2023-12-28T20:05:06+00:00" + "time": "2023-12-27T19:10:56+00:00" }, { "name": "aws/aws-crt-php", @@ -755,16 +755,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.295.3", + "version": "3.294.5", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "3346f60c6c5075453f90f703693f764dad76a3a8" + "reference": "2e34d45e970c77775e4c298e08732d64b647c41c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3346f60c6c5075453f90f703693f764dad76a3a8", - "reference": "3346f60c6c5075453f90f703693f764dad76a3a8", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2e34d45e970c77775e4c298e08732d64b647c41c", + "reference": "2e34d45e970c77775e4c298e08732d64b647c41c", "shasum": "" }, "require": { @@ -844,9 +844,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.295.3" + "source": "https://github.com/aws/aws-sdk-php/tree/3.294.5" }, - "time": "2023-12-28T19:32:33+00:00" + "time": "2023-12-21T19:10:21+00:00" }, { "name": "barryvdh/laravel-debugbar", @@ -2379,41 +2379,6 @@ "relative": true } }, - { - "name": "canyon-gbs/inventory-management", - "version": "1.0", - "dist": { - "type": "path", - "url": "app-modules/inventory-management", - "reference": "16210c789f3a6d5a4b14ce0db3a17f5cdc4f6e48" - }, - "require": { - "filament/filament": "^3.0.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "AdvisingApp\\InventoryManagement\\Providers\\InventoryManagementServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "AdvisingApp\\InventoryManagement\\": "src/", - "AdvisingApp\\InventoryManagement\\Tests\\": "tests/", - "AdvisingApp\\InventoryManagement\\Database\\Factories\\": "database/factories/", - "AdvisingApp\\InventoryManagement\\Database\\Seeders\\": "database/seeders/" - } - }, - "license": [ - "proprietary" - ], - "transport-options": { - "symlink": true, - "relative": true - } - }, { "name": "carbonphp/carbon-doctrine-types", "version": "2.1.0", @@ -4106,16 +4071,16 @@ }, { "name": "filament/actions", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203" + "reference": "be3a8c110aa69f3f4856816eefd477b600bc06e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/8f2a3df7c607a24c2433a3a71cb27b20a8dea203", - "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/be3a8c110aa69f3f4856816eefd477b600bc06e2", + "reference": "be3a8c110aa69f3f4856816eefd477b600bc06e2", "shasum": "" }, "require": { @@ -4153,20 +4118,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:29+00:00" + "time": "2023-12-21T12:38:03+00:00" }, { "name": "filament/filament", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "ae12dc49094560188a4289778a54773045880e44" + "reference": "e1aa070483c2eaa5bb92ce8d959779a9558fe022" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/ae12dc49094560188a4289778a54773045880e44", - "reference": "ae12dc49094560188a4289778a54773045880e44", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/e1aa070483c2eaa5bb92ce8d959779a9558fe022", + "reference": "e1aa070483c2eaa5bb92ce8d959779a9558fe022", "shasum": "" }, "require": { @@ -4218,20 +4183,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:35+00:00" + "time": "2023-12-22T14:36:15+00:00" }, { "name": "filament/forms", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506" + "reference": "673689bd958797b05127fe9956eafeed555b91bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/26e177a4b3a8ef7b8326d992bb5073f02220a506", - "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/673689bd958797b05127fe9956eafeed555b91bd", + "reference": "673689bd958797b05127fe9956eafeed555b91bd", "shasum": "" }, "require": { @@ -4274,20 +4239,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:30+00:00" + "time": "2023-12-22T14:36:00+00:00" }, { "name": "filament/infolists", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", - "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3" + "reference": "9207c2b83ba9c8dcbcac9a930e93ce87f381d780" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/infolists/zipball/66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", - "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", + "url": "https://api.github.com/repos/filamentphp/infolists/zipball/9207c2b83ba9c8dcbcac9a930e93ce87f381d780", + "reference": "9207c2b83ba9c8dcbcac9a930e93ce87f381d780", "shasum": "" }, "require": { @@ -4325,20 +4290,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-26T22:39:20+00:00" + "time": "2023-12-22T14:36:00+00:00" }, { "name": "filament/notifications", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", - "reference": "4f5634f9df312050efa3a035c543add6cec0e3a2" + "reference": "5b9255c0793751534461cace12febdc0d4cc05bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/notifications/zipball/4f5634f9df312050efa3a035c543add6cec0e3a2", - "reference": "4f5634f9df312050efa3a035c543add6cec0e3a2", + "url": "https://api.github.com/repos/filamentphp/notifications/zipball/5b9255c0793751534461cace12febdc0d4cc05bb", + "reference": "5b9255c0793751534461cace12febdc0d4cc05bb", "shasum": "" }, "require": { @@ -4377,11 +4342,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:27+00:00" + "time": "2023-12-17T22:25:42+00:00" }, { "name": "filament/spatie-laravel-media-library-plugin", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-media-library-plugin.git", @@ -4418,16 +4383,16 @@ }, { "name": "filament/spatie-laravel-settings-plugin", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-settings-plugin.git", - "reference": "d26f397a845934462d511432ba88363f63a7e203" + "reference": "7119f3f714dfa0ce098cd90aa2a741147a5508f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/spatie-laravel-settings-plugin/zipball/d26f397a845934462d511432ba88363f63a7e203", - "reference": "d26f397a845934462d511432ba88363f63a7e203", + "url": "https://api.github.com/repos/filamentphp/spatie-laravel-settings-plugin/zipball/7119f3f714dfa0ce098cd90aa2a741147a5508f6", + "reference": "7119f3f714dfa0ce098cd90aa2a741147a5508f6", "shasum": "" }, "require": { @@ -4461,20 +4426,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-26T22:39:37+00:00" + "time": "2023-12-19T13:24:28+00:00" }, { "name": "filament/support", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "97792dad038a87b7a6bfe465c4f1913252c99017" + "reference": "f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/97792dad038a87b7a6bfe465c4f1913252c99017", - "reference": "97792dad038a87b7a6bfe465c4f1913252c99017", + "url": "https://api.github.com/repos/filamentphp/support/zipball/f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd", + "reference": "f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd", "shasum": "" }, "require": { @@ -4518,20 +4483,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-24T21:16:58+00:00" + "time": "2023-12-22T14:36:21+00:00" }, { "name": "filament/tables", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118" + "reference": "3391bd1015bdde8e454d0a6391952dc131fb8dad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/e0701467097f6a82b235ad9f31e3c30ae1035118", - "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/3391bd1015bdde8e454d0a6391952dc131fb8dad", + "reference": "3391bd1015bdde8e454d0a6391952dc131fb8dad", "shasum": "" }, "require": { @@ -4571,20 +4536,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T17:31:59+00:00" + "time": "2023-12-22T14:36:23+00:00" }, { "name": "filament/widgets", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd" + "reference": "290184b9dfb99436df94a9a0b8511b21811d9e64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", - "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/290184b9dfb99436df94a9a0b8511b21811d9e64", + "reference": "290184b9dfb99436df94a9a0b8511b21811d9e64", "shasum": "" }, "require": { @@ -4615,7 +4580,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T17:31:57+00:00" + "time": "2023-12-17T22:26:03+00:00" }, { "name": "firebase/php-jwt", @@ -5189,16 +5154,16 @@ }, { "name": "google/apiclient-services", - "version": "v0.329.0", + "version": "v0.328.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "3216fd1b6ba33c5f6658c3581e9723ff21d9acb7" + "reference": "211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/3216fd1b6ba33c5f6658c3581e9723ff21d9acb7", - "reference": "3216fd1b6ba33c5f6658c3581e9723ff21d9acb7", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d", + "reference": "211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d", "shasum": "" }, "require": { @@ -5227,9 +5192,9 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.329.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.328.0" }, - "time": "2023-12-24T01:02:15+00:00" + "time": "2023-12-18T01:00:18+00:00" }, { "name": "google/auth", @@ -6217,16 +6182,16 @@ }, { "name": "laravel/framework", - "version": "v10.39.0", + "version": "v10.38.2", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "114926b07bfb5fbf2545c03aa2ce5c8c37be650c" + "reference": "43da808391da3540d44a8dfeb4e46da4ad8f5723" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/114926b07bfb5fbf2545c03aa2ce5c8c37be650c", - "reference": "114926b07bfb5fbf2545c03aa2ce5c8c37be650c", + "url": "https://api.github.com/repos/laravel/framework/zipball/43da808391da3540d44a8dfeb4e46da4ad8f5723", + "reference": "43da808391da3540d44a8dfeb4e46da4ad8f5723", "shasum": "" }, "require": { @@ -6329,7 +6294,7 @@ "league/flysystem-sftp-v3": "^3.0", "mockery/mockery": "^1.5.1", "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^8.18", + "orchestra/testbench-core": "^8.15.1", "pda/pheanstalk": "^4.0", "phpstan/phpstan": "^1.4.7", "phpunit/phpunit": "^10.0.7", @@ -6418,20 +6383,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-12-27T14:26:28+00:00" + "time": "2023-12-22T14:39:10+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.14", + "version": "v0.1.13", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "2219fa9c4b944add1e825c3bdb8ecae8bc503bc6" + "reference": "e1379d8ead15edd6cc4369c22274345982edc95a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/2219fa9c4b944add1e825c3bdb8ecae8bc503bc6", - "reference": "2219fa9c4b944add1e825c3bdb8ecae8bc503bc6", + "url": "https://api.github.com/repos/laravel/prompts/zipball/e1379d8ead15edd6cc4369c22274345982edc95a", + "reference": "e1379d8ead15edd6cc4369c22274345982edc95a", "shasum": "" }, "require": { @@ -6447,7 +6412,7 @@ "require-dev": { "mockery/mockery": "^1.5", "pestphp/pest": "^2.3", - "phpstan/phpstan": "^1.11", + "phpstan/phpstan": "^1.10", "phpstan/phpstan-mockery": "^1.1" }, "suggest": { @@ -6473,22 +6438,22 @@ ], "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.14" + "source": "https://github.com/laravel/prompts/tree/v0.1.13" }, - "time": "2023-12-27T04:18:09+00:00" + "time": "2023-10-27T13:53:59+00:00" }, { "name": "laravel/sanctum", - "version": "v3.3.3", + "version": "v3.3.2", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5" + "reference": "e1a272893bec13cf135627f7e156030b3afe1e60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/8c104366459739f3ada0e994bcd3e6fd681ce3d5", - "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/e1a272893bec13cf135627f7e156030b3afe1e60", + "reference": "e1a272893bec13cf135627f7e156030b3afe1e60", "shasum": "" }, "require": { @@ -6541,7 +6506,7 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2023-12-19T18:44:48+00:00" + "time": "2023-11-03T13:42:14+00:00" }, { "name": "laravel/scout", @@ -12949,16 +12914,16 @@ }, { "name": "spatie/temporary-directory", - "version": "2.2.1", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/spatie/temporary-directory.git", - "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a" + "reference": "efc258c9f4da28f0c7661765b8393e4ccee3d19c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", - "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/efc258c9f4da28f0c7661765b8393e4ccee3d19c", + "reference": "efc258c9f4da28f0c7661765b8393e4ccee3d19c", "shasum": "" }, "require": { @@ -12994,7 +12959,7 @@ ], "support": { "issues": "https://github.com/spatie/temporary-directory/issues", - "source": "https://github.com/spatie/temporary-directory/tree/2.2.1" + "source": "https://github.com/spatie/temporary-directory/tree/2.2.0" }, "funding": [ { @@ -13006,7 +12971,7 @@ "type": "github" } ], - "time": "2023-12-25T11:46:58+00:00" + "time": "2023-09-25T07:13:36+00:00" }, { "name": "sqids/sqids", @@ -15521,21 +15486,21 @@ }, { "name": "symfony/service-contracts", - "version": "v3.4.1", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "psr/container": "^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -15583,7 +15548,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" }, "funding": [ { @@ -15599,7 +15564,7 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2023-07-30T20:28:31+00:00" }, { "name": "symfony/string", @@ -15784,16 +15749,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v3.4.1", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "06450585bf65e978026bda220cdebca3f867fde7" + "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", - "reference": "06450585bf65e978026bda220cdebca3f867fde7", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", "shasum": "" }, "require": { @@ -15842,7 +15807,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" }, "funding": [ { @@ -15858,7 +15823,7 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2023-07-25T15:08:44+00:00" }, { "name": "symfony/uid", @@ -17183,16 +17148,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.43.0", + "version": "v3.41.1", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "39b5632c39ca9deb4eb7e670ba96fcf5c3a72e3c" + "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/39b5632c39ca9deb4eb7e670ba96fcf5c3a72e3c", - "reference": "39b5632c39ca9deb4eb7e670ba96fcf5c3a72e3c", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8b6ae8dcbaf23f09680643ab832a4a3a260265f6", + "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6", "shasum": "" }, "require": { @@ -17222,7 +17187,8 @@ "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", - "phpunit/phpunit": "^9.6 || ^10.5.5", + "phpunit/phpunit": "^9.6", + "symfony/phpunit-bridge": "^6.3.8 || ^7.0", "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { @@ -17261,7 +17227,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.43.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.41.1" }, "funding": [ { @@ -17269,7 +17235,7 @@ "type": "github" } ], - "time": "2023-12-28T17:36:39+00:00" + "time": "2023-12-10T19:59:27+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -17787,36 +17753,36 @@ }, { "name": "pestphp/pest", - "version": "v2.30.0", + "version": "v2.28.1", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "97dc32f9d24b84dd071d9e89438a19e43c833f6f" + "reference": "9ee41910201ef8fc5f5b6d1390e5ec4558222927" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/97dc32f9d24b84dd071d9e89438a19e43c833f6f", - "reference": "97dc32f9d24b84dd071d9e89438a19e43c833f6f", + "url": "https://api.github.com/repos/pestphp/pest/zipball/9ee41910201ef8fc5f5b6d1390e5ec4558222927", + "reference": "9ee41910201ef8fc5f5b6d1390e5ec4558222927", "shasum": "" }, "require": { "brianium/paratest": "^7.3.1", - "nunomaduro/collision": "^7.10.0|^8.0.1", + "nunomaduro/collision": "^7.10.0|^8.0.0", "nunomaduro/termwind": "^1.15.1|^2.0.0", "pestphp/pest-plugin": "^2.1.1", "pestphp/pest-plugin-arch": "^2.5.0", "php": "^8.1.0", - "phpunit/phpunit": "^10.5.5" + "phpunit/phpunit": "^10.5.3" }, "conflict": { - "phpunit/phpunit": ">10.5.5", + "phpunit/phpunit": ">10.5.3", "sebastian/exporter": "<5.1.0", "webmozart/assert": "<1.11.0" }, "require-dev": { "pestphp/pest-dev-tools": "^2.16.0", - "pestphp/pest-plugin-type-coverage": "^2.6.0", - "symfony/process": "^6.4.0|^7.0.0" + "pestphp/pest-plugin-type-coverage": "^2.5.0", + "symfony/process": "^6.4.0|^7.0.1" }, "bin": [ "bin/pest" @@ -17879,7 +17845,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v2.30.0" + "source": "https://github.com/pestphp/pest/tree/v2.28.1" }, "funding": [ { @@ -17891,7 +17857,7 @@ "type": "github" } ], - "time": "2023-12-28T10:36:40+00:00" + "time": "2023-12-15T11:42:34+00:00" }, { "name": "pestphp/pest-plugin", @@ -18874,16 +18840,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.5", + "version": "10.5.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856" + "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ed21115d505b4b4f7dc7b5651464e19a2c7f7856", - "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6fce887c71076a73f32fd3e0774a6833fc5c7f19", + "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19", "shasum": "" }, "require": { @@ -18955,7 +18921,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.3" }, "funding": [ { @@ -18971,7 +18937,7 @@ "type": "tidelift" } ], - "time": "2023-12-27T15:13:52+00:00" + "time": "2023-12-13T07:25:23+00:00" }, { "name": "pimple/pimple", From 6e1a19a11b94658c4d28cefb77edbdc0efca8e28 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 20:19:33 -0500 Subject: [PATCH 032/152] Make null safe Signed-off-by: Kevin Ullyott --- .../src/Filament/Resources/EventResource/Pages/EditEvent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index cda81e3d39..11ca44ef15 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -126,7 +126,7 @@ public function form(Form $form): Form $this->fieldBuilder(), ]) ->hidden(fn (Get $get) => $get('is_wizard')) - ->disabled(fn (?EventRegistrationForm $record) => $record->submissions()->exists()), + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), Repeater::make('steps') ->schema([ TextInput::make('label') From 164cafe79398e939534f0775be4f21537fc18a29 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 20:25:48 -0500 Subject: [PATCH 033/152] Fix double hydration issue Signed-off-by: Kevin Ullyott --- .../EventResource/Pages/EditEvent.php | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index 11ca44ef15..f0c0e8a8f9 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -69,6 +69,8 @@ class EditEvent extends EditRecord { protected static string $resource = EventResource::class; + protected bool $contentHydrated = false; + public function form(Form $form): Form { /** @var User $user */ @@ -189,7 +191,26 @@ public function fieldBuilder(): TiptapEditor }) ->dehydrated(false) ->columnSpanFull() - ->extraInputAttributes(['style' => 'min-height: 12rem;']); + ->extraInputAttributes(['style' => 'min-height: 12rem;']) + ->afterStateHydrated(function (TiptapEditor $component, string | array | null $state): void { + // TODO: This is a temporary fix until we can figure out whey this gets hydrated twice. + + if (! $state || $this->contentHydrated) { + return; + } + + if (! is_array($state)) { + $state = tiptap_converter()->asJSON($state, decoded: true); + } + + ray('here2'); + + $state = $component->renderBlockPreviews($state, $component); + + $component->state($state); + + $this->contentHydrated = true; + }); } public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array From b1caf48bb23ec3f17e65e55a7b8b4a16f58fb525 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 22:48:40 -0500 Subject: [PATCH 034/152] FIx some bugs with submissions Signed-off-by: Kevin Ullyott --- .../Actions/GenerateSubmissibleEmbedCode.php | 3 +- app-modules/form/src/Models/Submission.php | 2 +- .../render-event-registration-form.blade.php | 2 +- app-modules/meeting-center/routes/api.php | 12 +-- app-modules/meeting-center/routes/web.php | 2 +- .../EventResource/Pages/ViewEvent.php | 6 ++ .../EventRegistrationWidgetController.php | 30 +++++--- ...istrationFormIsEmbeddableAndAuthorized.php | 75 +++++++++++++++++++ .../Livewire/RenderEventRegistrationForm.php | 6 +- .../EventRegistrationFormSubmission.php | 5 ++ ...icateEventRegistrationFormNotification.php | 2 +- app/Http/Middleware/VerifyCsrfToken.php | 1 + 12 files changed, 121 insertions(+), 25 deletions(-) create mode 100644 app-modules/meeting-center/src/Http/Middleware/EnsureEventRegistrationFormIsEmbeddableAndAuthorized.php diff --git a/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php b/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php index ea28b94f01..339d06623d 100644 --- a/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php +++ b/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php @@ -77,8 +77,9 @@ public function handle(Submissible $submissible): string EOD; })(), EventRegistrationForm::class => (function () use ($submissible) { + /** @var EventRegistrationForm $submissible */ $scriptUrl = url('js/widgets/events/advising-app-event-registration-form-widget.js?'); - $formDefinitionUrl = URL::signedRoute('event-registration.define', ['form' => $submissible]); + $formDefinitionUrl = URL::signedRoute('event-registration.define', ['event' => $submissible->event]); return << diff --git a/app-modules/form/src/Models/Submission.php b/app-modules/form/src/Models/Submission.php index aa948d8ca1..0816268c2e 100644 --- a/app-modules/form/src/Models/Submission.php +++ b/app-modules/form/src/Models/Submission.php @@ -55,7 +55,7 @@ abstract public function submissible(): BelongsTo; abstract public function fields(): BelongsToMany; - public function author(): MorphTo + public function author(): MorphTo|BelongsTo { return $this ->morphTo('author'); diff --git a/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php b/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php index 26a5435918..e6e327ca9d 100644 --- a/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php +++ b/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php @@ -37,6 +37,6 @@
- {!! resolve(GenerateSubmissibleEmbedCode::class)->handle($this->eventRegistrationForm) !!} + {!! resolve(GenerateSubmissibleEmbedCode::class)->handle($this->event->eventRegistrationForm) !!}
diff --git a/app-modules/meeting-center/routes/api.php b/app-modules/meeting-center/routes/api.php index 13aa9a6000..1bb564f34d 100644 --- a/app-modules/meeting-center/routes/api.php +++ b/app-modules/meeting-center/routes/api.php @@ -34,28 +34,28 @@ */ -use AdvisingApp\Form\Http\Middleware\EnsureSubmissibleIsEmbeddableAndAuthorized; use AdvisingApp\MeetingCenter\Http\Controllers\EventRegistrationWidgetController; +use AdvisingApp\MeetingCenter\Http\Middleware\EnsureEventRegistrationFormIsEmbeddableAndAuthorized; Route::prefix('api') ->middleware([ 'api', - EnsureSubmissibleIsEmbeddableAndAuthorized::class . ':form', + EnsureEventRegistrationFormIsEmbeddableAndAuthorized::class . ':event', ]) ->group(function () { Route::prefix('event-registration') ->name('event-registration.') ->group(function () { - Route::get('/{form}', [EventRegistrationWidgetController::class, 'view']) + Route::get('/{event}', [EventRegistrationWidgetController::class, 'view']) ->middleware(['signed']) ->name('define'); - Route::post('/{form}/authenticate/request', [EventRegistrationWidgetController::class, 'requestAuthentication']) + Route::post('/{event}/authenticate/request', [EventRegistrationWidgetController::class, 'requestAuthentication']) ->middleware(['signed']) ->name('request-authentication'); - Route::post('/{form}/authenticate/{authentication}', [EventRegistrationWidgetController::class, 'authenticate']) + Route::post('/{event}/authenticate/{authentication}', [EventRegistrationWidgetController::class, 'authenticate']) ->middleware(['signed']) ->name('authenticate'); - Route::post('/{form}/submit', [EventRegistrationWidgetController::class, 'store']) + Route::post('/{event}/submit', [EventRegistrationWidgetController::class, 'store']) ->middleware(['signed']) ->name('submit'); }); diff --git a/app-modules/meeting-center/routes/web.php b/app-modules/meeting-center/routes/web.php index d1b6d06442..b5951e3f04 100644 --- a/app-modules/meeting-center/routes/web.php +++ b/app-modules/meeting-center/routes/web.php @@ -51,6 +51,6 @@ ->prefix('event-registration') ->name('event-registration.') ->group(function () { - Route::get('/{eventRegistrationForm}/respond', RenderEventRegistrationForm::class) + Route::get('/{event}/respond', RenderEventRegistrationForm::class) ->name('show'); }); diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ViewEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ViewEvent.php index 06d58a2b7f..be813c72a9 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ViewEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ViewEvent.php @@ -36,11 +36,13 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; +use Filament\Actions\Action; use Filament\Actions\EditAction; use Filament\Infolists\Infolist; use Filament\Actions\DeleteAction; use Filament\Resources\Pages\ViewRecord; use Filament\Infolists\Components\Section; +use AdvisingApp\MeetingCenter\Models\Event; use Filament\Infolists\Components\TextEntry; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; @@ -68,6 +70,10 @@ public function infolist(Infolist $infolist): Infolist protected function getHeaderActions(): array { return [ + Action::make('view') + ->url(fn (Event $event) => route('event-registration.show', ['event' => $event])) + ->icon('heroicon-m-arrow-top-right-on-square') + ->openUrlInNewTab(), EditAction::make(), DeleteAction::make(), ]; diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index 3bd79a987d..d542a26ad2 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -45,30 +45,33 @@ use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; +use AdvisingApp\MeetingCenter\Models\Event; use Illuminate\Support\Facades\Notification; use Symfony\Component\HttpFoundation\Response; use AdvisingApp\Form\Actions\GenerateFormKitSchema; use AdvisingApp\MeetingCenter\Models\EventAttendee; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; -use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; -use AdvisingApp\Form\Actions\ResolveSubmissionAuthorFromEmail; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; -use AdvisingApp\Form\Notifications\AuthenticateEventRegistrationFormNotification; +use AdvisingApp\MeetingCenter\Notifications\AuthenticateEventRegistrationFormNotification; class EventRegistrationWidgetController extends Controller { - public function view(GenerateFormKitSchema $generateSchema, EventRegistrationForm $form): JsonResponse + public function view(GenerateFormKitSchema $generateSchema, Event $event): JsonResponse { + $form = $event->eventRegistrationForm; + + ray($event, $form); + return response()->json( [ 'name' => $form->event->title, 'description' => $form->event->description, // TODO: Maybe get rid of this? It would never not be authenticated. 'is_authenticated' => true, - 'authentication_url' => URL::signedRoute('event-registration.request-authentication', ['form' => $form]), + 'authentication_url' => URL::signedRoute('event-registration.request-authentication', ['event' => $event]), 'recaptcha_enabled' => $form->recaptcha_enabled, ...($form->recaptcha_enabled ? [ 'recaptcha_site_key' => app(GoogleRecaptchaSettings::class)->site_key, @@ -80,8 +83,10 @@ public function view(GenerateFormKitSchema $generateSchema, EventRegistrationFor ); } - public function requestAuthentication(Request $request, EventRegistrationForm $form): JsonResponse + public function requestAuthentication(Request $request, Event $event): JsonResponse { + $form = $event->eventRegistrationForm; + $data = $request->validate([ 'email' => ['required', 'email'], ]); @@ -113,13 +118,13 @@ public function requestAuthentication(Request $request, EventRegistrationForm $f return response()->json([ 'message' => "We've sent an authentication code to {$attendee->email}.", 'authentication_url' => URL::signedRoute('event-registration.authenticate', [ - 'form' => $form, + 'event' => $event, 'authentication' => $authentication, ]), ]); } - public function authenticate(Request $request, EventRegistrationForm $form, EventRegistrationFormAuthentication $authentication): JsonResponse + public function authenticate(Request $request, Event $event, EventRegistrationFormAuthentication $authentication): JsonResponse { if ($authentication->isExpired()) { return response()->json([ @@ -140,7 +145,7 @@ public function authenticate(Request $request, EventRegistrationForm $form, Even return response()->json([ 'submission_url' => URL::signedRoute('event-registration.submit', [ 'authentication' => $authentication, - 'form' => $authentication->submissible, + 'event' => $authentication->submissible->event, ]), ]); } @@ -148,9 +153,10 @@ public function authenticate(Request $request, EventRegistrationForm $form, Even public function store( Request $request, GenerateSubmissibleValidation $generateValidation, - ResolveSubmissionAuthorFromEmail $resolveSubmissionAuthorFromEmail, - EventRegistrationForm $form, + Event $event, ): JsonResponse { + $form = $event->eventRegistrationForm; + $authentication = $request->query('authentication'); if (filled($authentication)) { @@ -168,6 +174,8 @@ public function store( $generateValidation($form) ); + ray($validator->errors()); + if ($validator->fails()) { return response()->json( [ diff --git a/app-modules/meeting-center/src/Http/Middleware/EnsureEventRegistrationFormIsEmbeddableAndAuthorized.php b/app-modules/meeting-center/src/Http/Middleware/EnsureEventRegistrationFormIsEmbeddableAndAuthorized.php new file mode 100644 index 0000000000..5d041e18ae --- /dev/null +++ b/app-modules/meeting-center/src/Http/Middleware/EnsureEventRegistrationFormIsEmbeddableAndAuthorized.php @@ -0,0 +1,75 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Http\Middleware; + +use Closure; +use Illuminate\Http\Request; +use AdvisingApp\MeetingCenter\Models\Event; +use Symfony\Component\HttpFoundation\Response; + +class EnsureEventRegistrationFormIsEmbeddableAndAuthorized +{ + public function handle(Request $request, Closure $next, string $binding): Response + { + /** @var Event $event */ + $event = $request->route($binding); + + $submissible = $event->eventRegistrationForm; + + $referer = $request->headers->get('referer'); + + if (! $referer) { + return response()->json(['error' => 'Missing referer header.'], 400); + } + + $referer = parse_url($referer)['host']; + + if ($referer != parse_url(config('app.url'))['host']) { + if (! $submissible->embed_enabled) { + return response()->json(['error' => 'Embedding is not enabled for this form.'], 403); + } + + $allowedDomains = collect($submissible->allowed_domains ?? []); + + if (! $allowedDomains->contains($referer)) { + return response()->json(['error' => 'Referer not allowed. Domain must be added to allowed domains list'], 403); + } + } + + return $next($request); + } +} diff --git a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php index 60dc4d9cdf..5a77647953 100644 --- a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php +++ b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php @@ -39,8 +39,8 @@ use Livewire\Component; use Illuminate\Contracts\View\View; use Filament\Forms\Contracts\HasForms; +use AdvisingApp\MeetingCenter\Models\Event; use Filament\Forms\Concerns\InteractsWithForms; -use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; class RenderEventRegistrationForm extends Component implements HasForms { @@ -48,13 +48,13 @@ class RenderEventRegistrationForm extends Component implements HasForms public bool $show = true; - public EventRegistrationForm $eventRegistrationForm; + public Event $event; public ?array $data = []; public function render(): View { return view('meeting-center::livewire.render-event-registration-form') - ->title("{$this->eventRegistrationForm->event->title} Registration"); + ->title("{$this->event->title} Registration"); } } diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php index 4a1392f1ae..35fdd58213 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php @@ -85,6 +85,11 @@ public function fields(): BelongsToMany ->withPivot(['id', 'response']); } + public function author(): BelongsTo + { + return $this->belongsTo(EventAttendee::class, 'event_attendee_id'); + } + public function deliverRequest(): void { $this->request_method->deliver($this); diff --git a/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php b/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php index 6719016200..09efa9ae1b 100644 --- a/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php +++ b/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php @@ -34,7 +34,7 @@ */ -namespace AdvisingApp\Form\Notifications; +namespace AdvisingApp\MeetingCenter\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 88dddf1747..660c731b42 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -49,6 +49,7 @@ class VerifyCsrfToken extends Middleware '/api/forms/*', '/api/applications/*', '/api/surveys/*', + '/api/event-registration/*', '/graphql/*', ]; } From 2e695d4655c20e30c37fc1f384d124b759357730 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 09:45:12 -0500 Subject: [PATCH 035/152] Fix relationship saving Signed-off-by: Kevin Ullyott --- .../EventResource/Pages/EditEvent.php | 26 ++++++++++++++++--- .../src/Models/EventRegistrationForm.php | 3 +++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index f0c0e8a8f9..72eda35866 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -52,6 +52,7 @@ use Filament\Forms\Components\Fieldset; use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\Component; use Filament\Forms\Components\TagsInput; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; @@ -64,6 +65,7 @@ use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; +use Filament\Forms\Components\Contracts\CanEntangleWithSingularRelationships; class EditEvent extends EditRecord { @@ -98,6 +100,24 @@ public function form(Form $form): Form ->required(), Fieldset::make('Registration Form') ->relationship('eventRegistrationForm') + ->saveRelationshipsBeforeChildrenUsing(static function (Component | CanEntangleWithSingularRelationships $component): void { + $component->getCachedExistingRecord()?->delete(); + + $relationship = $component->getRelationship(); + + $data = $component->getChildComponentContainer()->getState(shouldCallHooksBefore: false); + $data = $component->mutateRelationshipDataBeforeCreate($data); + + $relatedModel = $component->getRelatedModel(); + + $record = new $relatedModel(); + $record->fill($data); + + $relationship->save($record); + + $component->cachedExistingRecord($record); + }) + ->saveRelationshipsUsing(null) ->schema([ Grid::make() ->schema([ @@ -203,8 +223,6 @@ public function fieldBuilder(): TiptapEditor $state = tiptap_converter()->asJSON($state, decoded: true); } - ray('here2'); - $state = $component->renderBlockPreviews($state, $component); $component->state($state); @@ -275,14 +293,14 @@ protected function clearFormContentForWizard(): void $form = $event->eventRegistrationForm; - if ($form->is_wizard) { + if ($form?->is_wizard) { $form->content = null; $form->save(); return; } - $form->steps()->delete(); + $form?->steps()->delete(); } protected function getHeaderActions(): array diff --git a/app-modules/meeting-center/src/Models/EventRegistrationForm.php b/app-modules/meeting-center/src/Models/EventRegistrationForm.php index e8ed9f9aa2..66dda93cad 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationForm.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationForm.php @@ -38,6 +38,7 @@ use AdvisingApp\Form\Enums\Rounding; use AdvisingApp\Form\Models\Submissible; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -46,6 +47,8 @@ */ class EventRegistrationForm extends Submissible { + use SoftDeletes; + protected $fillable = [ 'form_id', 'embed_enabled', From 61651b32d641f33f6dddc8614da57cf38fc34ca0 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 10:58:26 -0500 Subject: [PATCH 036/152] Upgrade filament and remove hydration fix Signed-off-by: Kevin Ullyott --- .../EventResource/Pages/EditEvent.php | 21 +- composer.lock | 237 +++++++++--------- 2 files changed, 119 insertions(+), 139 deletions(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index 72eda35866..aa11585866 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -71,8 +71,6 @@ class EditEvent extends EditRecord { protected static string $resource = EventResource::class; - protected bool $contentHydrated = false; - public function form(Form $form): Form { /** @var User $user */ @@ -211,24 +209,7 @@ public function fieldBuilder(): TiptapEditor }) ->dehydrated(false) ->columnSpanFull() - ->extraInputAttributes(['style' => 'min-height: 12rem;']) - ->afterStateHydrated(function (TiptapEditor $component, string | array | null $state): void { - // TODO: This is a temporary fix until we can figure out whey this gets hydrated twice. - - if (! $state || $this->contentHydrated) { - return; - } - - if (! is_array($state)) { - $state = tiptap_converter()->asJSON($state, decoded: true); - } - - $state = $component->renderBlockPreviews($state, $component); - - $component->state($state); - - $this->contentHydrated = true; - }); + ->extraInputAttributes(['style' => 'min-height: 12rem;']); } public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array diff --git a/composer.lock b/composer.lock index 2377067c69..029ba3e12f 100644 --- a/composer.lock +++ b/composer.lock @@ -755,16 +755,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.294.5", + "version": "3.295.2", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "2e34d45e970c77775e4c298e08732d64b647c41c" + "reference": "7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2e34d45e970c77775e4c298e08732d64b647c41c", - "reference": "2e34d45e970c77775e4c298e08732d64b647c41c", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73", + "reference": "7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73", "shasum": "" }, "require": { @@ -844,9 +844,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.294.5" + "source": "https://github.com/aws/aws-sdk-php/tree/3.295.2" }, - "time": "2023-12-21T19:10:21+00:00" + "time": "2023-12-27T19:06:10+00:00" }, { "name": "barryvdh/laravel-debugbar", @@ -4071,16 +4071,16 @@ }, { "name": "filament/actions", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "be3a8c110aa69f3f4856816eefd477b600bc06e2" + "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/be3a8c110aa69f3f4856816eefd477b600bc06e2", - "reference": "be3a8c110aa69f3f4856816eefd477b600bc06e2", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/8f2a3df7c607a24c2433a3a71cb27b20a8dea203", + "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203", "shasum": "" }, "require": { @@ -4118,20 +4118,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-21T12:38:03+00:00" + "time": "2023-12-28T15:54:29+00:00" }, { "name": "filament/filament", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "e1aa070483c2eaa5bb92ce8d959779a9558fe022" + "reference": "ae12dc49094560188a4289778a54773045880e44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/e1aa070483c2eaa5bb92ce8d959779a9558fe022", - "reference": "e1aa070483c2eaa5bb92ce8d959779a9558fe022", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/ae12dc49094560188a4289778a54773045880e44", + "reference": "ae12dc49094560188a4289778a54773045880e44", "shasum": "" }, "require": { @@ -4183,20 +4183,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:15+00:00" + "time": "2023-12-28T15:54:35+00:00" }, { "name": "filament/forms", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "673689bd958797b05127fe9956eafeed555b91bd" + "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/673689bd958797b05127fe9956eafeed555b91bd", - "reference": "673689bd958797b05127fe9956eafeed555b91bd", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/26e177a4b3a8ef7b8326d992bb5073f02220a506", + "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506", "shasum": "" }, "require": { @@ -4239,20 +4239,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:00+00:00" + "time": "2023-12-28T15:54:30+00:00" }, { "name": "filament/infolists", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", - "reference": "9207c2b83ba9c8dcbcac9a930e93ce87f381d780" + "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/infolists/zipball/9207c2b83ba9c8dcbcac9a930e93ce87f381d780", - "reference": "9207c2b83ba9c8dcbcac9a930e93ce87f381d780", + "url": "https://api.github.com/repos/filamentphp/infolists/zipball/66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", + "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", "shasum": "" }, "require": { @@ -4290,20 +4290,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:00+00:00" + "time": "2023-12-26T22:39:20+00:00" }, { "name": "filament/notifications", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", - "reference": "5b9255c0793751534461cace12febdc0d4cc05bb" + "reference": "4f5634f9df312050efa3a035c543add6cec0e3a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/notifications/zipball/5b9255c0793751534461cace12febdc0d4cc05bb", - "reference": "5b9255c0793751534461cace12febdc0d4cc05bb", + "url": "https://api.github.com/repos/filamentphp/notifications/zipball/4f5634f9df312050efa3a035c543add6cec0e3a2", + "reference": "4f5634f9df312050efa3a035c543add6cec0e3a2", "shasum": "" }, "require": { @@ -4342,11 +4342,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-17T22:25:42+00:00" + "time": "2023-12-28T15:54:27+00:00" }, { "name": "filament/spatie-laravel-media-library-plugin", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-media-library-plugin.git", @@ -4383,16 +4383,16 @@ }, { "name": "filament/spatie-laravel-settings-plugin", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-settings-plugin.git", - "reference": "7119f3f714dfa0ce098cd90aa2a741147a5508f6" + "reference": "d26f397a845934462d511432ba88363f63a7e203" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/spatie-laravel-settings-plugin/zipball/7119f3f714dfa0ce098cd90aa2a741147a5508f6", - "reference": "7119f3f714dfa0ce098cd90aa2a741147a5508f6", + "url": "https://api.github.com/repos/filamentphp/spatie-laravel-settings-plugin/zipball/d26f397a845934462d511432ba88363f63a7e203", + "reference": "d26f397a845934462d511432ba88363f63a7e203", "shasum": "" }, "require": { @@ -4426,20 +4426,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-19T13:24:28+00:00" + "time": "2023-12-26T22:39:37+00:00" }, { "name": "filament/support", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd" + "reference": "97792dad038a87b7a6bfe465c4f1913252c99017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd", - "reference": "f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd", + "url": "https://api.github.com/repos/filamentphp/support/zipball/97792dad038a87b7a6bfe465c4f1913252c99017", + "reference": "97792dad038a87b7a6bfe465c4f1913252c99017", "shasum": "" }, "require": { @@ -4483,20 +4483,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:21+00:00" + "time": "2023-12-24T21:16:58+00:00" }, { "name": "filament/tables", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "3391bd1015bdde8e454d0a6391952dc131fb8dad" + "reference": "ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/3391bd1015bdde8e454d0a6391952dc131fb8dad", - "reference": "3391bd1015bdde8e454d0a6391952dc131fb8dad", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67", + "reference": "ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67", "shasum": "" }, "require": { @@ -4536,20 +4536,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:23+00:00" + "time": "2023-12-28T15:54:29+00:00" }, { "name": "filament/widgets", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "290184b9dfb99436df94a9a0b8511b21811d9e64" + "reference": "7195d2fe7d12a9b9595fa445a4dbedd6d7714836" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/290184b9dfb99436df94a9a0b8511b21811d9e64", - "reference": "290184b9dfb99436df94a9a0b8511b21811d9e64", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/7195d2fe7d12a9b9595fa445a4dbedd6d7714836", + "reference": "7195d2fe7d12a9b9595fa445a4dbedd6d7714836", "shasum": "" }, "require": { @@ -4580,7 +4580,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-17T22:26:03+00:00" + "time": "2023-12-24T21:17:06+00:00" }, { "name": "firebase/php-jwt", @@ -5154,16 +5154,16 @@ }, { "name": "google/apiclient-services", - "version": "v0.328.0", + "version": "v0.329.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d" + "reference": "3216fd1b6ba33c5f6658c3581e9723ff21d9acb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d", - "reference": "211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/3216fd1b6ba33c5f6658c3581e9723ff21d9acb7", + "reference": "3216fd1b6ba33c5f6658c3581e9723ff21d9acb7", "shasum": "" }, "require": { @@ -5192,9 +5192,9 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.328.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.329.0" }, - "time": "2023-12-18T01:00:18+00:00" + "time": "2023-12-24T01:02:15+00:00" }, { "name": "google/auth", @@ -6182,16 +6182,16 @@ }, { "name": "laravel/framework", - "version": "v10.38.2", + "version": "v10.39.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "43da808391da3540d44a8dfeb4e46da4ad8f5723" + "reference": "114926b07bfb5fbf2545c03aa2ce5c8c37be650c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/43da808391da3540d44a8dfeb4e46da4ad8f5723", - "reference": "43da808391da3540d44a8dfeb4e46da4ad8f5723", + "url": "https://api.github.com/repos/laravel/framework/zipball/114926b07bfb5fbf2545c03aa2ce5c8c37be650c", + "reference": "114926b07bfb5fbf2545c03aa2ce5c8c37be650c", "shasum": "" }, "require": { @@ -6294,7 +6294,7 @@ "league/flysystem-sftp-v3": "^3.0", "mockery/mockery": "^1.5.1", "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^8.15.1", + "orchestra/testbench-core": "^8.18", "pda/pheanstalk": "^4.0", "phpstan/phpstan": "^1.4.7", "phpunit/phpunit": "^10.0.7", @@ -6383,20 +6383,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-12-22T14:39:10+00:00" + "time": "2023-12-27T14:26:28+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.13", + "version": "v0.1.14", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "e1379d8ead15edd6cc4369c22274345982edc95a" + "reference": "2219fa9c4b944add1e825c3bdb8ecae8bc503bc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/e1379d8ead15edd6cc4369c22274345982edc95a", - "reference": "e1379d8ead15edd6cc4369c22274345982edc95a", + "url": "https://api.github.com/repos/laravel/prompts/zipball/2219fa9c4b944add1e825c3bdb8ecae8bc503bc6", + "reference": "2219fa9c4b944add1e825c3bdb8ecae8bc503bc6", "shasum": "" }, "require": { @@ -6412,7 +6412,7 @@ "require-dev": { "mockery/mockery": "^1.5", "pestphp/pest": "^2.3", - "phpstan/phpstan": "^1.10", + "phpstan/phpstan": "^1.11", "phpstan/phpstan-mockery": "^1.1" }, "suggest": { @@ -6438,22 +6438,22 @@ ], "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.13" + "source": "https://github.com/laravel/prompts/tree/v0.1.14" }, - "time": "2023-10-27T13:53:59+00:00" + "time": "2023-12-27T04:18:09+00:00" }, { "name": "laravel/sanctum", - "version": "v3.3.2", + "version": "v3.3.3", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "e1a272893bec13cf135627f7e156030b3afe1e60" + "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/e1a272893bec13cf135627f7e156030b3afe1e60", - "reference": "e1a272893bec13cf135627f7e156030b3afe1e60", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/8c104366459739f3ada0e994bcd3e6fd681ce3d5", + "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5", "shasum": "" }, "require": { @@ -6506,7 +6506,7 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2023-11-03T13:42:14+00:00" + "time": "2023-12-19T18:44:48+00:00" }, { "name": "laravel/scout", @@ -12914,16 +12914,16 @@ }, { "name": "spatie/temporary-directory", - "version": "2.2.0", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/spatie/temporary-directory.git", - "reference": "efc258c9f4da28f0c7661765b8393e4ccee3d19c" + "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/efc258c9f4da28f0c7661765b8393e4ccee3d19c", - "reference": "efc258c9f4da28f0c7661765b8393e4ccee3d19c", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", + "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", "shasum": "" }, "require": { @@ -12959,7 +12959,7 @@ ], "support": { "issues": "https://github.com/spatie/temporary-directory/issues", - "source": "https://github.com/spatie/temporary-directory/tree/2.2.0" + "source": "https://github.com/spatie/temporary-directory/tree/2.2.1" }, "funding": [ { @@ -12971,7 +12971,7 @@ "type": "github" } ], - "time": "2023-09-25T07:13:36+00:00" + "time": "2023-12-25T11:46:58+00:00" }, { "name": "sqids/sqids", @@ -15486,21 +15486,21 @@ }, { "name": "symfony/service-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -15548,7 +15548,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -15564,7 +15564,7 @@ "type": "tidelift" } ], - "time": "2023-07-30T20:28:31+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/string", @@ -15749,16 +15749,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" + "reference": "06450585bf65e978026bda220cdebca3f867fde7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", + "reference": "06450585bf65e978026bda220cdebca3f867fde7", "shasum": "" }, "require": { @@ -15807,7 +15807,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" }, "funding": [ { @@ -15823,7 +15823,7 @@ "type": "tidelift" } ], - "time": "2023-07-25T15:08:44+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/uid", @@ -17148,16 +17148,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.41.1", + "version": "v3.42.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6" + "reference": "632ef1be3447a9b890bef06147475facee535d0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8b6ae8dcbaf23f09680643ab832a4a3a260265f6", - "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/632ef1be3447a9b890bef06147475facee535d0f", + "reference": "632ef1be3447a9b890bef06147475facee535d0f", "shasum": "" }, "require": { @@ -17188,7 +17188,6 @@ "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", "phpunit/phpunit": "^9.6", - "symfony/phpunit-bridge": "^6.3.8 || ^7.0", "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { @@ -17227,7 +17226,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.41.1" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.42.0" }, "funding": [ { @@ -17235,7 +17234,7 @@ "type": "github" } ], - "time": "2023-12-10T19:59:27+00:00" + "time": "2023-12-24T14:38:51+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -17753,36 +17752,36 @@ }, { "name": "pestphp/pest", - "version": "v2.28.1", + "version": "v2.30.0", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "9ee41910201ef8fc5f5b6d1390e5ec4558222927" + "reference": "97dc32f9d24b84dd071d9e89438a19e43c833f6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/9ee41910201ef8fc5f5b6d1390e5ec4558222927", - "reference": "9ee41910201ef8fc5f5b6d1390e5ec4558222927", + "url": "https://api.github.com/repos/pestphp/pest/zipball/97dc32f9d24b84dd071d9e89438a19e43c833f6f", + "reference": "97dc32f9d24b84dd071d9e89438a19e43c833f6f", "shasum": "" }, "require": { "brianium/paratest": "^7.3.1", - "nunomaduro/collision": "^7.10.0|^8.0.0", + "nunomaduro/collision": "^7.10.0|^8.0.1", "nunomaduro/termwind": "^1.15.1|^2.0.0", "pestphp/pest-plugin": "^2.1.1", "pestphp/pest-plugin-arch": "^2.5.0", "php": "^8.1.0", - "phpunit/phpunit": "^10.5.3" + "phpunit/phpunit": "^10.5.5" }, "conflict": { - "phpunit/phpunit": ">10.5.3", + "phpunit/phpunit": ">10.5.5", "sebastian/exporter": "<5.1.0", "webmozart/assert": "<1.11.0" }, "require-dev": { "pestphp/pest-dev-tools": "^2.16.0", - "pestphp/pest-plugin-type-coverage": "^2.5.0", - "symfony/process": "^6.4.0|^7.0.1" + "pestphp/pest-plugin-type-coverage": "^2.6.0", + "symfony/process": "^6.4.0|^7.0.0" }, "bin": [ "bin/pest" @@ -17845,7 +17844,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v2.28.1" + "source": "https://github.com/pestphp/pest/tree/v2.30.0" }, "funding": [ { @@ -17857,7 +17856,7 @@ "type": "github" } ], - "time": "2023-12-15T11:42:34+00:00" + "time": "2023-12-28T10:36:40+00:00" }, { "name": "pestphp/pest-plugin", @@ -18840,16 +18839,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.3", + "version": "10.5.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19" + "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6fce887c71076a73f32fd3e0774a6833fc5c7f19", - "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ed21115d505b4b4f7dc7b5651464e19a2c7f7856", + "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856", "shasum": "" }, "require": { @@ -18921,7 +18920,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.5" }, "funding": [ { @@ -18937,7 +18936,7 @@ "type": "tidelift" } ], - "time": "2023-12-13T07:25:23+00:00" + "time": "2023-12-27T15:13:52+00:00" }, { "name": "pimple/pimple", From 0d73045c00b7c5a56f86807c7dabc450e029f278 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 12:15:40 -0500 Subject: [PATCH 037/152] Fix issue with signed urls Signed-off-by: Kevin Ullyott --- .../src/Http/Controllers/EventRegistrationWidgetController.php | 2 -- app/Providers/AppServiceProvider.php | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index d542a26ad2..eee1f4c4a1 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -63,8 +63,6 @@ public function view(GenerateFormKitSchema $generateSchema, Event $event): JsonR { $form = $event->eventRegistrationForm; - ray($event, $form); - return response()->json( [ 'name' => $form->event->title, diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index f54cc6fd41..4483cd73a2 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -64,6 +64,7 @@ public function boot(): void if (config('app.force_https')) { URL::forceScheme('https'); + $this->app['request']->server->set('HTTPS', true); } } } From 5c99e8164f224c347c75535e148d36dba65cfea0 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 12:29:06 -0500 Subject: [PATCH 038/152] Share event configuration between create and edit Signed-off-by: Kevin Ullyott --- .../HasSharedEventFormConfiguration.php | 245 ++++++++++++++++++ .../EventResource/Pages/CreateEvent.php | 32 +-- .../EventResource/Pages/EditEvent.php | 238 +---------------- 3 files changed, 253 insertions(+), 262 deletions(-) create mode 100644 app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php new file mode 100644 index 0000000000..f3de80786e --- /dev/null +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php @@ -0,0 +1,245 @@ +user(); + + return [ + TextInput::make('title') + ->string() + ->required(), + Textarea::make('description') + ->string() + ->nullable(), + TextInput::make('location') + ->string() + ->nullable(), + TextInput::make('capacity') + ->integer() + ->minValue(1) + ->nullable(), + DateTimePicker::make('starts_at') + ->timezone($user->timezone) + ->required(), + DateTimePicker::make('ends_at') + ->timezone($user->timezone) + ->required(), + Fieldset::make('Registration Form') + ->relationship('eventRegistrationForm') + ->saveRelationshipsBeforeChildrenUsing(static function (Component | CanEntangleWithSingularRelationships $component): void { + $component->getCachedExistingRecord()?->delete(); + + $relationship = $component->getRelationship(); + + $data = $component->getChildComponentContainer()->getState(shouldCallHooksBefore: false); + $data = $component->mutateRelationshipDataBeforeCreate($data); + + $relatedModel = $component->getRelatedModel(); + + $record = new $relatedModel(); + $record->fill($data); + + $relationship->save($record); + + $component->cachedExistingRecord($record); + }) + ->saveRelationshipsUsing(null) + ->schema([ + Grid::make() + ->schema([ + Toggle::make('embed_enabled') + ->label('Embed Enabled') + ->live() + ->helperText('If enabled, this form can be embedded on other websites.'), + TagsInput::make('allowed_domains') + ->label('Allowed Domains') + ->helperText('Only these domains will be allowed to embed this form.') + ->placeholder('example.com') + ->hidden(fn (Get $get) => ! $get('embed_enabled')) + ->disabled(fn (Get $get) => ! $get('embed_enabled')) + ->nestedRecursiveRules( + [ + 'string', + new IsDomain(), + ] + ), + ]) + ->columnSpanFull(), + Toggle::make('is_wizard') + ->label('Multi-step form') + ->live() + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), + Section::make('Fields') + ->schema([ + $this->fieldBuilder(), + ]) + ->hidden(fn (Get $get) => $get('is_wizard')) + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), + Repeater::make('steps') + ->schema([ + TextInput::make('label') + ->required() + ->string() + ->maxLength(255) + ->autocomplete(false) + ->columnSpanFull() + ->lazy(), + $this->fieldBuilder(), + ]) + ->addActionLabel('New step') + ->itemLabel(fn (array $state): ?string => $state['label'] ?? null) + ->visible(fn (Get $get) => $get('is_wizard')) + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()) + ->relationship() + ->reorderable() + ->columnSpanFull(), + Section::make('Appearance') + ->schema([ + ColorSelect::make('primary_color'), + Select::make('rounding') + ->options(Rounding::class), + ]) + ->columns(), + ]), + ]; + } + + public function fieldBuilder(): TiptapEditor + { + return TiptapEditor::make('content') + ->output(TiptapOutput::Json) + ->blocks(FormFieldBlockRegistry::get()) + ->tools(['bold', 'italic', 'small', '|', 'heading', 'bullet-list', 'ordered-list', 'hr', '|', 'link', 'grid', 'blocks']) + ->placeholder('Drag blocks here to build your form') + ->hiddenLabel() + ->saveRelationshipsUsing(function (TiptapEditor $component, EventRegistrationForm | EventRegistrationFormStep $record) { + if ($component->isDisabled()) { + return; + } + + $form = $record instanceof EventRegistrationForm ? $record : $record->submissible; + $formStep = $record instanceof EventRegistrationFormStep ? $record : null; + + EventRegistrationFormStep::query() + ->whereBelongsTo($form, 'submissible') + ->when($formStep, fn (EloquentBuilder $query) => $query->whereBelongsTo($formStep, 'step')) + ->delete(); + + $content = $component->decodeBlocksBeforeSave($component->getJSON(decoded: true)); + $content['content'] = $this->saveFieldsFromComponents( + $form, + $content['content'] ?? [], + $formStep, + ); + + $record->content = $content; + $record->save(); + }) + ->dehydrated(false) + ->columnSpanFull() + ->extraInputAttributes(['style' => 'min-height: 12rem;']); + } + + public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array + { + foreach ($components as $componentKey => $component) { + if (array_key_exists('content', $component)) { + $components[$componentKey]['content'] = $this->saveFieldsFromComponents($form, $component['content'], $eventRegistrationFormStep); + + continue; + } + + if ($component['type'] !== 'tiptapBlock') { + continue; + } + + $componentAttributes = $component['attrs'] ?? []; + + if (array_key_exists('id', $componentAttributes)) { + $id = $componentAttributes['id'] ?? null; + unset($componentAttributes['id']); + } + + if (array_key_exists('label', $componentAttributes['data'])) { + $label = $componentAttributes['data']['label'] ?? null; + unset($componentAttributes['data']['label']); + } + + if (array_key_exists('isRequired', $componentAttributes['data'])) { + $isRequired = $componentAttributes['data']['isRequired'] ?? null; + unset($componentAttributes['data']['isRequired']); + } + + /** @var EventRegistrationFormField $field */ + $field = $form->fields()->findOrNew($id ?? null); + $field->step()->associate($eventRegistrationFormStep); + $field->label = $label ?? $componentAttributes['type']; + $field->is_required = $isRequired ?? false; + $field->type = $componentAttributes['type']; + $field->config = $componentAttributes['data']; + $field->save(); + + $components[$componentKey]['attrs']['id'] = $field->id; + } + + return $components; + } + + protected function afterCreate(): void + { + $this->clearFormContentForWizard(); + } + + protected function afterSave(): void + { + $this->clearFormContentForWizard(); + } + + protected function clearFormContentForWizard(): void + { + /** @var Event $event */ + $event = $this->record; + + $form = $event->eventRegistrationForm; + + if ($form?->is_wizard) { + $form->content = null; + $form->save(); + + return; + } + + $form?->steps()->delete(); + } +} diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/CreateEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/CreateEvent.php index 5fb7b12ea2..28a87776c3 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/CreateEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/CreateEvent.php @@ -36,43 +36,19 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; -use App\Models\User; use Filament\Forms\Form; -use Filament\Forms\Components\Textarea; -use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\CreateRecord; -use Filament\Forms\Components\DateTimePicker; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; +use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\Concerns\HasSharedEventFormConfiguration; class CreateEvent extends CreateRecord { + use HasSharedEventFormConfiguration; + protected static string $resource = EventResource::class; public function form(Form $form): Form { - /** @var User $user */ - $user = auth()->user(); - - return $form->schema([ - TextInput::make('title') - ->string() - ->required(), - Textarea::make('description') - ->string() - ->nullable(), - TextInput::make('location') - ->string() - ->nullable(), - TextInput::make('capacity') - ->integer() - ->minValue(1) - ->nullable(), - DateTimePicker::make('starts_at') - ->timezone($user->timezone) - ->required(), - DateTimePicker::make('ends_at') - ->timezone($user->timezone) - ->required(), - ]); + return $form->schema($this->fields()); } } diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index aa11585866..7e8a652fdf 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -36,252 +36,22 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; -use App\Models\User; -use Filament\Forms\Get; use Filament\Forms\Form; use Filament\Actions\ViewAction; use Filament\Actions\DeleteAction; -use Filament\Forms\Components\Grid; -use AdvisingApp\Form\Enums\Rounding; -use AdvisingApp\Form\Rules\IsDomain; -use App\Forms\Components\ColorSelect; -use Filament\Forms\Components\Select; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Components\Section; -use FilamentTiptapEditor\TiptapEditor; -use Filament\Forms\Components\Fieldset; -use Filament\Forms\Components\Repeater; -use Filament\Forms\Components\Textarea; -use Filament\Forms\Components\Component; -use Filament\Forms\Components\TagsInput; -use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; -use AdvisingApp\MeetingCenter\Models\Event; -use FilamentTiptapEditor\Enums\TiptapOutput; -use Filament\Forms\Components\DateTimePicker; -use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; -use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; -use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; -use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; -use Filament\Forms\Components\Contracts\CanEntangleWithSingularRelationships; +use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\Concerns\HasSharedEventFormConfiguration; class EditEvent extends EditRecord { + use HasSharedEventFormConfiguration; + protected static string $resource = EventResource::class; public function form(Form $form): Form { - /** @var User $user */ - $user = auth()->user(); - - return $form->schema([ - TextInput::make('title') - ->string() - ->required(), - Textarea::make('description') - ->string() - ->nullable(), - TextInput::make('location') - ->string() - ->nullable(), - TextInput::make('capacity') - ->integer() - ->minValue(1) - ->nullable(), - DateTimePicker::make('starts_at') - ->timezone($user->timezone) - ->required(), - DateTimePicker::make('ends_at') - ->timezone($user->timezone) - ->required(), - Fieldset::make('Registration Form') - ->relationship('eventRegistrationForm') - ->saveRelationshipsBeforeChildrenUsing(static function (Component | CanEntangleWithSingularRelationships $component): void { - $component->getCachedExistingRecord()?->delete(); - - $relationship = $component->getRelationship(); - - $data = $component->getChildComponentContainer()->getState(shouldCallHooksBefore: false); - $data = $component->mutateRelationshipDataBeforeCreate($data); - - $relatedModel = $component->getRelatedModel(); - - $record = new $relatedModel(); - $record->fill($data); - - $relationship->save($record); - - $component->cachedExistingRecord($record); - }) - ->saveRelationshipsUsing(null) - ->schema([ - Grid::make() - ->schema([ - Toggle::make('embed_enabled') - ->label('Embed Enabled') - ->live() - ->helperText('If enabled, this form can be embedded on other websites.'), - TagsInput::make('allowed_domains') - ->label('Allowed Domains') - ->helperText('Only these domains will be allowed to embed this form.') - ->placeholder('example.com') - ->hidden(fn (Get $get) => ! $get('embed_enabled')) - ->disabled(fn (Get $get) => ! $get('embed_enabled')) - ->nestedRecursiveRules( - [ - 'string', - new IsDomain(), - ] - ), - ]) - ->columnSpanFull(), - Toggle::make('is_wizard') - ->label('Multi-step form') - ->live() - ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), - Section::make('Fields') - ->schema([ - $this->fieldBuilder(), - ]) - ->hidden(fn (Get $get) => $get('is_wizard')) - ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), - Repeater::make('steps') - ->schema([ - TextInput::make('label') - ->required() - ->string() - ->maxLength(255) - ->autocomplete(false) - ->columnSpanFull() - ->lazy(), - $this->fieldBuilder(), - ]) - ->addActionLabel('New step') - ->itemLabel(fn (array $state): ?string => $state['label'] ?? null) - ->visible(fn (Get $get) => $get('is_wizard')) - ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()) - ->relationship() - ->reorderable() - ->columnSpanFull(), - Section::make('Appearance') - ->schema([ - ColorSelect::make('primary_color'), - Select::make('rounding') - ->options(Rounding::class), - ]) - ->columns(), - ]), - ]); - } - - public function fieldBuilder(): TiptapEditor - { - return TiptapEditor::make('content') - ->output(TiptapOutput::Json) - ->blocks(FormFieldBlockRegistry::get()) - ->tools(['bold', 'italic', 'small', '|', 'heading', 'bullet-list', 'ordered-list', 'hr', '|', 'link', 'grid', 'blocks']) - ->placeholder('Drag blocks here to build your form') - ->hiddenLabel() - ->saveRelationshipsUsing(function (TiptapEditor $component, EventRegistrationForm | EventRegistrationFormStep $record) { - if ($component->isDisabled()) { - return; - } - - $form = $record instanceof EventRegistrationForm ? $record : $record->submissible; - $formStep = $record instanceof EventRegistrationFormStep ? $record : null; - - EventRegistrationFormStep::query() - ->whereBelongsTo($form, 'submissible') - ->when($formStep, fn (EloquentBuilder $query) => $query->whereBelongsTo($formStep, 'step')) - ->delete(); - - $content = $component->decodeBlocksBeforeSave($component->getJSON(decoded: true)); - $content['content'] = $this->saveFieldsFromComponents( - $form, - $content['content'] ?? [], - $formStep, - ); - - $record->content = $content; - $record->save(); - }) - ->dehydrated(false) - ->columnSpanFull() - ->extraInputAttributes(['style' => 'min-height: 12rem;']); - } - - public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array - { - foreach ($components as $componentKey => $component) { - if (array_key_exists('content', $component)) { - $components[$componentKey]['content'] = $this->saveFieldsFromComponents($form, $component['content'], $eventRegistrationFormStep); - - continue; - } - - if ($component['type'] !== 'tiptapBlock') { - continue; - } - - $componentAttributes = $component['attrs'] ?? []; - - if (array_key_exists('id', $componentAttributes)) { - $id = $componentAttributes['id'] ?? null; - unset($componentAttributes['id']); - } - - if (array_key_exists('label', $componentAttributes['data'])) { - $label = $componentAttributes['data']['label'] ?? null; - unset($componentAttributes['data']['label']); - } - - if (array_key_exists('isRequired', $componentAttributes['data'])) { - $isRequired = $componentAttributes['data']['isRequired'] ?? null; - unset($componentAttributes['data']['isRequired']); - } - - /** @var EventRegistrationFormField $field */ - $field = $form->fields()->findOrNew($id ?? null); - $field->step()->associate($eventRegistrationFormStep); - $field->label = $label ?? $componentAttributes['type']; - $field->is_required = $isRequired ?? false; - $field->type = $componentAttributes['type']; - $field->config = $componentAttributes['data']; - $field->save(); - - $components[$componentKey]['attrs']['id'] = $field->id; - } - - return $components; - } - - protected function afterCreate(): void - { - $this->clearFormContentForWizard(); - } - - protected function afterSave(): void - { - $this->clearFormContentForWizard(); - } - - protected function clearFormContentForWizard(): void - { - /** @var Event $event */ - $event = $this->record; - - $form = $event->eventRegistrationForm; - - if ($form?->is_wizard) { - $form->content = null; - $form->save(); - - return; - } - - $form?->steps()->delete(); + return $form->schema($this->fields()); } protected function getHeaderActions(): array From a88b659b8987816c68ae5093b5901304e4bc153d Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 13:03:40 -0500 Subject: [PATCH 039/152] Start working on adding the content Signed-off-by: Kevin Ullyott --- .../src/Actions/GenerateFormKitSchema.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index 1ce5fa3530..21b693588d 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -68,6 +68,32 @@ public function __invoke(Submissible $submissible): array ]; } + $content = [ + [ + '$formkit' => 'radio', + 'label' => 'Will you be attending?', + 'name' => 'attending', + 'options' => [ + [ + 'label' => 'Yes', + 'value' => 'yes', + ], + [ + 'label' => 'No', + 'value' => 'no', + ], + ], + 'validation' => 'required', + ], + [ + '$el' => 'div', + 'attrs' => [ + 'if' => '$get(form).values.attending === "yes"', + ], + 'children' => $content, + ], + ]; + return [ '$cmp' => 'FormKit', 'props' => [ From 9af3de4b850ca6f328de102134eab5229d391344 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 14:17:45 -0500 Subject: [PATCH 040/152] Fix data saving issues Signed-off-by: Kevin Ullyott --- .../src/Actions/GenerateFormKitSchema.php | 11 +++-- .../EventRegistrationWidgetController.php | 43 +++++++++++-------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index 21b693588d..f9f19e2ede 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -72,6 +72,7 @@ public function __invoke(Submissible $submissible): array [ '$formkit' => 'radio', 'label' => 'Will you be attending?', + 'id' => 'attending', 'name' => 'attending', 'options' => [ [ @@ -87,11 +88,15 @@ public function __invoke(Submissible $submissible): array ], [ '$el' => 'div', - 'attrs' => [ - 'if' => '$get(form).values.attending === "yes"', - ], + 'if' => '$get(attending).value === "yes"', 'children' => $content, ], + [ + '$formkit' => 'submit', + 'if' => '$get(attending).value === "no"', + 'label' => 'Submit', + 'disabled' => '$get(form).state.valid !== true', + ], ]; return [ diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index eee1f4c4a1..19672440e5 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -167,12 +167,17 @@ public function store( abort(Response::HTTP_UNAUTHORIZED); } + // TODO See if we can make attending a bool + $validator = Validator::make( $request->all(), - $generateValidation($form) + [ + 'attending' => ['required', 'in:yes,no'], + ...$request->get('attending') === 'yes' ? $generateValidation($form) : [], + ] ); - ray($validator->errors()); + //ray($validator->errors()); if ($validator->fails()) { return response()->json( @@ -192,33 +197,37 @@ public function store( $submission->submitted_at = now(); - // TODO: Adjust the status of the EventAttendee to Attending or Not Attending based on the form submission. - $submission->save(); + $authentication->author->update(['status' => $request->get('attending') === 'yes' ? EventAttendeeStatus::Attending : EventAttendeeStatus::NotAttending]); + $data = $validator->validated(); - unset($data['recaptcha-token']); + // TODO: change the EventFormSubmission to have a column to store the attending data item + + if ($data['attending'] === 'yes') { + unset($data['recaptcha-token'], $data['attending']); - if ($form->is_wizard) { - foreach ($form->steps as $step) { - foreach ($data[$step->label] as $fieldId => $response) { + if ($form->is_wizard) { + foreach ($form->steps as $step) { + foreach ($data[$step->label] as $fieldId => $response) { + $submission->fields()->attach( + $fieldId, + ['id' => Str::orderedUuid(), 'response' => $response], + ); + } + } + } else { + foreach ($data as $fieldId => $response) { $submission->fields()->attach( $fieldId, ['id' => Str::orderedUuid(), 'response' => $response], ); } } - } else { - foreach ($data as $fieldId => $response) { - $submission->fields()->attach( - $fieldId, - ['id' => Str::orderedUuid(), 'response' => $response], - ); - } - } - $submission->save(); + $submission->save(); + } return response()->json( [ From 3ccb4ade862a1dc2c71bebfc487eb3dda98ff84e Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 14:39:38 -0500 Subject: [PATCH 041/152] Fix more issues Signed-off-by: Kevin Ullyott --- ...nt_registration_form_submissions_table.php | 1 + .../EventRegistrationWidgetController.php | 108 ++++++++++-------- .../EventRegistrationFormSubmission.php | 3 + widgets/event-registration/src/App.vue | 13 ++- 4 files changed, 72 insertions(+), 53 deletions(-) diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php index 0165143dbd..2b362933c9 100644 --- a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php @@ -46,6 +46,7 @@ public function up(): void $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); + $table->string('attendee_status'); $table->timestamp('submitted_at')->nullable(); $table->timestamp('canceled_at')->nullable(); $table->string('request_method')->nullable(); diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index 19672440e5..bae23c1cbd 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -37,10 +37,12 @@ namespace AdvisingApp\MeetingCenter\Http\Controllers; use Closure; +use Exception; use Illuminate\Support\Str; use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; use Filament\Support\Colors\Color; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\URL; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; @@ -153,80 +155,88 @@ public function store( GenerateSubmissibleValidation $generateValidation, Event $event, ): JsonResponse { - $form = $event->eventRegistrationForm; - - $authentication = $request->query('authentication'); + try { + DB::beginTransaction(); - if (filled($authentication)) { - $authentication = EventRegistrationFormAuthentication::findOrFail($authentication); - } - - if ( - ($authentication?->isExpired() ?? true) - ) { - abort(Response::HTTP_UNAUTHORIZED); - } + $form = $event->eventRegistrationForm; - // TODO See if we can make attending a bool + $authentication = $request->query('authentication'); - $validator = Validator::make( - $request->all(), - [ - 'attending' => ['required', 'in:yes,no'], - ...$request->get('attending') === 'yes' ? $generateValidation($form) : [], - ] - ); + if (filled($authentication)) { + $authentication = EventRegistrationFormAuthentication::findOrFail($authentication); + } - //ray($validator->errors()); + if ( + ($authentication?->isExpired() ?? true) + ) { + abort(Response::HTTP_UNAUTHORIZED); + } - if ($validator->fails()) { - return response()->json( + $validator = Validator::make( + $request->all(), [ - 'errors' => (object) $validator->errors(), - ], - Response::HTTP_UNPROCESSABLE_ENTITY + 'attending' => ['required', 'in:yes,no'], + ...$request->get('attending') === 'yes' ? $generateValidation($form) : [], + ] ); - } - /** @var EventRegistrationFormSubmission $submission */ - $submission = $form->submissions()->make(); + if ($validator->fails()) { + return response()->json( + [ + 'errors' => (object) $validator->errors(), + ], + Response::HTTP_UNPROCESSABLE_ENTITY + ); + } - $submission->author()->associate($authentication->author); + /** @var EventRegistrationFormSubmission $submission */ + $submission = $form->submissions()->make(); - $authentication->delete(); + $submission->author()->associate($authentication->author); - $submission->submitted_at = now(); + $authentication->delete(); - $submission->save(); + $submission->submitted_at = now(); - $authentication->author->update(['status' => $request->get('attending') === 'yes' ? EventAttendeeStatus::Attending : EventAttendeeStatus::NotAttending]); + $submission->attendee_status = $request->get('attending') === 'yes' ? EventAttendeeStatus::Attending : EventAttendeeStatus::NotAttending; - $data = $validator->validated(); + $submission->save(); - // TODO: change the EventFormSubmission to have a column to store the attending data item + $authentication->author->update(['status' => $request->get('attending') === 'yes' ? EventAttendeeStatus::Attending : EventAttendeeStatus::NotAttending]); - if ($data['attending'] === 'yes') { - unset($data['recaptcha-token'], $data['attending']); + $data = $validator->validated(); - if ($form->is_wizard) { - foreach ($form->steps as $step) { - foreach ($data[$step->label] as $fieldId => $response) { + if ($data['attending'] === 'yes') { + unset($data['recaptcha-token']); + + if ($form->is_wizard) { + foreach ($form->steps as $step) { + foreach ($data[$step->label] as $fieldId => $response) { + $submission->fields()->attach( + $fieldId, + ['id' => Str::orderedUuid(), 'response' => $response], + ); + } + } + } else { + foreach ($data as $fieldId => $response) { $submission->fields()->attach( $fieldId, ['id' => Str::orderedUuid(), 'response' => $response], ); } } - } else { - foreach ($data as $fieldId => $response) { - $submission->fields()->attach( - $fieldId, - ['id' => Str::orderedUuid(), 'response' => $response], - ); - } + + $submission->save(); } - $submission->save(); + DB::commit(); + } catch (Exception $e) { + // TODO: Tag and report this exception. Send the tag to the frontend as a reference. + + DB::rollBack(); + + throw $e; } return response()->json( diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php index 35fdd58213..2c6aba5124 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php @@ -41,6 +41,7 @@ use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Form\Enums\FormSubmissionStatus; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use AdvisingApp\Form\Enums\FormSubmissionRequestDeliveryMethod; @@ -52,6 +53,7 @@ class EventRegistrationFormSubmission extends Submission protected $fillable = [ 'canceled_at', 'form_id', + 'attendee_status', 'request_method', 'request_note', 'submitted_at', @@ -61,6 +63,7 @@ class EventRegistrationFormSubmission extends Submission 'submitted_at' => 'immutable_datetime', 'canceled_at' => 'immutable_datetime', 'request_method' => FormSubmissionRequestDeliveryMethod::class, + 'attendee_status' => EventAttendeeStatus::class, ]; public function submissible(): BelongsTo diff --git a/widgets/event-registration/src/App.vue b/widgets/event-registration/src/App.vue index 78579b05e8..da5a68bd65 100644 --- a/widgets/event-registration/src/App.vue +++ b/widgets/event-registration/src/App.vue @@ -93,10 +93,15 @@ const data = reactive({ }, body: JSON.stringify(data), }) - .then((response) => response.json()) - .then((json) => { - if (json.errors) { - node.setErrors([], json.errors); + .then((response) => { + if (response.status === 500) { + node.setErrors(['An error occurred while submitting the form. Please try again later.']); + + return; + } + + if (response.json().errors) { + node.setErrors([], response.json().errors); return; } From a82e69c31bc68d54d4f6678c3130b6b5b1850712 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 15:56:26 -0500 Subject: [PATCH 042/152] Remove todo Signed-off-by: Kevin Ullyott --- .../src/Http/Controllers/EventRegistrationWidgetController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index bae23c1cbd..bc9d4fe1d2 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -69,7 +69,6 @@ public function view(GenerateFormKitSchema $generateSchema, Event $event): JsonR [ 'name' => $form->event->title, 'description' => $form->event->description, - // TODO: Maybe get rid of this? It would never not be authenticated. 'is_authenticated' => true, 'authentication_url' => URL::signedRoute('event-registration.request-authentication', ['event' => $event]), 'recaptcha_enabled' => $form->recaptcha_enabled, From 9b4da51a3360e01bbc08ce526c6d0d7304ea226d Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 16:00:34 -0500 Subject: [PATCH 043/152] Split the generation logic Signed-off-by: Kevin Ullyott --- .../src/Actions/GenerateFormKitSchema.php | 60 ++++++------------- ...GenerateEventRegistrationFormKitSchema.php | 57 ++++++++++++++++++ .../EventRegistrationWidgetController.php | 4 +- 3 files changed, 77 insertions(+), 44 deletions(-) create mode 100644 app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index f9f19e2ede..42168bffb5 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -44,6 +44,23 @@ class GenerateFormKitSchema { public function __invoke(Submissible $submissible): array + { + $content = $this->generateContent($submissible); + + return [ + '$cmp' => 'FormKit', + 'props' => [ + 'type' => 'form', + 'id' => 'form', + 'onSubmit' => '$submitForm', + 'plugins' => '$plugins', + 'actions' => false, + ], + 'children' => $content, + ]; + } + + public function generateContent(Submissible $submissible): array { if ($submissible->is_wizard) { $submissible->loadMissing([ @@ -68,48 +85,7 @@ public function __invoke(Submissible $submissible): array ]; } - $content = [ - [ - '$formkit' => 'radio', - 'label' => 'Will you be attending?', - 'id' => 'attending', - 'name' => 'attending', - 'options' => [ - [ - 'label' => 'Yes', - 'value' => 'yes', - ], - [ - 'label' => 'No', - 'value' => 'no', - ], - ], - 'validation' => 'required', - ], - [ - '$el' => 'div', - 'if' => '$get(attending).value === "yes"', - 'children' => $content, - ], - [ - '$formkit' => 'submit', - 'if' => '$get(attending).value === "no"', - 'label' => 'Submit', - 'disabled' => '$get(form).state.valid !== true', - ], - ]; - - return [ - '$cmp' => 'FormKit', - 'props' => [ - 'type' => 'form', - 'id' => 'form', - 'onSubmit' => '$submitForm', - 'plugins' => '$plugins', - 'actions' => false, - ], - 'children' => $content, - ]; + return $content; } public function content(array $content, ?Collection $fields = null): array diff --git a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php new file mode 100644 index 0000000000..31adf39373 --- /dev/null +++ b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php @@ -0,0 +1,57 @@ +generateContent($submissible); + + $content = [ + [ + '$formkit' => 'radio', + 'label' => 'Will you be attending?', + 'id' => 'attending', + 'name' => 'attending', + 'options' => [ + [ + 'label' => 'Yes', + 'value' => 'yes', + ], + [ + 'label' => 'No', + 'value' => 'no', + ], + ], + 'validation' => 'required', + ], + [ + '$el' => 'div', + 'if' => '$get(attending).value === "yes"', + 'children' => $content, + ], + [ + '$formkit' => 'submit', + 'if' => '$get(attending).value === "no"', + 'label' => 'Submit', + 'disabled' => '$get(form).state.valid !== true', + ], + ]; + + return [ + '$cmp' => 'FormKit', + 'props' => [ + 'type' => 'form', + 'id' => 'form', + 'onSubmit' => '$submitForm', + 'plugins' => '$plugins', + 'actions' => false, + ], + 'children' => $content, + ]; + } +} \ No newline at end of file diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index bc9d4fe1d2..898e656280 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -50,18 +50,18 @@ use AdvisingApp\MeetingCenter\Models\Event; use Illuminate\Support\Facades\Notification; use Symfony\Component\HttpFoundation\Response; -use AdvisingApp\Form\Actions\GenerateFormKitSchema; use AdvisingApp\MeetingCenter\Models\EventAttendee; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; +use AdvisingApp\MeetingCenter\Actions\GenerateEventRegistrationFormKitSchema; use AdvisingApp\MeetingCenter\Notifications\AuthenticateEventRegistrationFormNotification; class EventRegistrationWidgetController extends Controller { - public function view(GenerateFormKitSchema $generateSchema, Event $event): JsonResponse + public function view(GenerateEventRegistrationFormKitSchema $generateSchema, Event $event): JsonResponse { $form = $event->eventRegistrationForm; From 8cab069f1fe00ac33ab5ac2408d0be6421150dcd Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 16:07:36 -0500 Subject: [PATCH 044/152] Fix bug with multistep Signed-off-by: Kevin Ullyott --- .../Pages/Concerns/HasSharedEventFormConfiguration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php index f3de80786e..15f123c68b 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php @@ -151,7 +151,7 @@ public function fieldBuilder(): TiptapEditor $form = $record instanceof EventRegistrationForm ? $record : $record->submissible; $formStep = $record instanceof EventRegistrationFormStep ? $record : null; - EventRegistrationFormStep::query() + EventRegistrationFormField::query() ->whereBelongsTo($form, 'submissible') ->when($formStep, fn (EloquentBuilder $query) => $query->whereBelongsTo($formStep, 'step')) ->delete(); From a2169c0ef912140ab75febb4f23606df54dc2699 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 16:39:14 -0500 Subject: [PATCH 045/152] Init viewing event attendees Signed-off-by: Kevin Ullyott --- .../src/Enums/EventAttendeeStatus.php | 15 +++- .../src/Filament/Resources/EventResource.php | 12 +++ .../Pages/ManageEventAttendees.php | 88 +++++++++++++++++++ .../meeting-center/src/Models/Event.php | 6 ++ .../src/Models/EventAttendee.php | 6 ++ 5 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php diff --git a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php index f84db2a022..ba6ad0a674 100644 --- a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php +++ b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php @@ -2,7 +2,10 @@ namespace AdvisingApp\MeetingCenter\Enums; -enum EventAttendeeStatus: string +use Filament\Support\Contracts\HasColor; +use Filament\Support\Contracts\HasLabel; + +enum EventAttendeeStatus: string implements HasColor, HasLabel { case Invited = 'invited'; @@ -19,4 +22,14 @@ public function getLabel(): ?string default => $this->name, }; } + + public function getColor(): string + { + return match ($this) { + self::Invited => 'info', + self::Pending => 'warning', + self::Attending => 'success', + self::NotAttending => 'danger', + }; + } } diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource.php b/app-modules/meeting-center/src/Filament/Resources/EventResource.php index 57e54bee16..7f258955d0 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource.php @@ -37,11 +37,13 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources; use Filament\Resources\Resource; +use Filament\Resources\Pages\Page; use AdvisingApp\MeetingCenter\Models\Event; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\EditEvent; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\ViewEvent; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\ListEvents; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\CreateEvent; +use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\ManageEventAttendees; class EventResource extends Resource { @@ -58,6 +60,15 @@ public static function getRelations(): array return []; } + public static function getRecordSubNavigation(Page $page): array + { + return $page->generateNavigationItems([ + ViewEvent::class, + EditEvent::class, + ManageEventAttendees::class, + ]); + } + public static function getPages(): array { return [ @@ -65,6 +76,7 @@ public static function getPages(): array 'create' => CreateEvent::route('/create'), 'view' => ViewEvent::route('/{record}'), 'edit' => EditEvent::route('/{record}/edit'), + 'manage-attendees' => ManageEventAttendees::route('/{record}/manage-attendees'), ]; } } diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php new file mode 100644 index 0000000000..3ccd98b991 --- /dev/null +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -0,0 +1,88 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; + +use Filament\Tables\Table; +use App\Filament\Columns\IdColumn; +use Filament\Tables\Columns\TextColumn; +use Filament\Resources\Pages\ManageRelatedRecords; +use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; + +class ManageEventAttendees extends ManageRelatedRecords +{ + protected static string $resource = EventResource::class; + + // TODO: Obsolete when there is no table, remove from Filament + protected static string $relationship = 'attendees'; + + protected static ?string $navigationLabel = 'Attendees'; + + protected static ?string $breadcrumb = 'Attendees'; + + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + public function table(Table $table): Table + { + return $table + ->columns([ + IdColumn::make(), + TextColumn::make('status') + ->badge(), + TextColumn::make('email'), + ]) + ->filters([]) + ->headerActions([]) + ->actions([ + //ViewAction::make() + // ->modalHeading(fn (SurveySubmission $record) => 'Submission Details: ' . $record->submitted_at->format('M j, Y H:i:s')) + // ->infolist(fn (SurveySubmission $record): ?array => ($record->author && $record->submissible->is_authenticated) ? [ + // Section::make('Authenticated author') + // ->schema([ + // TextEntry::make('author.' . $record->author::displayNameKey()) + // ->label('Name'), + // TextEntry::make('author.email') + // ->label('Email address'), + // ]) + // ->columns(2), + // ] : null) + // ->modalContent(fn (SurveySubmission $record) => view('survey::submission', ['submission' => $record])) + // ->visible(fn (SurveySubmission $record) => $record->submitted_at), + //DeleteAction::make(), + ]) + ->bulkActions([]); + } +} diff --git a/app-modules/meeting-center/src/Models/Event.php b/app-modules/meeting-center/src/Models/Event.php index e19a7706e9..4dba05b52f 100644 --- a/app-modules/meeting-center/src/Models/Event.php +++ b/app-modules/meeting-center/src/Models/Event.php @@ -38,6 +38,7 @@ use App\Models\BaseModel; use Illuminate\Database\Eloquent\Relations\HasOne; +use Illuminate\Database\Eloquent\Relations\HasMany; /** * @mixin IdeHelperEvent @@ -62,4 +63,9 @@ public function eventRegistrationForm(): HasOne { return $this->hasOne(EventRegistrationForm::class, 'event_id'); } + + public function attendees(): HasMany + { + return $this->hasMany(EventAttendee::class, 'event_id'); + } } diff --git a/app-modules/meeting-center/src/Models/EventAttendee.php b/app-modules/meeting-center/src/Models/EventAttendee.php index fab1a5c640..f3c957ad13 100644 --- a/app-modules/meeting-center/src/Models/EventAttendee.php +++ b/app-modules/meeting-center/src/Models/EventAttendee.php @@ -39,6 +39,7 @@ use App\Models\BaseModel; use App\Models\Attributes\NoPermissions; use Illuminate\Notifications\Notifiable; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; #[NoPermissions] @@ -58,4 +59,9 @@ class EventAttendee extends BaseModel protected $casts = [ 'status' => EventAttendeeStatus::class, ]; + + public function event(): BelongsTo + { + return $this->belongsTo(Event::class, 'event_id'); + } } From 1eadc9929c06b2acaaeea925100d22ad4bf2e7ef Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 16:44:14 -0500 Subject: [PATCH 046/152] More work on Attendee Signed-off-by: Kevin Ullyott --- .../Pages/ManageEventAttendees.php | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php index 3ccd98b991..f64949509c 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -38,8 +38,12 @@ use Filament\Tables\Table; use App\Filament\Columns\IdColumn; +use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; +use Filament\Infolists\Components\Section; +use Filament\Infolists\Components\TextEntry; use Filament\Resources\Pages\ManageRelatedRecords; +use AdvisingApp\MeetingCenter\Models\EventAttendee; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; class ManageEventAttendees extends ManageRelatedRecords @@ -67,21 +71,21 @@ public function table(Table $table): Table ->filters([]) ->headerActions([]) ->actions([ - //ViewAction::make() - // ->modalHeading(fn (SurveySubmission $record) => 'Submission Details: ' . $record->submitted_at->format('M j, Y H:i:s')) - // ->infolist(fn (SurveySubmission $record): ?array => ($record->author && $record->submissible->is_authenticated) ? [ - // Section::make('Authenticated author') - // ->schema([ - // TextEntry::make('author.' . $record->author::displayNameKey()) - // ->label('Name'), - // TextEntry::make('author.email') - // ->label('Email address'), - // ]) - // ->columns(2), - // ] : null) - // ->modalContent(fn (SurveySubmission $record) => view('survey::submission', ['submission' => $record])) - // ->visible(fn (SurveySubmission $record) => $record->submitted_at), - //DeleteAction::make(), + ViewAction::make() + ->modalHeading(fn (EventAttendee $record) => $record->event->title . ' - ' . $record->email) + ->infolist(fn (EventAttendee $record): array => [ + Section::make('Attendee Info') + ->schema([ + TextEntry::make('status') + ->label('Status') + ->badge(), + TextEntry::make('email') + ->label('Email address'), + ]) + ->columns(), + ]), + // TODO: Display this Attendees submissions + //->modalContent(fn (EventAttendee $record) => view('survey::submission', ['submission' => $record])), ]) ->bulkActions([]); } From f6c312fb4c72bf299a7490a023aa2cf7579bc629 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 13:59:21 -0500 Subject: [PATCH 047/152] Fix bug Signed-off-by: Kevin Ullyott --- .../src/Http/Controllers/EventRegistrationWidgetController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index 898e656280..b1c816251e 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -206,7 +206,7 @@ public function store( $data = $validator->validated(); if ($data['attending'] === 'yes') { - unset($data['recaptcha-token']); + unset($data['recaptcha-token'], $data['attending']); if ($form->is_wizard) { foreach ($form->steps as $step) { From 32bccb8dbdc489a025e831615dd3b1ab7da8403b Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 14:57:22 -0500 Subject: [PATCH 048/152] Start displaying the attendee submission Signed-off-by: Kevin Ullyott --- ...ent-attendee-submissions-manager.blade.php | 3 + .../Pages/ManageEventAttendees.php | 4 ++ .../EventAttendeeSubmissionsManager.php | 60 +++++++++++++++++++ .../src/Models/EventAttendee.php | 6 ++ .../EventRegistrationFormSubmission.php | 45 -------------- .../MeetingCenterServiceProvider.php | 4 ++ 6 files changed, 77 insertions(+), 45 deletions(-) create mode 100644 app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php create mode 100644 app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php diff --git a/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php b/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php new file mode 100644 index 0000000000..c3fedc4aac --- /dev/null +++ b/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php @@ -0,0 +1,3 @@ +
+ {{ $this->table }} +
diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php index f64949509c..ef9922f12c 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -41,6 +41,7 @@ use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; use Filament\Infolists\Components\Section; +use Filament\Infolists\Components\Livewire; use Filament\Infolists\Components\TextEntry; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\MeetingCenter\Models\EventAttendee; @@ -83,6 +84,9 @@ public function table(Table $table): Table ->label('Email address'), ]) ->columns(), + // TODO: Look into Livewire/Filament bug that prevents us from passing the class here, requiring that we define it in the Service Provider + // TODO: Look into bug where, without lazy load, you have to click view twice to get the modal to show + Livewire::make('event-attendee-submissions-manager')->lazy(), ]), // TODO: Display this Attendees submissions //->modalContent(fn (EventAttendee $record) => view('survey::submission', ['submission' => $record])), diff --git a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php new file mode 100644 index 0000000000..211f87bc04 --- /dev/null +++ b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php @@ -0,0 +1,60 @@ +relationship(fn (): HasMany => $this->record->submissions()) + ->inverseRelationship('author') + ->columns([ + TextColumn::make('attendee_status') + ->badge(), + ]) + ->filters([ + // ... + ]) + ->actions([ + ViewAction::make() + ->modalHeading(fn (EventRegistrationFormSubmission $record) => 'Submission Details: ' . $record->submitted_at->format('M j, Y H:i:s')) + ->infolist(fn (EventRegistrationFormSubmission $record): array => [ + Section::make('Authenticated author') + ->schema([ + TextEntry::make('author.email') + ->label('Email Address'), + ]) + ->columns(), + ]), + //->modalContent(fn (FormSubmission $record) => view('form::submission', ['submission' => $record])), + ]) + ->bulkActions([ + // ... + ]); + } +} diff --git a/app-modules/meeting-center/src/Models/EventAttendee.php b/app-modules/meeting-center/src/Models/EventAttendee.php index f3c957ad13..3564fc7334 100644 --- a/app-modules/meeting-center/src/Models/EventAttendee.php +++ b/app-modules/meeting-center/src/Models/EventAttendee.php @@ -39,6 +39,7 @@ use App\Models\BaseModel; use App\Models\Attributes\NoPermissions; use Illuminate\Notifications\Notifiable; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; @@ -64,4 +65,9 @@ public function event(): BelongsTo { return $this->belongsTo(Event::class, 'event_id'); } + + public function submissions(): HasMany + { + return $this->hasMany(EventRegistrationFormSubmission::class, 'event_attendee_id'); + } } diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php index 2c6aba5124..75d629a0e1 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php @@ -38,8 +38,6 @@ use App\Models\User; use AdvisingApp\Form\Models\Submission; -use Illuminate\Database\Eloquent\Builder; -use AdvisingApp\Form\Enums\FormSubmissionStatus; use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -92,47 +90,4 @@ public function author(): BelongsTo { return $this->belongsTo(EventAttendee::class, 'event_attendee_id'); } - - public function deliverRequest(): void - { - $this->request_method->deliver($this); - } - - public function scopeRequested(Builder $query): Builder - { - return $query->notSubmitted()->notCanceled(); - } - - public function scopeSubmitted(Builder $query): Builder - { - return $query->whereNotNull('submitted_at'); - } - - public function scopeCanceled(Builder $query): Builder - { - return $query->notSubmitted()->whereNotNull('canceled_at'); - } - - public function scopeNotSubmitted(Builder $query): Builder - { - return $query->whereNull('submitted_at'); - } - - public function scopeNotCanceled(Builder $query): Builder - { - return $query->whereNull('canceled_at'); - } - - public function getStatus(): FormSubmissionStatus - { - if ($this->submitted_at) { - return FormSubmissionStatus::Submitted; - } - - if ($this->canceled_at) { - return FormSubmissionStatus::Canceled; - } - - return FormSubmissionStatus::Requested; - } } diff --git a/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php b/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php index bc5e36b29c..e3dc80d32a 100644 --- a/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php +++ b/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php @@ -37,6 +37,7 @@ namespace AdvisingApp\MeetingCenter\Providers; use Filament\Panel; +use Livewire\Livewire; use Illuminate\Support\ServiceProvider; use AdvisingApp\MeetingCenter\Models\Event; use Illuminate\Console\Scheduling\Schedule; @@ -53,6 +54,7 @@ use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; +use AdvisingApp\MeetingCenter\Livewire\EventAttendeeSubmissionsManager; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; class MeetingCenterServiceProvider extends ServiceProvider @@ -86,6 +88,8 @@ public function boot(): void $this->registerRolesAndPermissions(); $this->registerObservers(); + + Livewire::component('event-attendee-submissions-manager', EventAttendeeSubmissionsManager::class); } protected function registerRolesAndPermissions(): void From a3276575e83b87be6658677c27380fb1d8a36fd9 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 15:16:46 -0500 Subject: [PATCH 049/152] Display an attendees submissions Signed-off-by: Kevin Ullyott --- .../event-registration-submission.blade.php | 55 +++++++++++++++++++ .../Pages/ManageEventAttendees.php | 17 +++--- .../EventAttendeeSubmissionsManager.php | 23 ++++---- 3 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 app-modules/meeting-center/resources/views/event-registration-submission.blade.php diff --git a/app-modules/meeting-center/resources/views/event-registration-submission.blade.php b/app-modules/meeting-center/resources/views/event-registration-submission.blade.php new file mode 100644 index 0000000000..2756746379 --- /dev/null +++ b/app-modules/meeting-center/resources/views/event-registration-submission.blade.php @@ -0,0 +1,55 @@ +{{-- + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +--}} + +
+ @if ($submission->submissible->is_wizard) + @foreach ($submission->submissible->steps as $step) + + + {{ $step->label }} + + + + + @endforeach + @else + + @endif +
diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php index ef9922f12c..a228570e01 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -40,7 +40,7 @@ use App\Filament\Columns\IdColumn; use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; -use Filament\Infolists\Components\Section; +use Filament\Infolists\Components\Fieldset; use Filament\Infolists\Components\Livewire; use Filament\Infolists\Components\TextEntry; use Filament\Resources\Pages\ManageRelatedRecords; @@ -75,7 +75,7 @@ public function table(Table $table): Table ViewAction::make() ->modalHeading(fn (EventAttendee $record) => $record->event->title . ' - ' . $record->email) ->infolist(fn (EventAttendee $record): array => [ - Section::make('Attendee Info') + Fieldset::make('Attendee Info') ->schema([ TextEntry::make('status') ->label('Status') @@ -84,12 +84,15 @@ public function table(Table $table): Table ->label('Email address'), ]) ->columns(), - // TODO: Look into Livewire/Filament bug that prevents us from passing the class here, requiring that we define it in the Service Provider - // TODO: Look into bug where, without lazy load, you have to click view twice to get the modal to show - Livewire::make('event-attendee-submissions-manager')->lazy(), + + Fieldset::make('Attendee Submissions') + ->schema([ + // TODO: Look into Livewire/Filament bug that prevents us from passing the class here, requiring that we define it in the Service Provider + // TODO: Look into bug where, without lazy load, you have to click view twice to get the modal to show + Livewire::make('event-attendee-submissions-manager')->lazy() + ->columnSpanFull(), + ]), ]), - // TODO: Display this Attendees submissions - //->modalContent(fn (EventAttendee $record) => view('survey::submission', ['submission' => $record])), ]) ->bulkActions([]); } diff --git a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php index 211f87bc04..91a41825ad 100644 --- a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php +++ b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php @@ -34,27 +34,30 @@ public function table(Table $table): Table ->relationship(fn (): HasMany => $this->record->submissions()) ->inverseRelationship('author') ->columns([ + TextColumn::make('submitted_at') + ->label('Submitted At') + ->dateTime() + ->sortable(), TextColumn::make('attendee_status') + ->label('Submission Status') ->badge(), ]) - ->filters([ - // ... - ]) + ->defaultSort('submitted_at', 'desc') ->actions([ ViewAction::make() ->modalHeading(fn (EventRegistrationFormSubmission $record) => 'Submission Details: ' . $record->submitted_at->format('M j, Y H:i:s')) ->infolist(fn (EventRegistrationFormSubmission $record): array => [ - Section::make('Authenticated author') + Section::make('Metadata') ->schema([ TextEntry::make('author.email') - ->label('Email Address'), + ->label('Author Email Address'), + TextEntry::make('attendee_status') + ->label('Submission Status') + ->badge(), ]) ->columns(), - ]), - //->modalContent(fn (FormSubmission $record) => view('form::submission', ['submission' => $record])), - ]) - ->bulkActions([ - // ... + ]) + ->modalContent(fn (EventRegistrationFormSubmission $record) => view('meeting-center::event-registration-submission', ['submission' => $record])), ]); } } From c99e763b23603f8922c93f4e846e1ed89e752044 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 15:53:14 -0500 Subject: [PATCH 050/152] Relate a Student or Prospect to an EventAttendee Signed-off-by: Kevin Ullyott --- .../Pages/ManageEventAttendees.php | 29 +++++++++++++++++++ .../src/Models/EventAttendee.php | 20 +++++++++++++ 2 files changed, 49 insertions(+) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php index a228570e01..dc7cc511f5 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -40,12 +40,17 @@ use App\Filament\Columns\IdColumn; use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; +use AdvisingApp\Prospect\Models\Prospect; use Filament\Infolists\Components\Fieldset; use Filament\Infolists\Components\Livewire; use Filament\Infolists\Components\TextEntry; +use AdvisingApp\StudentDataModel\Models\Student; +use Filament\Infolists\Components\RepeatableEntry; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\MeetingCenter\Models\EventAttendee; +use AdvisingApp\Prospect\Filament\Resources\ProspectResource; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; +use AdvisingApp\StudentDataModel\Filament\Resources\StudentResource; class ManageEventAttendees extends ManageRelatedRecords { @@ -85,6 +90,30 @@ public function table(Table $table): Table ]) ->columns(), + Fieldset::make('Relations') + ->schema([ + RepeatableEntry::make('prospects') + ->schema([ + TextEntry::make(Prospect::displayNameKey()) + ->label('Name') + ->color('primary') + ->url(fn (Prospect $record): string => ProspectResource::getUrl('view', ['record' => $record])), + ]) + ->columns() + ->visible(fn (EventAttendee $record): bool => $record->prospects->isNotEmpty()), + RepeatableEntry::make('students') + ->schema([ + TextEntry::make(Student::displayNameKey()) + ->label('Name') + ->color('primary') + ->url(fn (Student $record): string => StudentResource::getUrl('view', ['record' => $record])), + ]) + ->columns() + ->visible(fn (EventAttendee $record): bool => $record->students->isNotEmpty()), + ]) + ->visible(fn (EventAttendee $record): bool => $record->prospects->isNotEmpty() || $record->students->isNotEmpty()) + ->columns(), + Fieldset::make('Attendee Submissions') ->schema([ // TODO: Look into Livewire/Filament bug that prevents us from passing the class here, requiring that we define it in the Service Provider diff --git a/app-modules/meeting-center/src/Models/EventAttendee.php b/app-modules/meeting-center/src/Models/EventAttendee.php index 3564fc7334..9590bae852 100644 --- a/app-modules/meeting-center/src/Models/EventAttendee.php +++ b/app-modules/meeting-center/src/Models/EventAttendee.php @@ -39,6 +39,8 @@ use App\Models\BaseModel; use App\Models\Attributes\NoPermissions; use Illuminate\Notifications\Notifiable; +use AdvisingApp\Prospect\Models\Prospect; +use AdvisingApp\StudentDataModel\Models\Student; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; @@ -70,4 +72,22 @@ public function submissions(): HasMany { return $this->hasMany(EventRegistrationFormSubmission::class, 'event_attendee_id'); } + + public function prospects(): HasMany + { + return $this->hasMany( + related: Prospect::class, + foreignKey: 'email', + localKey: 'email', + ); + } + + public function students(): HasMany + { + return $this->hasMany( + related: Student::class, + foreignKey: 'email', + localKey: 'email', + ); + } } From c6300b7c01b84eb6f943e0a9f1ad3a879f797d9e Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 16:39:38 -0500 Subject: [PATCH 051/152] Clear out unneded columns Signed-off-by: Kevin Ullyott --- ...94229_create_event_registration_form_submissions_table.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php index 2b362933c9..af7df1dc37 100644 --- a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php @@ -48,10 +48,6 @@ public function up(): void $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); $table->string('attendee_status'); $table->timestamp('submitted_at')->nullable(); - $table->timestamp('canceled_at')->nullable(); - $table->string('request_method')->nullable(); - $table->text('request_note')->nullable(); - $table->foreignUuid('requester_id')->nullable()->constrained('users')->nullOnDelete(); $table->timestamps(); $table->softDeletes(); From fb92eef00a18c1d3bc565d91c1f46b540b6027f2 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 16:44:03 -0500 Subject: [PATCH 052/152] composer update Signed-off-by: Kevin Ullyott --- composer.lock | 145 +++++++++++++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 55 deletions(-) diff --git a/composer.lock b/composer.lock index 029ba3e12f..ba8789147b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a7c988d45a8bf04ea377069a6dd7b23a", + "content-hash": "19b34ef965a1ec4aa7ec0deb038e20bd", "packages": [ { "name": "amphp/amp", @@ -559,16 +559,16 @@ }, { "name": "awcodes/filament-tiptap-editor", - "version": "v3.2.17", + "version": "v3.2.18", "source": { "type": "git", "url": "https://github.com/awcodes/filament-tiptap-editor.git", - "reference": "0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f" + "reference": "7de016e723ba62908f979a39204955e1801b0967" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f", - "reference": "0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f", + "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/7de016e723ba62908f979a39204955e1801b0967", + "reference": "7de016e723ba62908f979a39204955e1801b0967", "shasum": "" }, "require": { @@ -630,7 +630,7 @@ ], "support": { "issues": "https://github.com/awcodes/filament-tiptap-editor/issues", - "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.17" + "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.18" }, "funding": [ { @@ -638,7 +638,7 @@ "type": "github" } ], - "time": "2023-12-27T19:10:56+00:00" + "time": "2023-12-28T20:05:06+00:00" }, { "name": "aws/aws-crt-php", @@ -755,16 +755,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.295.2", + "version": "3.295.4", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73" + "reference": "2372661db989fe4229abd95f4434b37252076d58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73", - "reference": "7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2372661db989fe4229abd95f4434b37252076d58", + "reference": "2372661db989fe4229abd95f4434b37252076d58", "shasum": "" }, "require": { @@ -844,9 +844,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.295.2" + "source": "https://github.com/aws/aws-sdk-php/tree/3.295.4" }, - "time": "2023-12-27T19:06:10+00:00" + "time": "2023-12-29T19:07:49+00:00" }, { "name": "barryvdh/laravel-debugbar", @@ -2379,6 +2379,41 @@ "relative": true } }, + { + "name": "canyon-gbs/inventory-management", + "version": "1.0", + "dist": { + "type": "path", + "url": "app-modules/inventory-management", + "reference": "16210c789f3a6d5a4b14ce0db3a17f5cdc4f6e48" + }, + "require": { + "filament/filament": "^3.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "AdvisingApp\\InventoryManagement\\Providers\\InventoryManagementServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "AdvisingApp\\InventoryManagement\\": "src/", + "AdvisingApp\\InventoryManagement\\Tests\\": "tests/", + "AdvisingApp\\InventoryManagement\\Database\\Factories\\": "database/factories/", + "AdvisingApp\\InventoryManagement\\Database\\Seeders\\": "database/seeders/" + } + }, + "license": [ + "proprietary" + ], + "transport-options": { + "symlink": true, + "relative": true + } + }, { "name": "carbonphp/carbon-doctrine-types", "version": "2.1.0", @@ -4071,7 +4106,7 @@ }, { "name": "filament/actions", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", @@ -4122,7 +4157,7 @@ }, { "name": "filament/filament", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", @@ -4187,7 +4222,7 @@ }, { "name": "filament/forms", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", @@ -4243,7 +4278,7 @@ }, { "name": "filament/infolists", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", @@ -4294,7 +4329,7 @@ }, { "name": "filament/notifications", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", @@ -4346,7 +4381,7 @@ }, { "name": "filament/spatie-laravel-media-library-plugin", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-media-library-plugin.git", @@ -4383,7 +4418,7 @@ }, { "name": "filament/spatie-laravel-settings-plugin", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-settings-plugin.git", @@ -4430,7 +4465,7 @@ }, { "name": "filament/support", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", @@ -4487,16 +4522,16 @@ }, { "name": "filament/tables", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67" + "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67", - "reference": "ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/e0701467097f6a82b235ad9f31e3c30ae1035118", + "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118", "shasum": "" }, "require": { @@ -4536,20 +4571,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:29+00:00" + "time": "2023-12-28T17:31:59+00:00" }, { "name": "filament/widgets", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "7195d2fe7d12a9b9595fa445a4dbedd6d7714836" + "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/7195d2fe7d12a9b9595fa445a4dbedd6d7714836", - "reference": "7195d2fe7d12a9b9595fa445a4dbedd6d7714836", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", + "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", "shasum": "" }, "require": { @@ -4580,7 +4615,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-24T21:17:06+00:00" + "time": "2023-12-28T17:31:57+00:00" }, { "name": "firebase/php-jwt", @@ -10161,16 +10196,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.34", + "version": "3.0.35", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "56c79f16a6ae17e42089c06a2144467acc35348a" + "reference": "4b1827beabce71953ca479485c0ae9c51287f2fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56c79f16a6ae17e42089c06a2144467acc35348a", - "reference": "56c79f16a6ae17e42089c06a2144467acc35348a", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4b1827beabce71953ca479485c0ae9c51287f2fe", + "reference": "4b1827beabce71953ca479485c0ae9c51287f2fe", "shasum": "" }, "require": { @@ -10251,7 +10286,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.34" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.35" }, "funding": [ { @@ -10267,7 +10302,7 @@ "type": "tidelift" } ], - "time": "2023-11-27T11:13:31+00:00" + "time": "2023-12-29T01:59:53+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -17148,16 +17183,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.42.0", + "version": "v3.44.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "632ef1be3447a9b890bef06147475facee535d0f" + "reference": "5445834057a744c1a434ed60fcac566b4de3a0f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/632ef1be3447a9b890bef06147475facee535d0f", - "reference": "632ef1be3447a9b890bef06147475facee535d0f", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/5445834057a744c1a434ed60fcac566b4de3a0f2", + "reference": "5445834057a744c1a434ed60fcac566b4de3a0f2", "shasum": "" }, "require": { @@ -17187,7 +17222,7 @@ "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^9.6 || ^10.5.5", "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { @@ -17226,7 +17261,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.42.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.44.0" }, "funding": [ { @@ -17234,7 +17269,7 @@ "type": "github" } ], - "time": "2023-12-24T14:38:51+00:00" + "time": "2023-12-29T20:21:16+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -20765,28 +20800,28 @@ }, { "name": "ta-tikoma/phpunit-architecture-test", - "version": "0.7.5", + "version": "0.7.6", "source": { "type": "git", "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", - "reference": "9eb08437e8f0c0c75cc947a373cf49672c335827" + "reference": "a252cd9488fd62f3c8c6cafa303b1b96e9df24e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/9eb08437e8f0c0c75cc947a373cf49672c335827", - "reference": "9eb08437e8f0c0c75cc947a373cf49672c335827", + "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/a252cd9488fd62f3c8c6cafa303b1b96e9df24e0", + "reference": "a252cd9488fd62f3c8c6cafa303b1b96e9df24e0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.15.4", + "nikic/php-parser": "^4.18.0", "php": "^8.1.0", "phpdocumentor/reflection-docblock": "^5.3.0", - "phpunit/phpunit": "^10.1.1", - "symfony/finder": "^6.2.7 || ^7.0.0" + "phpunit/phpunit": "^10.5.5", + "symfony/finder": "^6.4.0 || ^7.0.0" }, "require-dev": { - "laravel/pint": "^1.9.0", - "phpstan/phpstan": "^1.10.13" + "laravel/pint": "^1.13.7", + "phpstan/phpstan": "^1.10.50" }, "type": "library", "autoload": { @@ -20818,9 +20853,9 @@ ], "support": { "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues", - "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.7.5" + "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.7.6" }, - "time": "2023-10-12T15:31:50+00:00" + "time": "2023-12-29T13:14:58+00:00" }, { "name": "theseer/tokenizer", From b71d7f212500d03cb5304d7d9ef1a7972a4b9a4f Mon Sep 17 00:00:00 2001 From: Orrison Date: Fri, 29 Dec 2023 21:45:41 +0000 Subject: [PATCH 053/152] chore: fix enforcement of copyright on all files --- ...ent-attendee-submissions-manager.blade.php | 33 ++++++++++++++++++ ...GenerateEventRegistrationFormKitSchema.php | 34 +++++++++++++++++++ .../src/Enums/EventAttendeeStatus.php | 34 +++++++++++++++++++ .../HasSharedEventFormConfiguration.php | 34 +++++++++++++++++++ .../EventAttendeeSubmissionsManager.php | 34 +++++++++++++++++++ 5 files changed, 169 insertions(+) diff --git a/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php b/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php index c3fedc4aac..9c8071e9c4 100644 --- a/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php +++ b/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php @@ -1,3 +1,36 @@ +{{-- + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +--}}
{{ $this->table }}
diff --git a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php index 31adf39373..abea705568 100644 --- a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php +++ b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\MeetingCenter\Actions; use AdvisingApp\Form\Models\Submissible; diff --git a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php index ba6ad0a674..407f84ae5e 100644 --- a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php +++ b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\MeetingCenter\Enums; use Filament\Support\Contracts\HasColor; diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php index 15f123c68b..fb5f1f5ce4 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\Concerns; use App\Models\User; diff --git a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php index 91a41825ad..a93aecee71 100644 --- a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php +++ b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\MeetingCenter\Livewire; use Livewire\Component; From 7f18805ccc1d6dd719467428295e98e5eb70e14c Mon Sep 17 00:00:00 2001 From: joelicatajr Date: Fri, 29 Dec 2023 21:49:05 +0000 Subject: [PATCH 054/152] chore: fix code style --- .../src/Actions/GenerateEventRegistrationFormKitSchema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php index abea705568..49ea7c3720 100644 --- a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php +++ b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php @@ -88,4 +88,4 @@ public function __invoke(Submissible $submissible): array 'children' => $content, ]; } -} \ No newline at end of file +} From bb401ee370552df7cb98473c903d61921bf9c882 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 12:02:17 -0500 Subject: [PATCH 055/152] PR Feedback Signed-off-by: Kevin Ullyott --- .../src/Actions/GenerateFormKitSchema.php | 60 +++++++++-------- .../src/Models/SubmissibleAuthentication.php | 3 +- app-modules/form/src/Models/Submission.php | 3 +- ...GenerateEventRegistrationFormKitSchema.php | 64 +++++++++---------- 4 files changed, 61 insertions(+), 69 deletions(-) diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index 42168bffb5..f51dbc2029 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -45,8 +45,6 @@ class GenerateFormKitSchema { public function __invoke(Submissible $submissible): array { - $content = $this->generateContent($submissible); - return [ '$cmp' => 'FormKit', 'props' => [ @@ -56,38 +54,10 @@ public function __invoke(Submissible $submissible): array 'plugins' => '$plugins', 'actions' => false, ], - 'children' => $content, + 'children' => $this->generateContent($submissible), ]; } - public function generateContent(Submissible $submissible): array - { - if ($submissible->is_wizard) { - $submissible->loadMissing([ - 'steps' => [ - 'fields', - ], - ]); - - $content = $this->wizardContent($submissible); - } else { - $submissible->loadMissing([ - 'fields', - ]); - - $content = [ - ...$this->content($submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), - [ - '$formkit' => 'submit', - 'label' => 'Submit', - 'disabled' => '$get(form).state.valid !== true', - ], - ]; - } - - return $content; - } - public function content(array $content, ?Collection $fields = null): array { $blocks = FormFieldBlockRegistry::keyByType(); @@ -278,4 +248,32 @@ public function wizardContent(Submissible $submissible): array ], ]; } + + protected function generateContent(Submissible $submissible): array + { + if ($submissible->is_wizard) { + $submissible->loadMissing([ + 'steps' => [ + 'fields', + ], + ]); + + $content = $this->wizardContent($submissible); + } else { + $submissible->loadMissing([ + 'fields', + ]); + + $content = [ + ...$this->content($submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), + [ + '$formkit' => 'submit', + 'label' => 'Submit', + 'disabled' => '$get(form).state.valid !== true', + ], + ]; + } + + return $content; + } } diff --git a/app-modules/form/src/Models/SubmissibleAuthentication.php b/app-modules/form/src/Models/SubmissibleAuthentication.php index b5a0360f6f..3d6bb26158 100644 --- a/app-modules/form/src/Models/SubmissibleAuthentication.php +++ b/app-modules/form/src/Models/SubmissibleAuthentication.php @@ -41,7 +41,6 @@ use App\Models\Attributes\NoPermissions; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\MassPrunable; -use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** @@ -66,7 +65,7 @@ public function prunable(): Builder ->where('created_at', '<', now()->subMonth()); } - public function author(): MorphTo|BelongsTo + public function author(): BelongsTo { return $this->morphTo(); } diff --git a/app-modules/form/src/Models/Submission.php b/app-modules/form/src/Models/Submission.php index 0816268c2e..86f3e41f3e 100644 --- a/app-modules/form/src/Models/Submission.php +++ b/app-modules/form/src/Models/Submission.php @@ -40,7 +40,6 @@ use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Collection; use AdvisingApp\StudentDataModel\Models\Student; -use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -55,7 +54,7 @@ abstract public function submissible(): BelongsTo; abstract public function fields(): BelongsToMany; - public function author(): MorphTo|BelongsTo + public function author(): BelongsTo { return $this ->morphTo('author'); diff --git a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php index 49ea7c3720..b9646558fb 100644 --- a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php +++ b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php @@ -43,39 +43,6 @@ class GenerateEventRegistrationFormKitSchema extends GenerateFormKitSchema { public function __invoke(Submissible $submissible): array { - $content = $this->generateContent($submissible); - - $content = [ - [ - '$formkit' => 'radio', - 'label' => 'Will you be attending?', - 'id' => 'attending', - 'name' => 'attending', - 'options' => [ - [ - 'label' => 'Yes', - 'value' => 'yes', - ], - [ - 'label' => 'No', - 'value' => 'no', - ], - ], - 'validation' => 'required', - ], - [ - '$el' => 'div', - 'if' => '$get(attending).value === "yes"', - 'children' => $content, - ], - [ - '$formkit' => 'submit', - 'if' => '$get(attending).value === "no"', - 'label' => 'Submit', - 'disabled' => '$get(form).state.valid !== true', - ], - ]; - return [ '$cmp' => 'FormKit', 'props' => [ @@ -85,7 +52,36 @@ public function __invoke(Submissible $submissible): array 'plugins' => '$plugins', 'actions' => false, ], - 'children' => $content, + 'children' => [ + [ + '$formkit' => 'radio', + 'label' => 'Will you be attending?', + 'id' => 'attending', + 'name' => 'attending', + 'options' => [ + [ + 'label' => 'Yes', + 'value' => 'yes', + ], + [ + 'label' => 'No', + 'value' => 'no', + ], + ], + 'validation' => 'required', + ], + [ + '$el' => 'div', + 'if' => '$get(attending).value === "yes"', + 'children' => $this->generateContent($submissible), + ], + [ + '$formkit' => 'submit', + 'if' => '$get(attending).value === "no"', + 'label' => 'Submit', + 'disabled' => '$get(form).state.valid !== true', + ], + ], ]; } } From 1207d90949c110d658f5f7c9484b9270e242b9ae Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 3 Jan 2024 09:23:32 -0500 Subject: [PATCH 056/152] Regenerate the helper file Signed-off-by: Kevin Ullyott --- _ide_helper_models.php | 118 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/_ide_helper_models.php b/_ide_helper_models.php index 520c0c5be7..1e43672ec5 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -832,6 +832,8 @@ class IdeHelperAudit {} * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @property \Illuminate\Support\Carbon|null $deleted_at + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count * @property-read \App\Models\User $user * @method static \Illuminate\Database\Eloquent\Builder|License newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|License newQuery() @@ -2422,6 +2424,9 @@ class IdeHelperCalendarEvent {} * @property \Illuminate\Support\Carbon $ends_at * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $attendees + * @property-read int|null $attendees_count + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationForm|null $eventRegistrationForm * @method static \AdvisingApp\MeetingCenter\Database\Factories\EventFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|Event newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Event newQuery() @@ -2441,6 +2446,119 @@ class IdeHelperCalendarEvent {} class IdeHelperEvent {} } +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventAttendee + * + * @property \AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus $status + * @property-read \AdvisingApp\MeetingCenter\Models\Event|null $event + * @property-read \Illuminate\Notifications\DatabaseNotificationCollection $notifications + * @property-read int|null $notifications_count + * @property-read \Illuminate\Database\Eloquent\Collection $prospects + * @property-read int|null $prospects_count + * @property-read \Illuminate\Database\Eloquent\Collection $students + * @property-read int|null $students_count + * @property-read \Illuminate\Database\Eloquent\Collection $submissions + * @property-read int|null $submissions_count + * @method static \Illuminate\Database\Eloquent\Builder|EventAttendee newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventAttendee newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventAttendee query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventAttendee {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationForm + * + * @property \AdvisingApp\Form\Enums\Rounding $rounding + * @property-read \AdvisingApp\MeetingCenter\Models\Event|null $event + * @property-read \Illuminate\Database\Eloquent\Collection $fields + * @property-read int|null $fields_count + * @property-read \Illuminate\Database\Eloquent\Collection $steps + * @property-read int|null $steps_count + * @property-read \Illuminate\Database\Eloquent\Collection $submissions + * @property-read int|null $submissions_count + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm onlyTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm query() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm withoutTrashed() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationForm {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication + * + * @property-read EventRegistrationForm $submissible + * @property-read \AdvisingApp\MeetingCenter\Models\EventAttendee|null $author + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormAuthentication newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormAuthentication newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormAuthentication query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationFormAuthentication {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationFormField + * + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep $step + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationForm $submissible + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormField newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormField newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormField query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationFormField {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep + * + * @property-read \Illuminate\Database\Eloquent\Collection $fields + * @property-read int|null $fields_count + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationForm $submissible + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormStep newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormStep newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormStep query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationFormStep {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission + * + * @property \AdvisingApp\Form\Enums\FormSubmissionRequestDeliveryMethod $request_method + * @property \AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus $attendee_status + * @property-read \AdvisingApp\MeetingCenter\Models\EventAttendee|null $author + * @property-read \Illuminate\Database\Eloquent\Collection $fields + * @property-read int|null $fields_count + * @property-read \App\Models\User $requester + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationForm $submissible + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormSubmission newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormSubmission newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormSubmission query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationFormSubmission {} +} + namespace AdvisingApp\Notification\Models{ /** * AdvisingApp\Notification\Models\OutboundDeliverable From 4f9a9186f07428fbd375b9f30e9d5d1bb046ba9a Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 10:14:25 -0500 Subject: [PATCH 057/152] Remove open search fields and indexing from prospects. --- .../ProspectResource/Pages/ListProspects.php | 14 +++----- app-modules/prospect/src/Models/Prospect.php | 35 ------------------- 2 files changed, 5 insertions(+), 44 deletions(-) diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ListProspects.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ListProspects.php index cc455741c8..a5cc897835 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ListProspects.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ListProspects.php @@ -56,7 +56,6 @@ use Filament\Resources\Pages\ListRecords; use Filament\Tables\Filters\SelectFilter; use Illuminate\Database\Eloquent\Builder; -use App\Concerns\FilterTableWithOpenSearch; use Filament\Tables\Actions\BulkActionGroup; use Illuminate\Database\Eloquent\Collection; use Filament\Tables\Actions\DeleteBulkAction; @@ -71,14 +70,11 @@ use AdvisingApp\CareTeam\Filament\Actions\ToggleCareTeamBulkAction; use AdvisingApp\Notification\Filament\Actions\SubscribeTableAction; use AdvisingApp\CaseloadManagement\Actions\TranslateCaseloadFilters; -use App\Filament\Columns\OpenSearch\TextColumn as OpenSearchTextColumn; -use App\Filament\Filters\OpenSearch\SelectFilter as OpenSearchSelectFilter; use AdvisingApp\Engagement\Filament\Actions\Contracts\HasBulkEngagementAction; use AdvisingApp\Engagement\Filament\Actions\Concerns\ImplementsHasBulkEngagementAction; class ListProspects extends ListRecords implements HasBulkEngagementAction { - use FilterTableWithOpenSearch; use ImplementsHasBulkEngagementAction; protected static string $resource = ProspectResource::class; @@ -88,16 +84,16 @@ public function table(Table $table): Table return $table ->columns([ IdColumn::make(), - OpenSearchTextColumn::make(Prospect::displayNameKey()) + TextColumn::make(Prospect::displayNameKey()) ->label('Name') ->searchable() ->sortable(), - OpenSearchTextColumn::make('email') + TextColumn::make('email') ->label('Email') ->translateLabel() ->searchable() ->sortable(), - OpenSearchTextColumn::make('mobile') + TextColumn::make('mobile') ->label('Mobile') ->translateLabel() ->searchable() @@ -147,11 +143,11 @@ public function table(Table $table): Table ->searchable() ->optionsLimit(20) ->query(fn (Builder $query, array $data) => $this->caseloadFilter($query, $data)), - OpenSearchSelectFilter::make('status_id') + SelectFilter::make('status_id') ->relationship('status', 'name') ->multiple() ->preload(), - OpenSearchSelectFilter::make('source_id') + SelectFilter::make('source_id') ->relationship('source', 'name') ->multiple() ->preload(), diff --git a/app-modules/prospect/src/Models/Prospect.php b/app-modules/prospect/src/Models/Prospect.php index 00baff3249..d0aa1a0f80 100644 --- a/app-modules/prospect/src/Models/Prospect.php +++ b/app-modules/prospect/src/Models/Prospect.php @@ -45,7 +45,6 @@ use Illuminate\Notifications\Notifiable; use OwenIt\Auditing\Contracts\Auditable; use AdvisingApp\CareTeam\Models\CareTeam; -use OpenSearch\ScoutDriverPlus\Searchable; use AdvisingApp\Form\Models\FormSubmission; use Illuminate\Database\Eloquent\SoftDeletes; use AdvisingApp\Engagement\Models\EngagementFile; @@ -84,7 +83,6 @@ class Prospect extends BaseModel implements Auditable, Subscribable, Educatable, use HasManyMorphedEngagementResponses; use HasManyMorphedInteractions; use HasSubscriptions; - use Searchable; use NotifiableViaSms; protected $fillable = [ @@ -115,39 +113,6 @@ class Prospect extends BaseModel implements Auditable, Subscribable, Educatable, 'birthdate' => 'date', ]; - public function searchableAs(): string - { - return config('scout.prefix') . 'prospects'; - } - - public function toSearchableArray(): array - { - return [ - 'id' => (int) $this->getScoutKey(), - 'status_id' => $this->status_id, - 'source_id' => $this->source_id, - 'first_name' => $this->first_name, - 'last_name' => $this->last_name, - 'full_name' => $this->full_name, - 'preferred' => $this->preferred, - 'description' => $this->description, - 'email' => $this->email, - 'email_2' => $this->email_2, - 'mobile' => $this->mobile, - 'sms_opt_out' => $this->sms_opt_out, - 'email_bounce' => $this->email_bounce, - 'phone' => $this->phone, - 'address' => $this->address, - 'address_2' => $this->address_2, - 'birthdate' => $this->birthdate, - 'hsgrad' => (int) $this->hsgrad, - 'assigned_to_id' => $this->assigned_to_id, - 'created_by_id' => $this->created_by_id, - 'created_at' => $this->created_at->format('Y-m-d H:i:s'), - 'updated_at' => $this->updated_at->format('Y-m-d H:i:s'), - ]; - } - public function identifier(): string { return $this->id; From 568175450fcf91e3c1239debf6e58e96110e00d5 Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Wed, 3 Jan 2024 12:41:26 -0500 Subject: [PATCH 058/152] wip --- .../config/roles/web/analytics_management.php | 3 + .../AnalyticsResourceCategoryFactory.php | 25 +++++++ .../factories/AnalyticsResourceFactory.php | 9 ++- .../AnalyticsResourceSourceFactory.php | 4 +- ...te_analytics_resource_categories_table.php | 21 ++++++ ...72758_create_analytics_resources_table.php | 2 +- .../AnalyticsResourceCategorySeeder.php | 29 ++++++++ .../seeders/AnalyticsResourceSeeder.php | 2 +- .../seeders/AnalyticsResourceSourceSeeder.php | 3 +- ...alyticsResourceCategoryClassification.php} | 2 +- .../AnalyticsResourceCategoryResource.php | 37 +++++++++++ .../Pages/CreateAnalyticsResourceCategory.php | 39 +++++++++++ .../Pages/EditAnalyticsResourceCategory.php | 49 ++++++++++++++ .../Pages/ListAnalyticsResourceCategories.php | 54 +++++++++++++++ .../Pages/ViewAnalyticsResourceCategory.php | 36 ++++++++++ .../Resources/AnalyticsResourceResource.php | 1 - .../Pages/CreateAnalyticsResource.php | 16 ++--- .../Pages/EditAnalyticsResource.php | 16 ++--- .../Pages/ListAnalyticsResources.php | 12 ++-- .../Pages/CreateAnalyticsResourceSource.php | 5 +- .../Pages/EditAnalyticsResourceSource.php | 7 +- .../Pages/ListAnalyticsResourceSources.php | 11 ++-- .../src/Models/AnalyticsResource.php | 11 +++- .../src/Models/AnalyticsResourceCategory.php | 31 +++++++++ .../src/Models/AnalyticsResourceSource.php | 2 +- .../AnalyticsResourceCategoryPolicy.php | 66 +++++++++++++++++++ .../src/Policies/AnalyticsResourcePolicy.php | 66 +++++++++++++++++++ .../AnalyticsResourceSourcePolicy.php | 66 +++++++++++++++++++ .../Providers/AnalyticsServiceProvider.php | 4 +- app-modules/analytics/tests/.gitkeep | 0 .../CreateAnalyticsResourceTest.php | 53 +++++++++++++++ .../EditAnalyticsResourceTest.php | 59 +++++++++++++++++ .../ListAnalyticsResourcesTest.php | 23 +++++++ .../CreateAnalyticsResourceCategoryTest.php | 43 ++++++++++++ .../EditAnalyticsResourceCategoryTest.php | 55 ++++++++++++++++ .../ListAnalyticsResourceCategoriesTest.php | 23 +++++++ .../ViewAnalyticsResourceCategoryTest.php | 31 +++++++++ .../CreateAnalyticsResourceSourceTest.php | 43 ++++++++++++ .../EditAnalyticsResourceSourceTest.php | 54 +++++++++++++++ .../ListAnalyticsResourceSourcesTest.php | 23 +++++++ .../ViewAnalyticsResourceSourceTest.php | 31 +++++++++ database/seeders/DatabaseSeeder.php | 2 + stubs/policy.stub | 35 ++-------- 43 files changed, 1022 insertions(+), 82 deletions(-) create mode 100644 app-modules/analytics/database/factories/AnalyticsResourceCategoryFactory.php create mode 100644 app-modules/analytics/database/migrations/2024_01_02_172757_create_analytics_resource_categories_table.php create mode 100644 app-modules/analytics/database/seeders/AnalyticsResourceCategorySeeder.php rename app-modules/analytics/src/Enums/{AnalyticsResourceCategory.php => AnalyticsResourceCategoryClassification.php} (80%) create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/EditAnalyticsResourceCategory.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php create mode 100644 app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ViewAnalyticsResourceCategory.php create mode 100644 app-modules/analytics/src/Models/AnalyticsResourceCategory.php create mode 100644 app-modules/analytics/src/Policies/AnalyticsResourceCategoryPolicy.php create mode 100644 app-modules/analytics/src/Policies/AnalyticsResourcePolicy.php create mode 100644 app-modules/analytics/src/Policies/AnalyticsResourceSourcePolicy.php delete mode 100644 app-modules/analytics/tests/.gitkeep create mode 100644 app-modules/analytics/tests/AnalyticsResource/CreateAnalyticsResourceTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResource/EditAnalyticsResourceTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResource/ListAnalyticsResourcesTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResourceCategory/CreateAnalyticsResourceCategoryTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResourceCategory/EditAnalyticsResourceCategoryTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResourceCategory/ListAnalyticsResourceCategoriesTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResourceCategory/ViewAnalyticsResourceCategoryTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResourceSource/CreateAnalyticsResourceSourceTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResourceSource/EditAnalyticsResourceSourceTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResourceSource/ListAnalyticsResourceSourcesTest.php create mode 100644 app-modules/analytics/tests/AnalyticsResourceSource/ViewAnalyticsResourceSourceTest.php diff --git a/app-modules/analytics/config/roles/web/analytics_management.php b/app-modules/analytics/config/roles/web/analytics_management.php index cbbeacab9d..352eb33774 100644 --- a/app-modules/analytics/config/roles/web/analytics_management.php +++ b/app-modules/analytics/config/roles/web/analytics_management.php @@ -39,6 +39,9 @@ 'analytics_resource_source' => [ '*', ], + 'analytics_resource_classification' => [ + '*', + ], 'analytics_resource' => [ '*', ], diff --git a/app-modules/analytics/database/factories/AnalyticsResourceCategoryFactory.php b/app-modules/analytics/database/factories/AnalyticsResourceCategoryFactory.php new file mode 100644 index 0000000000..59af02a4b2 --- /dev/null +++ b/app-modules/analytics/database/factories/AnalyticsResourceCategoryFactory.php @@ -0,0 +1,25 @@ + + */ +class AnalyticsResourceCategoryFactory extends Factory +{ + /** + * @return array + */ + public function definition(): array + { + return [ + 'name' => str(fake()->unique()->word())->ucfirst()->toString(), + 'description' => fake()->optional()->sentences(asText: true), + 'classification' => fake()->randomElement(AnalyticsResourceCategoryClassification::cases()), + ]; + } +} diff --git a/app-modules/analytics/database/factories/AnalyticsResourceFactory.php b/app-modules/analytics/database/factories/AnalyticsResourceFactory.php index 8b69e09d73..98cac6dd23 100644 --- a/app-modules/analytics/database/factories/AnalyticsResourceFactory.php +++ b/app-modules/analytics/database/factories/AnalyticsResourceFactory.php @@ -5,7 +5,7 @@ use AdvisingApp\Analytics\Models\AnalyticsResource; use Illuminate\Database\Eloquent\Factories\Factory; use AdvisingApp\Analytics\Models\AnalyticsResourceSource; -use AdvisingApp\Analytics\Enums\AnalyticsResourceCategory; +use AdvisingApp\Analytics\Models\AnalyticsResourceCategory; /** * @extends Factory @@ -18,10 +18,9 @@ class AnalyticsResourceFactory extends Factory public function definition(): array { return [ - 'name' => str(fake()->unique()->word())->ucfirst(), + 'name' => str(fake()->unique()->word())->ucfirst()->toString(), 'description' => fake()->sentences(asText: true), 'url' => fake()->optional()->url(), - 'category' => fake()->randomElement(AnalyticsResourceCategory::cases()), 'is_active' => fake()->boolean(), 'is_included_in_data_portal' => fake()->boolean(), ]; @@ -33,6 +32,10 @@ public function configure(): AnalyticsResourceFactory|Factory $analyticsResource ->source() ->associate(fake()->optional()->randomElement([AnalyticsResourceSource::inRandomOrder()->first() ?? AnalyticsResourceSource::factory()->create()])); + + $analyticsResource + ->category() + ->associate(fake()->randomElement([AnalyticsResourceCategory::inRandomOrder()->first() ?? AnalyticsResourceCategory::factory()->create()])); }); } } diff --git a/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php b/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php index dd0dafcdbc..c296571146 100644 --- a/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php +++ b/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php @@ -2,8 +2,8 @@ namespace AdvisingApp\Analytics\Database\Factories; -use AdvisingApp\Analytics\Models\AnalyticsResourceSource; use Illuminate\Database\Eloquent\Factories\Factory; +use AdvisingApp\Analytics\Models\AnalyticsResourceSource; /** * @extends Factory @@ -16,7 +16,7 @@ class AnalyticsResourceSourceFactory extends Factory public function definition(): array { return [ - 'name' => str(fake()->unique()->word())->ucfirst(), + 'name' => str(fake()->unique()->word())->ucfirst()->toString(), ]; } } diff --git a/app-modules/analytics/database/migrations/2024_01_02_172757_create_analytics_resource_categories_table.php b/app-modules/analytics/database/migrations/2024_01_02_172757_create_analytics_resource_categories_table.php new file mode 100644 index 0000000000..7f3beafac1 --- /dev/null +++ b/app-modules/analytics/database/migrations/2024_01_02_172757_create_analytics_resource_categories_table.php @@ -0,0 +1,21 @@ +uuid('id')->primary(); + + $table->string('name')->unique(); + $table->longText('description')->nullable(); + $table->string('classification'); + + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php b/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php index 327bb0c4f1..ac52fae19d 100644 --- a/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php +++ b/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php @@ -13,11 +13,11 @@ public function up(): void $table->string('name')->unique(); $table->longText('description')->nullable(); $table->string('url')->nullable(); - $table->string('category'); $table->boolean('is_active'); $table->boolean('is_included_in_data_portal'); $table->foreignUuid('source_id')->nullable()->constrained('analytics_resource_sources'); + $table->foreignUuid('category_id')->constrained('analytics_resource_categories'); $table->timestamps(); }); diff --git a/app-modules/analytics/database/seeders/AnalyticsResourceCategorySeeder.php b/app-modules/analytics/database/seeders/AnalyticsResourceCategorySeeder.php new file mode 100644 index 0000000000..03fd5f7da4 --- /dev/null +++ b/app-modules/analytics/database/seeders/AnalyticsResourceCategorySeeder.php @@ -0,0 +1,29 @@ +createMany([ + [ + 'name' => 'Public', + 'classification' => AnalyticsResourceCategoryClassification::Public, + ], + [ + 'name' => 'Internal', + 'classification' => AnalyticsResourceCategoryClassification::Internal, + ], + [ + 'name' => 'Restricted Internal', + 'classification' => AnalyticsResourceCategoryClassification::RestrictedInternal, + ], + ]); + } +} diff --git a/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php b/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php index 1eba30282c..b409111a53 100644 --- a/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php +++ b/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php @@ -2,8 +2,8 @@ namespace AdvisingApp\Analytics\Database\Seeders; -use AdvisingApp\Analytics\Models\AnalyticsResource; use Illuminate\Database\Seeder; +use AdvisingApp\Analytics\Models\AnalyticsResource; class AnalyticsResourceSeeder extends Seeder { diff --git a/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php b/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php index b9e1d26511..a8406c1a15 100644 --- a/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php +++ b/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php @@ -2,9 +2,8 @@ namespace AdvisingApp\Analytics\Database\Seeders; -use AdvisingApp\Analytics\Models\AnalyticsResourceSource; -use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; +use AdvisingApp\Analytics\Models\AnalyticsResourceSource; class AnalyticsResourceSourceSeeder extends Seeder { diff --git a/app-modules/analytics/src/Enums/AnalyticsResourceCategory.php b/app-modules/analytics/src/Enums/AnalyticsResourceCategoryClassification.php similarity index 80% rename from app-modules/analytics/src/Enums/AnalyticsResourceCategory.php rename to app-modules/analytics/src/Enums/AnalyticsResourceCategoryClassification.php index ea55b15827..eafd1a8f01 100644 --- a/app-modules/analytics/src/Enums/AnalyticsResourceCategory.php +++ b/app-modules/analytics/src/Enums/AnalyticsResourceCategoryClassification.php @@ -4,7 +4,7 @@ use Filament\Support\Contracts\HasLabel; -enum AnalyticsResourceCategory: string implements HasLabel +enum AnalyticsResourceCategoryClassification: string implements HasLabel { case Public = 'public'; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php new file mode 100644 index 0000000000..df9d7d39e1 --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php @@ -0,0 +1,37 @@ + ListAnalyticsResourceCategories::route('/'), + 'create' => CreateAnalyticsResourceCategory::route('/create'), + 'view' => ViewAnalyticsResourceCategory::route('/{record}'), + 'edit' => EditAnalyticsResourceCategory::route('/{record}/edit'), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php new file mode 100644 index 0000000000..43027e17d5 --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php @@ -0,0 +1,39 @@ +schema([ + Section::make() + ->columns() + ->schema([ + TextInput::make('name') + ->required() + ->string() + ->unique(ignoreRecord: true), + Select::make('classification') + ->options(AnalyticsResourceCategoryClassification::class) + ->enum(AnalyticsResourceCategoryClassification::class) + ->required(), + Textarea::make('description') + ->nullable() + ->string(), + ]), + ]); + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/EditAnalyticsResourceCategory.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/EditAnalyticsResourceCategory.php new file mode 100644 index 0000000000..95d785eb7c --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/EditAnalyticsResourceCategory.php @@ -0,0 +1,49 @@ +schema([ + Section::make() + ->columns() + ->schema([ + TextInput::make('name') + ->required() + ->string() + ->unique(ignoreRecord: true), + Select::make('classification') + ->options(AnalyticsResourceCategoryClassification::class) + ->enum(AnalyticsResourceCategoryClassification::class) + ->required(), + Textarea::make('description') + ->nullable() + ->string(), + ]), + ]); + } + + protected function getHeaderActions(): array + { + return [ + ViewAction::make(), + DeleteAction::make(), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php new file mode 100644 index 0000000000..248fda9828 --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php @@ -0,0 +1,54 @@ +columns([ + IdColumn::make(), + TextColumn::make('name'), + TextColumn::make('classification') + ->sortable(), + TextColumn::make('description') + ->limit(60), + TextColumn::make('resources_count') + ->label('# of Analytics Resources') + ->counts('resources') + ->sortable(), + ]) + ->filters([ + ]) + ->actions([ + ViewAction::make(), + EditAction::make(), + ]) + ->bulkActions([ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]); + } + + protected function getHeaderActions(): array + { + return [ + CreateAction::make(), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ViewAnalyticsResourceCategory.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ViewAnalyticsResourceCategory.php new file mode 100644 index 0000000000..7432ff1903 --- /dev/null +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ViewAnalyticsResourceCategory.php @@ -0,0 +1,36 @@ +schema([ + Section::make() + ->schema([ + TextEntry::make('name'), + TextEntry::make('classification'), + TextEntry::make('description'), + ]) + ->columns(), + ]); + } + + protected function getHeaderActions(): array + { + return [ + EditAction::make(), + ]; + } +} diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php index 21004506fc..c91f336f9f 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php @@ -2,7 +2,6 @@ namespace AdvisingApp\Analytics\Filament\Resources; -use Filament\Forms\Form; use Filament\Resources\Resource; use AdvisingApp\Analytics\Models\AnalyticsResource; use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource\Pages\EditAnalyticsResource; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php index ac32db271e..223e375cfc 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php @@ -2,7 +2,6 @@ namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource\Pages; -use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use Filament\Forms\Form; use Filament\Forms\Components\Select; use Filament\Forms\Components\Section; @@ -10,7 +9,7 @@ use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\CreateRecord; -use AdvisingApp\Analytics\Enums\AnalyticsResourceCategory; +use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource; class CreateAnalyticsResource extends CreateRecord @@ -31,13 +30,12 @@ public function form(Form $form): Form Textarea::make('description') ->nullable() ->string(), - Select::make('category') - ->required() - ->options(AnalyticsResourceCategory::class) - ->enum(AnalyticsResourceCategory::class), - Select::make('source') - ->relationship(titleAttribute: 'name'), - TextInput::make('Url') + Select::make('category_id') + ->relationship('category', 'name') + ->required(), + Select::make('source_id') + ->relationship('source', 'name'), + TextInput::make('url') ->nullable() ->url(), SpatieMediaLibraryFileUpload::make('thumbnail') diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php index ab81ee88e7..5c29fa5994 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php @@ -2,7 +2,6 @@ namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource\Pages; -use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use Filament\Forms\Form; use Filament\Actions\DeleteAction; use Filament\Forms\Components\Select; @@ -11,7 +10,7 @@ use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; -use AdvisingApp\Analytics\Enums\AnalyticsResourceCategory; +use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource; class EditAnalyticsResource extends EditRecord @@ -32,13 +31,12 @@ public function form(Form $form): Form Textarea::make('description') ->nullable() ->string(), - Select::make('category') - ->required() - ->options(AnalyticsResourceCategory::class) - ->enum(AnalyticsResourceCategory::class), - Select::make('source') - ->relationship(titleAttribute: 'name'), - TextInput::make('Url') + Select::make('category_id') + ->relationship('category', 'name') + ->required(), + Select::make('source_id') + ->relationship('source', 'name'), + TextInput::make('url') ->nullable() ->url(), SpatieMediaLibraryFileUpload::make('thumbnail') diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php index 90563b4fef..261ed6aab0 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php @@ -2,21 +2,18 @@ namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource\Pages; -use AdvisingApp\Analytics\Enums\AnalyticsResourceCategory; -use App\Filament\Filters\OpenSearch\SelectFilter; -use Filament\Tables\Filters\TernaryFilter; use Filament\Tables\Table; use App\Filament\Columns\IdColumn; use Filament\Actions\CreateAction; -use Filament\Tables\Filters\Filter; use Filament\Tables\Actions\EditAction; use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\TextColumn; use Filament\Resources\Pages\ListRecords; +use Filament\Tables\Filters\TernaryFilter; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DeleteBulkAction; +use App\Filament\Filters\OpenSearch\SelectFilter; use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource; -use Illuminate\Database\Eloquent\Builder; class ListAnalyticsResources extends ListRecords { @@ -38,7 +35,7 @@ public function table(Table $table): Table TextColumn::make('source.name') ->sortable() ->searchable(), - TextColumn::make('category') + TextColumn::make('category.name') ->sortable(), IconColumn::make('is_active') ->boolean() @@ -55,7 +52,8 @@ public function table(Table $table): Table TernaryFilter::make('is_included_in_data_portal') ->label('Included in Data Portal'), SelectFilter::make('category') - ->options(AnalyticsResourceCategory::class) + ->relationship('category', 'name') + ->preload() ->multiple(), SelectFilter::make('source') ->relationship('source', 'name') diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php index 2a179bea12..a4bc65a79d 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php @@ -2,11 +2,10 @@ namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource\Pages; -use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource; -use Filament\Actions; -use Filament\Forms\Components\TextInput; use Filament\Forms\Form; +use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\CreateRecord; +use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource; class CreateAnalyticsResourceSource extends CreateRecord { diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php index fbab96ae45..da5d314b94 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php @@ -2,13 +2,12 @@ namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource\Pages; -use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource; -use Filament\Actions; -use Filament\Actions\DeleteAction; +use Filament\Forms\Form; use Filament\Actions\ViewAction; +use Filament\Actions\DeleteAction; use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; +use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource; class EditAnalyticsResourceSource extends EditRecord { diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php index a94ab9dd01..22629f38ac 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php @@ -2,17 +2,16 @@ namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource\Pages; -use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource; +use Filament\Tables\Table; use App\Filament\Columns\IdColumn; -use Filament\Actions; use Filament\Actions\CreateAction; -use Filament\Resources\Pages\ListRecords; -use Filament\Tables\Actions\BulkActionGroup; -use Filament\Tables\Actions\DeleteBulkAction; use Filament\Tables\Actions\EditAction; use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; -use Filament\Tables\Table; +use Filament\Resources\Pages\ListRecords; +use Filament\Tables\Actions\BulkActionGroup; +use Filament\Tables\Actions\DeleteBulkAction; +use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource; class ListAnalyticsResourceSources extends ListRecords { diff --git a/app-modules/analytics/src/Models/AnalyticsResource.php b/app-modules/analytics/src/Models/AnalyticsResource.php index 88efbdfe55..3c72e65198 100644 --- a/app-modules/analytics/src/Models/AnalyticsResource.php +++ b/app-modules/analytics/src/Models/AnalyticsResource.php @@ -7,7 +7,6 @@ use OwenIt\Auditing\Contracts\Auditable; use Spatie\MediaLibrary\InteractsWithMedia; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use AdvisingApp\Analytics\Enums\AnalyticsResourceCategory; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; class AnalyticsResource extends BaseModel implements Auditable, HasMedia @@ -19,12 +18,13 @@ class AnalyticsResource extends BaseModel implements Auditable, HasMedia 'name', 'description', 'url', - 'category', 'is_active', + 'is_included_in_data_portal', + 'category_id', + 'source_id', ]; protected $casts = [ - 'category' => AnalyticsResourceCategory::class, 'is_active' => 'boolean', 'is_included_in_data_portal' => 'boolean', ]; @@ -39,4 +39,9 @@ public function source(): BelongsTo { return $this->belongsTo(AnalyticsResourceSource::class); } + + public function category(): BelongsTo + { + return $this->belongsTo(AnalyticsResourceCategory::class); + } } diff --git a/app-modules/analytics/src/Models/AnalyticsResourceCategory.php b/app-modules/analytics/src/Models/AnalyticsResourceCategory.php new file mode 100644 index 0000000000..351b3b06c0 --- /dev/null +++ b/app-modules/analytics/src/Models/AnalyticsResourceCategory.php @@ -0,0 +1,31 @@ + AnalyticsResourceCategoryClassification::class, + ]; + + public function resources(): HasMany + { + return $this->hasMany(AnalyticsResource::class, 'category_id'); + } +} diff --git a/app-modules/analytics/src/Models/AnalyticsResourceSource.php b/app-modules/analytics/src/Models/AnalyticsResourceSource.php index 4f7a3447ee..313c1774e7 100644 --- a/app-modules/analytics/src/Models/AnalyticsResourceSource.php +++ b/app-modules/analytics/src/Models/AnalyticsResourceSource.php @@ -3,9 +3,9 @@ namespace AdvisingApp\Analytics\Models; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\HasMany; use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; class AnalyticsResourceSource extends BaseModel implements Auditable diff --git a/app-modules/analytics/src/Policies/AnalyticsResourceCategoryPolicy.php b/app-modules/analytics/src/Policies/AnalyticsResourceCategoryPolicy.php new file mode 100644 index 0000000000..f8979b1679 --- /dev/null +++ b/app-modules/analytics/src/Policies/AnalyticsResourceCategoryPolicy.php @@ -0,0 +1,66 @@ +canOrElse( + abilities: 'analytics_resource_category.view-any', + denyResponse: 'You do not have permission to view analytics resource categories.' + ); + } + + public function view(Authenticatable $authenticatable, AnalyticsResourceCategory $analyticsResourceCategory): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_category.*.view', "analytics_resource_category.{$analyticsResourceCategory->id}.view"], + denyResponse: 'You do not have permission to view this analytics resource category.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'analytics_resource_category.create', + denyResponse: 'You do not have permission to create analytics resource categories.' + ); + } + + public function update(Authenticatable $authenticatable, AnalyticsResourceCategory $analyticsResourceCategory): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_category.*.update', "analytics_resource_category.{$analyticsResourceCategory->id}.update"], + denyResponse: 'You do not have permission to update this analytics resource category.' + ); + } + + public function delete(Authenticatable $authenticatable, AnalyticsResourceCategory $analyticsResourceCategory): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_category.*.delete', "analytics_resource_category.{$analyticsResourceCategory->id}.delete"], + denyResponse: 'You do not have permission to delete this analytics resource category.' + ); + } + + public function restore(Authenticatable $authenticatable, AnalyticsResourceCategory $analyticsResourceCategory): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_category.*.restore', "analytics_resource_category.{$analyticsResourceCategory->id}.restore"], + denyResponse: 'You do not have permission to restore this analytics resource category.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AnalyticsResourceCategory $analyticsResourceCategory): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_category.*.force-delete', "analytics_resource_category.{$analyticsResourceCategory->id}.force-delete"], + denyResponse: 'You do not have permission to force delete this analytics resource category.' + ); + } +} diff --git a/app-modules/analytics/src/Policies/AnalyticsResourcePolicy.php b/app-modules/analytics/src/Policies/AnalyticsResourcePolicy.php new file mode 100644 index 0000000000..77ccdf40fa --- /dev/null +++ b/app-modules/analytics/src/Policies/AnalyticsResourcePolicy.php @@ -0,0 +1,66 @@ +canOrElse( + abilities: 'analytics_resource.view-any', + denyResponse: 'You do not have permission to view analytics resources.' + ); + } + + public function view(Authenticatable $authenticatable, AnalyticsResource $analyticsResource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource.*.view', "analytics_resource.{$analyticsResource->id}.view"], + denyResponse: 'You do not have permission to view this analytics resource.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'analytics_resource.create', + denyResponse: 'You do not have permission to create analytics resources.' + ); + } + + public function update(Authenticatable $authenticatable, AnalyticsResource $analyticsResource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource.*.update', "analytics_resource.{$analyticsResource->id}.update"], + denyResponse: 'You do not have permission to update this analytics resource.' + ); + } + + public function delete(Authenticatable $authenticatable, AnalyticsResource $analyticsResource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource.*.delete', "analytics_resource.{$analyticsResource->id}.delete"], + denyResponse: 'You do not have permission to delete this analytics resource.' + ); + } + + public function restore(Authenticatable $authenticatable, AnalyticsResource $analyticsResource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource.*.restore', "analytics_resource.{$analyticsResource->id}.restore"], + denyResponse: 'You do not have permission to restore this analytics resource.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AnalyticsResource $analyticsResource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource.*.force-delete', "analytics_resource.{$analyticsResource->id}.force-delete"], + denyResponse: 'You do not have permission to force delete this analytics resource.' + ); + } +} diff --git a/app-modules/analytics/src/Policies/AnalyticsResourceSourcePolicy.php b/app-modules/analytics/src/Policies/AnalyticsResourceSourcePolicy.php new file mode 100644 index 0000000000..09f8dc7389 --- /dev/null +++ b/app-modules/analytics/src/Policies/AnalyticsResourceSourcePolicy.php @@ -0,0 +1,66 @@ +canOrElse( + abilities: 'analytics_resource_source.view-any', + denyResponse: 'You do not have permission to view analytics resource sources.' + ); + } + + public function view(Authenticatable $authenticatable, AnalyticsResourceSource $analyticsResourceSource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_source.*.view', "analytics_resource_source.{$analyticsResourceSource->id}.view"], + denyResponse: 'You do not have permission to view this analytics resource source.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'analytics_resource_source.create', + denyResponse: 'You do not have permission to create analytics resource sources.' + ); + } + + public function update(Authenticatable $authenticatable, AnalyticsResourceSource $analyticsResourceSource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_source.*.update', "analytics_resource_source.{$analyticsResourceSource->id}.update"], + denyResponse: 'You do not have permission to update this analytics resource source.' + ); + } + + public function delete(Authenticatable $authenticatable, AnalyticsResourceSource $analyticsResourceSource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_source.*.delete', "analytics_resource_source.{$analyticsResourceSource->id}.delete"], + denyResponse: 'You do not have permission to delete this analytics resource source.' + ); + } + + public function restore(Authenticatable $authenticatable, AnalyticsResourceSource $analyticsResourceSource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_source.*.restore', "analytics_resource_source.{$analyticsResourceSource->id}.restore"], + denyResponse: 'You do not have permission to restore this analytics resource source.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AnalyticsResourceSource $analyticsResourceSource): Response + { + return $authenticatable->canOrElse( + abilities: ['analytics_resource_source.*.force-delete', "analytics_resource_source.{$analyticsResourceSource->id}.force-delete"], + denyResponse: 'You do not have permission to force delete this analytics resource source.' + ); + } +} diff --git a/app-modules/analytics/src/Providers/AnalyticsServiceProvider.php b/app-modules/analytics/src/Providers/AnalyticsServiceProvider.php index 0487400ab6..9c81a5652e 100644 --- a/app-modules/analytics/src/Providers/AnalyticsServiceProvider.php +++ b/app-modules/analytics/src/Providers/AnalyticsServiceProvider.php @@ -36,13 +36,14 @@ namespace AdvisingApp\Analytics\Providers; -use AdvisingApp\Analytics\Models\AnalyticsResource; use Filament\Panel; use Illuminate\Support\ServiceProvider; use AdvisingApp\Analytics\AnalyticsPlugin; +use AdvisingApp\Analytics\Models\AnalyticsResource; use Illuminate\Database\Eloquent\Relations\Relation; use AdvisingApp\Authorization\AuthorizationRoleRegistry; use AdvisingApp\Analytics\Models\AnalyticsResourceSource; +use AdvisingApp\Analytics\Models\AnalyticsResourceCategory; use AdvisingApp\Authorization\AuthorizationPermissionRegistry; class AnalyticsServiceProvider extends ServiceProvider @@ -56,6 +57,7 @@ public function boot(): void { Relation::morphMap([ 'analytics_resource_source' => AnalyticsResourceSource::class, + 'analytics_resource_category' => AnalyticsResourceCategory::class, 'analytics_resource' => AnalyticsResource::class, ]); diff --git a/app-modules/analytics/tests/.gitkeep b/app-modules/analytics/tests/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/app-modules/analytics/tests/AnalyticsResource/CreateAnalyticsResourceTest.php b/app-modules/analytics/tests/AnalyticsResource/CreateAnalyticsResourceTest.php new file mode 100644 index 0000000000..68277f1291 --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResource/CreateAnalyticsResourceTest.php @@ -0,0 +1,53 @@ +create(); + + actingAs($user) + ->get( + AnalyticsResourceResource::getUrl('create') + )->assertForbidden(); + + livewire(CreateAnalyticsResource::class) + ->assertForbidden(); + + $user->givePermissionTo('analytics_resource.view-any'); + $user->givePermissionTo('analytics_resource.create'); + + actingAs($user) + ->get( + AnalyticsResourceResource::getUrl('create') + )->assertSuccessful(); + + /** @var AnalyticsResource $request */ + $request = AnalyticsResource::factory()->make(); + + livewire(CreateAnalyticsResource::class) + ->fillForm($request->toArray()) + ->call('create') + ->assertHasNoFormErrors(); + + assertCount(1, AnalyticsResource::all()); + + /** @var AnalyticsResource $analyticsResource */ + $analyticsResource = AnalyticsResource::first(); + + expect($analyticsResource) + ->name->toBe($request->name) + ->description->toBe($request->description) + ->url->toBe($request->url) + ->is_active->toBe($request->is_active) + ->is_included_in_data_portal->toBe($request->is_included_in_data_portal) + ->source_id->toBe($request->source_id) + ->category_id->toBe($request->category_id); +}); diff --git a/app-modules/analytics/tests/AnalyticsResource/EditAnalyticsResourceTest.php b/app-modules/analytics/tests/AnalyticsResource/EditAnalyticsResourceTest.php new file mode 100644 index 0000000000..33406cdd3d --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResource/EditAnalyticsResourceTest.php @@ -0,0 +1,59 @@ +create(); + + $analyticsResource = AnalyticsResource::factory()->create(); + + actingAs($user) + ->get( + AnalyticsResourceResource::getUrl('edit', [ + 'record' => $analyticsResource, + ]) + )->assertForbidden(); + + livewire(EditAnalyticsResource::class, [ + 'record' => $analyticsResource->getRouteKey(), + ]) + ->assertForbidden(); + + $user->givePermissionTo('analytics_resource.view-any'); + $user->givePermissionTo('analytics_resource.*.update'); + + actingAs($user) + ->get( + AnalyticsResourceResource::getUrl('edit', [ + 'record' => $analyticsResource, + ]) + )->assertSuccessful(); + + // TODO: Finish these tests to ensure changes are allowed + /** @var AnalyticsResource $request */ + $request = AnalyticsResource::factory()->make(); + + livewire(EditAnalyticsResource::class, [ + 'record' => $analyticsResource->getRouteKey(), + ]) + ->fillForm($request->toArray()) + ->call('save') + ->assertHasNoFormErrors(); + + /** @var AnalyticsResource $analyticsResource */ + expect($analyticsResource->refresh()) + ->name->toBe($request->name) + ->description->toBe($request->description) + ->url->toBe($request->url) + ->is_active->toBe($request->is_active) + ->is_included_in_data_portal->toBe($request->is_included_in_data_portal) + ->source_id->toBe($request->source_id) + ->category_id->toBe($request->category_id); +}); diff --git a/app-modules/analytics/tests/AnalyticsResource/ListAnalyticsResourcesTest.php b/app-modules/analytics/tests/AnalyticsResource/ListAnalyticsResourcesTest.php new file mode 100644 index 0000000000..136918b4de --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResource/ListAnalyticsResourcesTest.php @@ -0,0 +1,23 @@ +create(); + + actingAs($user) + ->get( + AnalyticsResourceResource::getUrl() + )->assertForbidden(); + + $user->givePermissionTo('analytics_resource.view-any'); + + actingAs($user) + ->get( + AnalyticsResourceResource::getUrl() + )->assertSuccessful(); +}); diff --git a/app-modules/analytics/tests/AnalyticsResourceCategory/CreateAnalyticsResourceCategoryTest.php b/app-modules/analytics/tests/AnalyticsResourceCategory/CreateAnalyticsResourceCategoryTest.php new file mode 100644 index 0000000000..530319a297 --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResourceCategory/CreateAnalyticsResourceCategoryTest.php @@ -0,0 +1,43 @@ +create(); + + actingAs($user) + ->get( + AnalyticsResourceCategoryResource::getUrl('create') + )->assertForbidden(); + + livewire(CreateAnalyticsResourceCategory::class) + ->assertForbidden(); + + $user->givePermissionTo('analytics_resource_category.view-any'); + $user->givePermissionTo('analytics_resource_category.create'); + + actingAs($user) + ->get( + AnalyticsResourceCategoryResource::getUrl('create') + )->assertSuccessful(); + + $request = AnalyticsResourceCategory::factory()->make(); + + livewire(CreateAnalyticsResourceCategory::class) + ->fillForm($request->toArray()) + ->call('create') + ->assertHasNoFormErrors(); + + assertCount(1, AnalyticsResourceCategory::all()); + + assertDatabaseHas(AnalyticsResourceCategory::class, $request->toArray()); +}); diff --git a/app-modules/analytics/tests/AnalyticsResourceCategory/EditAnalyticsResourceCategoryTest.php b/app-modules/analytics/tests/AnalyticsResourceCategory/EditAnalyticsResourceCategoryTest.php new file mode 100644 index 0000000000..79eae81a30 --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResourceCategory/EditAnalyticsResourceCategoryTest.php @@ -0,0 +1,55 @@ +create(); + + $analyticsResourceCategory = AnalyticsResourceCategory::factory()->create(); + + actingAs($user) + ->get( + AnalyticsResourceCategoryResource::getUrl('edit', [ + 'record' => $analyticsResourceCategory, + ]) + )->assertForbidden(); + + livewire(EditAnalyticsResourceCategory::class, [ + 'record' => $analyticsResourceCategory->getRouteKey(), + ]) + ->assertForbidden(); + + $user->givePermissionTo('analytics_resource_category.view-any'); + $user->givePermissionTo('analytics_resource_category.*.update'); + + actingAs($user) + ->get( + AnalyticsResourceCategoryResource::getUrl('edit', [ + 'record' => $analyticsResourceCategory, + ]) + )->assertSuccessful(); + + // TODO: Finish these tests to ensure changes are allowed + /** @var AnalyticsResourceCategory $request */ + $request = AnalyticsResourceCategory::factory()->make(); + + livewire(EditAnalyticsResourceCategory::class, [ + 'record' => $analyticsResourceCategory->getRouteKey(), + ]) + ->fillForm($request->toArray()) + ->call('save') + ->assertHasNoFormErrors(); + + /** @var AnalyticsResourceCategory $analyticsResourceCategory */ + expect($analyticsResourceCategory->refresh()) + ->name->toBe($request->name) + ->description->toBe($request->description) + ->classification->toBe($request->classification); +}); diff --git a/app-modules/analytics/tests/AnalyticsResourceCategory/ListAnalyticsResourceCategoriesTest.php b/app-modules/analytics/tests/AnalyticsResourceCategory/ListAnalyticsResourceCategoriesTest.php new file mode 100644 index 0000000000..cad79e6d82 --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResourceCategory/ListAnalyticsResourceCategoriesTest.php @@ -0,0 +1,23 @@ +create(); + + actingAs($user) + ->get( + AnalyticsResourceCategoryResource::getUrl() + )->assertForbidden(); + + $user->givePermissionTo('analytics_resource_category.view-any'); + + actingAs($user) + ->get( + AnalyticsResourceCategoryResource::getUrl() + )->assertSuccessful(); +}); diff --git a/app-modules/analytics/tests/AnalyticsResourceCategory/ViewAnalyticsResourceCategoryTest.php b/app-modules/analytics/tests/AnalyticsResourceCategory/ViewAnalyticsResourceCategoryTest.php new file mode 100644 index 0000000000..31ae20a974 --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResourceCategory/ViewAnalyticsResourceCategoryTest.php @@ -0,0 +1,31 @@ +create(); + + $analyticsResourceCategory = AnalyticsResourceCategory::factory()->create(); + + actingAs($user) + ->get( + AnalyticsResourceCategoryResource::getUrl('view', [ + 'record' => $analyticsResourceCategory, + ]) + )->assertForbidden(); + + $user->givePermissionTo('analytics_resource_category.view-any'); + $user->givePermissionTo('analytics_resource_category.*.view'); + + actingAs($user) + ->get( + AnalyticsResourceCategoryResource::getUrl('view', [ + 'record' => $analyticsResourceCategory, + ]) + )->assertSuccessful(); +}); diff --git a/app-modules/analytics/tests/AnalyticsResourceSource/CreateAnalyticsResourceSourceTest.php b/app-modules/analytics/tests/AnalyticsResourceSource/CreateAnalyticsResourceSourceTest.php new file mode 100644 index 0000000000..4b23591332 --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResourceSource/CreateAnalyticsResourceSourceTest.php @@ -0,0 +1,43 @@ +create(); + + actingAs($user) + ->get( + AnalyticsResourceSourceResource::getUrl('create') + )->assertForbidden(); + + livewire(CreateAnalyticsResourceSource::class) + ->assertForbidden(); + + $user->givePermissionTo('analytics_resource_source.view-any'); + $user->givePermissionTo('analytics_resource_source.create'); + + actingAs($user) + ->get( + AnalyticsResourceSourceResource::getUrl('create') + )->assertSuccessful(); + + $request = AnalyticsResourceSource::factory()->make(); + + livewire(CreateAnalyticsResourceSource::class) + ->fillForm($request->toArray()) + ->call('create') + ->assertHasNoFormErrors(); + + assertCount(1, AnalyticsResourceSource::all()); + + assertDatabaseHas(AnalyticsResourceSource::class, $request->toArray()); +}); diff --git a/app-modules/analytics/tests/AnalyticsResourceSource/EditAnalyticsResourceSourceTest.php b/app-modules/analytics/tests/AnalyticsResourceSource/EditAnalyticsResourceSourceTest.php new file mode 100644 index 0000000000..f8eadeef62 --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResourceSource/EditAnalyticsResourceSourceTest.php @@ -0,0 +1,54 @@ +create(); + + $analyticsResourceSource = AnalyticsResourceSource::factory()->create(); + + actingAs($user) + ->get( + AnalyticsResourceSourceResource::getUrl('edit', [ + 'record' => $analyticsResourceSource, + ]) + )->assertForbidden(); + + livewire(EditAnalyticsResourceSource::class, [ + 'record' => $analyticsResourceSource->getRouteKey(), + ]) + ->assertForbidden(); + + $user->givePermissionTo('analytics_resource_source.view-any'); + $user->givePermissionTo('analytics_resource_source.*.update'); + + actingAs($user) + ->get( + AnalyticsResourceSourceResource::getUrl('edit', [ + 'record' => $analyticsResourceSource, + ]) + )->assertSuccessful(); + + // TODO: Finish these tests to ensure changes are allowed + /** @var AnalyticsResourceSource $request */ + $request = AnalyticsResourceCategory::factory()->make(); + + livewire(EditAnalyticsResourceSource::class, [ + 'record' => $analyticsResourceSource->getRouteKey(), + ]) + ->fillForm($request->toArray()) + ->call('save') + ->assertHasNoFormErrors(); + + /** @var AnalyticsResourceSource $analyticsResourceSource */ + expect($analyticsResourceSource->refresh()) + ->name->toBe($request->name); +}); diff --git a/app-modules/analytics/tests/AnalyticsResourceSource/ListAnalyticsResourceSourcesTest.php b/app-modules/analytics/tests/AnalyticsResourceSource/ListAnalyticsResourceSourcesTest.php new file mode 100644 index 0000000000..fda6640c4e --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResourceSource/ListAnalyticsResourceSourcesTest.php @@ -0,0 +1,23 @@ +create(); + + actingAs($user) + ->get( + AnalyticsResourceSourceResource::getUrl() + )->assertForbidden(); + + $user->givePermissionTo('analytics_resource_source.view-any'); + + actingAs($user) + ->get( + AnalyticsResourceSourceResource::getUrl() + )->assertSuccessful(); +}); diff --git a/app-modules/analytics/tests/AnalyticsResourceSource/ViewAnalyticsResourceSourceTest.php b/app-modules/analytics/tests/AnalyticsResourceSource/ViewAnalyticsResourceSourceTest.php new file mode 100644 index 0000000000..0be728780e --- /dev/null +++ b/app-modules/analytics/tests/AnalyticsResourceSource/ViewAnalyticsResourceSourceTest.php @@ -0,0 +1,31 @@ +create(); + + $analyticsResourceSource = AnalyticsResourceSource::factory()->create(); + + actingAs($user) + ->get( + AnalyticsResourceSourceResource::getUrl('view', [ + 'record' => $analyticsResourceSource, + ]) + )->assertForbidden(); + + $user->givePermissionTo('analytics_resource_source.view-any'); + $user->givePermissionTo('analytics_resource_source.*.view'); + + actingAs($user) + ->get( + AnalyticsResourceSourceResource::getUrl('view', [ + 'record' => $analyticsResourceSource, + ]) + )->assertSuccessful(); +}); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 07be7b1d92..61c434a860 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -58,6 +58,7 @@ use AdvisingApp\Analytics\Database\Seeders\AnalyticsResourceSourceSeeder; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseStatusSeeder; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseQualitySeeder; +use AdvisingApp\Analytics\Database\Seeders\AnalyticsResourceCategorySeeder; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseCategorySeeder; use AdvisingApp\ServiceManagement\Database\Seeders\ServiceRequestTypeSeeder; use AdvisingApp\Application\Database\Seeders\ApplicationSubmissionStateSeeder; @@ -111,6 +112,7 @@ public function run(): void AssetSeeder::class, MaintenanceProviderSeeder::class, AnalyticsResourceSourceSeeder::class, + AnalyticsResourceCategorySeeder::class, AnalyticsResourceSeeder::class, ]); } diff --git a/stubs/policy.stub b/stubs/policy.stub index 5a465a99ed..7b3737a7cd 100644 --- a/stubs/policy.stub +++ b/stubs/policy.stub @@ -8,58 +8,37 @@ use App\Models\Authenticatable; class {{ class }} { - /** - * Determine whether the user can view any models. - */ - public function viewAny(Authenticatable $authenticatable): bool + public function viewAny(Authenticatable $authenticatable): Response { // } - /** - * Determine whether the user can view the model. - */ - public function view(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): bool + public function view(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): Response { // } - /** - * Determine whether the user can create models. - */ - public function create(Authenticatable $authenticatable): bool + public function create(Authenticatable $authenticatable): Response { // } - /** - * Determine whether the user can update the model. - */ - public function update(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): bool + public function update(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): Response { // } - /** - * Determine whether the user can delete the model. - */ - public function delete(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): bool + public function delete(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): Response { // } - /** - * Determine whether the user can restore the model. - */ - public function restore(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): bool + public function restore(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): Response { // } - /** - * Determine whether the user can permanently delete the model. - */ - public function forceDelete(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): bool + public function forceDelete(Authenticatable $authenticatable, {{ model }} ${{ modelVariable }}): Response { // } From e5af3605d4510fcf8cc9d282d981893b0be83709 Mon Sep 17 00:00:00 2001 From: mxm1070 Date: Wed, 3 Jan 2024 17:49:58 +0000 Subject: [PATCH 059/152] chore: fix enforcement of copyright on all files --- .../AnalyticsResourceCategoryFactory.php | 34 +++++++++++++++++++ .../factories/AnalyticsResourceFactory.php | 34 +++++++++++++++++++ .../AnalyticsResourceSourceFactory.php | 34 +++++++++++++++++++ ...reate_analytics_resource_sources_table.php | 34 +++++++++++++++++++ ...te_analytics_resource_categories_table.php | 34 +++++++++++++++++++ ...72758_create_analytics_resources_table.php | 34 +++++++++++++++++++ .../AnalyticsResourceCategorySeeder.php | 34 +++++++++++++++++++ .../seeders/AnalyticsResourceSeeder.php | 34 +++++++++++++++++++ .../seeders/AnalyticsResourceSourceSeeder.php | 34 +++++++++++++++++++ ...nalyticsResourceCategoryClassification.php | 34 +++++++++++++++++++ .../AnalyticsResourceCategoryResource.php | 34 +++++++++++++++++++ .../Pages/CreateAnalyticsResourceCategory.php | 34 +++++++++++++++++++ .../Pages/EditAnalyticsResourceCategory.php | 34 +++++++++++++++++++ .../Pages/ListAnalyticsResourceCategories.php | 34 +++++++++++++++++++ .../Pages/ViewAnalyticsResourceCategory.php | 34 +++++++++++++++++++ .../Resources/AnalyticsResourceResource.php | 34 +++++++++++++++++++ .../Pages/CreateAnalyticsResource.php | 34 +++++++++++++++++++ .../Pages/EditAnalyticsResource.php | 34 +++++++++++++++++++ .../Pages/ListAnalyticsResources.php | 34 +++++++++++++++++++ .../AnalyticsResourceSourceResource.php | 34 +++++++++++++++++++ .../Pages/CreateAnalyticsResourceSource.php | 34 +++++++++++++++++++ .../Pages/EditAnalyticsResourceSource.php | 34 +++++++++++++++++++ .../Pages/ListAnalyticsResourceSources.php | 34 +++++++++++++++++++ .../Pages/ViewAnalyticsResourceSource.php | 34 +++++++++++++++++++ .../src/Models/AnalyticsResource.php | 34 +++++++++++++++++++ .../src/Models/AnalyticsResourceCategory.php | 34 +++++++++++++++++++ .../src/Models/AnalyticsResourceSource.php | 34 +++++++++++++++++++ .../AnalyticsResourceCategoryPolicy.php | 34 +++++++++++++++++++ .../src/Policies/AnalyticsResourcePolicy.php | 34 +++++++++++++++++++ .../AnalyticsResourceSourcePolicy.php | 34 +++++++++++++++++++ .../CreateAnalyticsResourceTest.php | 34 +++++++++++++++++++ .../EditAnalyticsResourceTest.php | 34 +++++++++++++++++++ .../ListAnalyticsResourcesTest.php | 34 +++++++++++++++++++ .../CreateAnalyticsResourceCategoryTest.php | 34 +++++++++++++++++++ .../EditAnalyticsResourceCategoryTest.php | 34 +++++++++++++++++++ .../ListAnalyticsResourceCategoriesTest.php | 34 +++++++++++++++++++ .../ViewAnalyticsResourceCategoryTest.php | 34 +++++++++++++++++++ .../CreateAnalyticsResourceSourceTest.php | 34 +++++++++++++++++++ .../EditAnalyticsResourceSourceTest.php | 34 +++++++++++++++++++ .../ListAnalyticsResourceSourcesTest.php | 34 +++++++++++++++++++ .../ViewAnalyticsResourceSourceTest.php | 34 +++++++++++++++++++ 41 files changed, 1394 insertions(+) diff --git a/app-modules/analytics/database/factories/AnalyticsResourceCategoryFactory.php b/app-modules/analytics/database/factories/AnalyticsResourceCategoryFactory.php index 59af02a4b2..709c516313 100644 --- a/app-modules/analytics/database/factories/AnalyticsResourceCategoryFactory.php +++ b/app-modules/analytics/database/factories/AnalyticsResourceCategoryFactory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; diff --git a/app-modules/analytics/database/factories/AnalyticsResourceFactory.php b/app-modules/analytics/database/factories/AnalyticsResourceFactory.php index 98cac6dd23..552fb5c575 100644 --- a/app-modules/analytics/database/factories/AnalyticsResourceFactory.php +++ b/app-modules/analytics/database/factories/AnalyticsResourceFactory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Database\Factories; use AdvisingApp\Analytics\Models\AnalyticsResource; diff --git a/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php b/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php index c296571146..1f4d4469bd 100644 --- a/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php +++ b/app-modules/analytics/database/factories/AnalyticsResourceSourceFactory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; diff --git a/app-modules/analytics/database/migrations/2024_01_02_165407_create_analytics_resource_sources_table.php b/app-modules/analytics/database/migrations/2024_01_02_165407_create_analytics_resource_sources_table.php index b3a8069a5a..64bb8a2b27 100644 --- a/app-modules/analytics/database/migrations/2024_01_02_165407_create_analytics_resource_sources_table.php +++ b/app-modules/analytics/database/migrations/2024_01_02_165407_create_analytics_resource_sources_table.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; diff --git a/app-modules/analytics/database/migrations/2024_01_02_172757_create_analytics_resource_categories_table.php b/app-modules/analytics/database/migrations/2024_01_02_172757_create_analytics_resource_categories_table.php index 7f3beafac1..2fa98828d6 100644 --- a/app-modules/analytics/database/migrations/2024_01_02_172757_create_analytics_resource_categories_table.php +++ b/app-modules/analytics/database/migrations/2024_01_02_172757_create_analytics_resource_categories_table.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; diff --git a/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php b/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php index ac52fae19d..b74554ed12 100644 --- a/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php +++ b/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; diff --git a/app-modules/analytics/database/seeders/AnalyticsResourceCategorySeeder.php b/app-modules/analytics/database/seeders/AnalyticsResourceCategorySeeder.php index 03fd5f7da4..2423341b0b 100644 --- a/app-modules/analytics/database/seeders/AnalyticsResourceCategorySeeder.php +++ b/app-modules/analytics/database/seeders/AnalyticsResourceCategorySeeder.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Database\Seeders; use Illuminate\Database\Seeder; diff --git a/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php b/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php index b409111a53..c644094465 100644 --- a/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php +++ b/app-modules/analytics/database/seeders/AnalyticsResourceSeeder.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Database\Seeders; use Illuminate\Database\Seeder; diff --git a/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php b/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php index a8406c1a15..eb5a224af2 100644 --- a/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php +++ b/app-modules/analytics/database/seeders/AnalyticsResourceSourceSeeder.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Database\Seeders; use Illuminate\Database\Seeder; diff --git a/app-modules/analytics/src/Enums/AnalyticsResourceCategoryClassification.php b/app-modules/analytics/src/Enums/AnalyticsResourceCategoryClassification.php index eafd1a8f01..2f2d8053ea 100644 --- a/app-modules/analytics/src/Enums/AnalyticsResourceCategoryClassification.php +++ b/app-modules/analytics/src/Enums/AnalyticsResourceCategoryClassification.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Enums; use Filament\Support\Contracts\HasLabel; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php index df9d7d39e1..bd3dfa5b7e 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources; use Filament\Resources\Resource; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php index 43027e17d5..47848d7bf8 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceCategoryResource\Pages; use Filament\Forms\Form; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/EditAnalyticsResourceCategory.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/EditAnalyticsResourceCategory.php index 95d785eb7c..371b49fc91 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/EditAnalyticsResourceCategory.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/EditAnalyticsResourceCategory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceCategoryResource\Pages; use Filament\Forms\Form; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php index 248fda9828..336b1cfb3b 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceCategoryResource\Pages; use Filament\Tables\Table; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ViewAnalyticsResourceCategory.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ViewAnalyticsResourceCategory.php index 7432ff1903..3b5c294fbd 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ViewAnalyticsResourceCategory.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ViewAnalyticsResourceCategory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceCategoryResource\Pages; use Filament\Actions\EditAction; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php index c91f336f9f..3caa81cfa8 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources; use Filament\Resources\Resource; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php index 223e375cfc..02bc4e0a9b 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource\Pages; use Filament\Forms\Form; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php index 5c29fa5994..25d29ab84f 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource\Pages; use Filament\Forms\Form; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php index 261ed6aab0..a5b9ba9f5c 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/ListAnalyticsResources.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource\Pages; use Filament\Tables\Table; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php index ea55f45616..6f2c859d21 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources; use Filament\Resources\Resource; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php index a4bc65a79d..edf722b595 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/CreateAnalyticsResourceSource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource\Pages; use Filament\Forms\Form; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php index da5d314b94..a109622838 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/EditAnalyticsResourceSource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource\Pages; use Filament\Forms\Form; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php index 22629f38ac..67c75d32e1 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource\Pages; use Filament\Tables\Table; diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ViewAnalyticsResourceSource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ViewAnalyticsResourceSource.php index 58d0f9d66a..e5a90ee92d 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ViewAnalyticsResourceSource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ViewAnalyticsResourceSource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceSourceResource\Pages; use Filament\Actions\EditAction; diff --git a/app-modules/analytics/src/Models/AnalyticsResource.php b/app-modules/analytics/src/Models/AnalyticsResource.php index 3c72e65198..c130b6daf1 100644 --- a/app-modules/analytics/src/Models/AnalyticsResource.php +++ b/app-modules/analytics/src/Models/AnalyticsResource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Models; use App\Models\BaseModel; diff --git a/app-modules/analytics/src/Models/AnalyticsResourceCategory.php b/app-modules/analytics/src/Models/AnalyticsResourceCategory.php index 351b3b06c0..1dfa8ee67e 100644 --- a/app-modules/analytics/src/Models/AnalyticsResourceCategory.php +++ b/app-modules/analytics/src/Models/AnalyticsResourceCategory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Models; use App\Models\BaseModel; diff --git a/app-modules/analytics/src/Models/AnalyticsResourceSource.php b/app-modules/analytics/src/Models/AnalyticsResourceSource.php index 313c1774e7..00bdd6ab55 100644 --- a/app-modules/analytics/src/Models/AnalyticsResourceSource.php +++ b/app-modules/analytics/src/Models/AnalyticsResourceSource.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Models; use App\Models\BaseModel; diff --git a/app-modules/analytics/src/Policies/AnalyticsResourceCategoryPolicy.php b/app-modules/analytics/src/Policies/AnalyticsResourceCategoryPolicy.php index f8979b1679..a570af08da 100644 --- a/app-modules/analytics/src/Policies/AnalyticsResourceCategoryPolicy.php +++ b/app-modules/analytics/src/Policies/AnalyticsResourceCategoryPolicy.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Policies; use App\Models\Authenticatable; diff --git a/app-modules/analytics/src/Policies/AnalyticsResourcePolicy.php b/app-modules/analytics/src/Policies/AnalyticsResourcePolicy.php index 77ccdf40fa..8c2b19813d 100644 --- a/app-modules/analytics/src/Policies/AnalyticsResourcePolicy.php +++ b/app-modules/analytics/src/Policies/AnalyticsResourcePolicy.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Policies; use App\Models\Authenticatable; diff --git a/app-modules/analytics/src/Policies/AnalyticsResourceSourcePolicy.php b/app-modules/analytics/src/Policies/AnalyticsResourceSourcePolicy.php index 09f8dc7389..ac77477028 100644 --- a/app-modules/analytics/src/Policies/AnalyticsResourceSourcePolicy.php +++ b/app-modules/analytics/src/Policies/AnalyticsResourceSourcePolicy.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Analytics\Policies; use App\Models\Authenticatable; diff --git a/app-modules/analytics/tests/AnalyticsResource/CreateAnalyticsResourceTest.php b/app-modules/analytics/tests/AnalyticsResource/CreateAnalyticsResourceTest.php index 68277f1291..805d40595b 100644 --- a/app-modules/analytics/tests/AnalyticsResource/CreateAnalyticsResourceTest.php +++ b/app-modules/analytics/tests/AnalyticsResource/CreateAnalyticsResourceTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResource/EditAnalyticsResourceTest.php b/app-modules/analytics/tests/AnalyticsResource/EditAnalyticsResourceTest.php index 33406cdd3d..866c2efa7c 100644 --- a/app-modules/analytics/tests/AnalyticsResource/EditAnalyticsResourceTest.php +++ b/app-modules/analytics/tests/AnalyticsResource/EditAnalyticsResourceTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResource/ListAnalyticsResourcesTest.php b/app-modules/analytics/tests/AnalyticsResource/ListAnalyticsResourcesTest.php index 136918b4de..938c63ec81 100644 --- a/app-modules/analytics/tests/AnalyticsResource/ListAnalyticsResourcesTest.php +++ b/app-modules/analytics/tests/AnalyticsResource/ListAnalyticsResourcesTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResourceCategory/CreateAnalyticsResourceCategoryTest.php b/app-modules/analytics/tests/AnalyticsResourceCategory/CreateAnalyticsResourceCategoryTest.php index 530319a297..9221c4abd5 100644 --- a/app-modules/analytics/tests/AnalyticsResourceCategory/CreateAnalyticsResourceCategoryTest.php +++ b/app-modules/analytics/tests/AnalyticsResourceCategory/CreateAnalyticsResourceCategoryTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResourceCategory/EditAnalyticsResourceCategoryTest.php b/app-modules/analytics/tests/AnalyticsResourceCategory/EditAnalyticsResourceCategoryTest.php index 79eae81a30..cfa209e664 100644 --- a/app-modules/analytics/tests/AnalyticsResourceCategory/EditAnalyticsResourceCategoryTest.php +++ b/app-modules/analytics/tests/AnalyticsResourceCategory/EditAnalyticsResourceCategoryTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResourceCategory/ListAnalyticsResourceCategoriesTest.php b/app-modules/analytics/tests/AnalyticsResourceCategory/ListAnalyticsResourceCategoriesTest.php index cad79e6d82..a18c9ea531 100644 --- a/app-modules/analytics/tests/AnalyticsResourceCategory/ListAnalyticsResourceCategoriesTest.php +++ b/app-modules/analytics/tests/AnalyticsResourceCategory/ListAnalyticsResourceCategoriesTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResourceCategory/ViewAnalyticsResourceCategoryTest.php b/app-modules/analytics/tests/AnalyticsResourceCategory/ViewAnalyticsResourceCategoryTest.php index 31ae20a974..94976167ab 100644 --- a/app-modules/analytics/tests/AnalyticsResourceCategory/ViewAnalyticsResourceCategoryTest.php +++ b/app-modules/analytics/tests/AnalyticsResourceCategory/ViewAnalyticsResourceCategoryTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResourceSource/CreateAnalyticsResourceSourceTest.php b/app-modules/analytics/tests/AnalyticsResourceSource/CreateAnalyticsResourceSourceTest.php index 4b23591332..5c35e17706 100644 --- a/app-modules/analytics/tests/AnalyticsResourceSource/CreateAnalyticsResourceSourceTest.php +++ b/app-modules/analytics/tests/AnalyticsResourceSource/CreateAnalyticsResourceSourceTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResourceSource/EditAnalyticsResourceSourceTest.php b/app-modules/analytics/tests/AnalyticsResourceSource/EditAnalyticsResourceSourceTest.php index f8eadeef62..0e25784cd7 100644 --- a/app-modules/analytics/tests/AnalyticsResourceSource/EditAnalyticsResourceSourceTest.php +++ b/app-modules/analytics/tests/AnalyticsResourceSource/EditAnalyticsResourceSourceTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResourceSource/ListAnalyticsResourceSourcesTest.php b/app-modules/analytics/tests/AnalyticsResourceSource/ListAnalyticsResourceSourcesTest.php index fda6640c4e..58b85cb376 100644 --- a/app-modules/analytics/tests/AnalyticsResourceSource/ListAnalyticsResourceSourcesTest.php +++ b/app-modules/analytics/tests/AnalyticsResourceSource/ListAnalyticsResourceSourcesTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; diff --git a/app-modules/analytics/tests/AnalyticsResourceSource/ViewAnalyticsResourceSourceTest.php b/app-modules/analytics/tests/AnalyticsResourceSource/ViewAnalyticsResourceSourceTest.php index 0be728780e..150c5f5b7d 100644 --- a/app-modules/analytics/tests/AnalyticsResourceSource/ViewAnalyticsResourceSourceTest.php +++ b/app-modules/analytics/tests/AnalyticsResourceSource/ViewAnalyticsResourceSourceTest.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use App\Models\User; use function Pest\Laravel\actingAs; From 4cf8f1ed6b4b0753fb4281de1aecbcb2703c0c29 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Wed, 3 Jan 2024 17:58:05 +0000 Subject: [PATCH 060/152] apply license rules --- _ide_helper_models.php | 47 ++----- .../AlertResource/Pages/ListAlerts.php | 4 +- app-modules/alert/src/Models/Alert.php | 9 ++ .../alert/src/Policies/AlertPolicy.php | 25 ++++ .../Concerns/HasSharedFormConfiguration.php | 22 +-- .../authorization/src/Enums/LicenseType.php | 14 +- app-modules/campaign/src/Models/Campaign.php | 11 ++ .../campaign/src/Policies/CampaignPolicy.php | 20 +++ .../src/Enums/CaseloadModel.php | 9 ++ .../CaseloadResource/Pages/CreateCaseload.php | 45 +++++-- .../CaseloadResource/Pages/EditCaseload.php | 5 +- .../CaseloadResource/Pages/ListCaseloads.php | 4 +- .../src/Models/Caseload.php | 19 +++ .../src/Policies/CaseloadPolicy.php | 25 ++++ .../Pages/CreateEngagement.php | 5 +- .../Pages/EditEngagement.php | 5 +- .../engagement/src/Models/Engagement.php | 11 +- .../src/Policies/EngagementPolicy.php | 25 ++++ .../Concerns/HasSharedFormConfiguration.php | 24 ++-- app-modules/form/src/Models/Submission.php | 11 ++ .../Pages/CreateInteraction.php | 5 +- .../Pages/EditInteraction.php | 5 +- .../interaction/src/Models/Interaction.php | 10 ++ .../src/Policies/InteractionPolicy.php | 36 +++++ .../notification/src/Models/Subscription.php | 10 ++ .../src/Policies/SubscriptionPolicy.php | 20 +++ .../ProspectResource/Pages/CreateProspect.php | 8 +- .../ProspectResource/Pages/EditProspect.php | 10 +- .../Pages/ManageProspectCareTeam.php | 5 + .../Pages/ManageProspectSubscriptions.php | 5 + app-modules/prospect/src/Models/Prospect.php | 30 ++++- .../prospect/src/Policies/ProspectPolicy.php | 3 +- .../Pages/CreateServiceRequest.php | 5 +- .../Pages/EditServiceRequest.php | 5 +- .../AssignedToRelationManager.php | 32 +++-- .../src/Models/ServiceRequest.php | 9 ++ .../src/Policies/ServiceRequestPolicy.php | 20 +++ .../Pages/ManageStudentCareTeam.php | 5 + .../Pages/ManageStudentSubscriptions.php | 5 + .../Models/Concerns/BelongsToEducatable.php | 43 ++++++ .../src/Models/Contracts/Educatable.php | 3 + .../student-data-model/src/Models/Student.php | 30 ++++- .../src/Policies/StudentPolicy.php | 3 +- .../Concerns/HasSharedFormConfiguration.php | 24 ++-- .../src/Filament/Concerns/TaskEditForm.php | 13 +- .../task/src/Filament/Concerns/TaskForm.php | 125 ++++++++++++++++++ .../BaseTaskRelationManager.php | 13 +- .../TaskResource/Pages/CreateTask.php | 14 +- app-modules/task/src/Models/Task.php | 9 ++ app-modules/task/src/Policies/TaskPolicy.php | 20 +++ app/Filament/Fields/ColorSelect.php | 2 +- app/Filament/Fields/EducatableSelect.php | 29 ++-- .../Pages/CreateNotificationSetting.php | 8 +- .../Pages/EditNotificationSetting.php | 10 +- app/Livewire/TaskKanban.php | 6 +- app/Models/Authenticatable.php | 11 ++ app/Models/SystemUser.php | 46 +++++++ app/Models/User.php | 62 +++++++-- 58 files changed, 855 insertions(+), 184 deletions(-) create mode 100644 app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php create mode 100644 app-modules/task/src/Filament/Concerns/TaskForm.php diff --git a/_ide_helper_models.php b/_ide_helper_models.php index 520c0c5be7..0b68c7ed95 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -1,39 +1,5 @@ - - Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. - - Advising App™ is licensed under the Elastic License 2.0. For more details, - see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. - - Notice: - - - You may not provide the software to third parties as a hosted or managed - service, where the service provides users with access to any substantial set of - the features or functionality of the software. - - You may not move, change, disable, or circumvent the license key functionality - in the software, and you may not remove or obscure any functionality in the - software that is protected by the license key. - - You may not alter, remove, or obscure any licensing, copyright, or other notices - of the licensor in the software. Any use of the licensor’s trademarks is subject - to applicable law. - - Canyon GBS LLC respects the intellectual property rights of others and expects the - same in return. Canyon GBS™ and Advising App™ are registered trademarks of - Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks - vigorously. - - The software solution, including services, infrastructure, and code, is offered as a - Software as a Service (SaaS) by Canyon GBS LLC. - - Use of this software implies agreement to the license terms and conditions as stated - in the Elastic License 2.0. - - For more information or inquiries please visit our website at - https://www.canyongbs.com or contact us via email at legal@canyongbs.com. - - -*/ - // @formatter:off /** * A helper file for your Eloquent Models @@ -366,6 +332,8 @@ class IdeHelperSystemUser {} * @method static \Illuminate\Database\Eloquent\Builder|User admins() * @method static \Illuminate\Database\Eloquent\Builder|User advancedFilter($data) * @method static \Database\Factories\UserFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|User hasAnyLicense(\AdvisingApp\Authorization\Enums\LicenseType|array|string|null $type) + * @method static \Illuminate\Database\Eloquent\Builder|User hasLicense(\AdvisingApp\Authorization\Enums\LicenseType|array|string|null $type) * @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|User newQuery() * @method static \Illuminate\Database\Eloquent\Builder|User onlyTrashed() @@ -434,6 +402,7 @@ class IdeHelperUser {} * @property-read \Illuminate\Database\Eloquent\Collection $audits * @property-read int|null $audits_count * @method static \AdvisingApp\Alert\Database\Factories\AlertFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Alert licensedToEducatable(string $relationship) * @method static \Illuminate\Database\Eloquent\Builder|Alert newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Alert newQuery() * @method static \Illuminate\Database\Eloquent\Builder|Alert onlyTrashed() @@ -613,6 +582,7 @@ class IdeHelperApplicationStep {} * @property-read \AdvisingApp\Application\Models\ApplicationSubmissionState $state * @property-read \AdvisingApp\Application\Models\Application $submissible * @method static \AdvisingApp\Application\Database\Factories\ApplicationSubmissionFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Submission licensedToEducatable(string $relationship) * @method static \Illuminate\Database\Eloquent\Builder|ApplicationSubmission newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|ApplicationSubmission newQuery() * @method static \Illuminate\Database\Eloquent\Builder|ApplicationSubmission query() @@ -832,6 +802,8 @@ class IdeHelperAudit {} * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @property \Illuminate\Support\Carbon|null $deleted_at + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count * @property-read \App\Models\User $user * @method static \Illuminate\Database\Eloquent\Builder|License newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|License newQuery() @@ -1345,6 +1317,7 @@ class IdeHelperEmailTemplate {} * @method static \Illuminate\Database\Eloquent\Builder|Engagement isAwaitingDelivery() * @method static \Illuminate\Database\Eloquent\Builder|Engagement isNotPartOfABatch() * @method static \Illuminate\Database\Eloquent\Builder|Engagement isScheduled() + * @method static \Illuminate\Database\Eloquent\Builder|Engagement licensedToEducatable(string $relationship) * @method static \Illuminate\Database\Eloquent\Builder|Engagement newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Engagement newQuery() * @method static \Illuminate\Database\Eloquent\Builder|Engagement query() @@ -1719,6 +1692,7 @@ class IdeHelperFormStep {} * @property-read \AdvisingApp\Form\Models\Form $submissible * @method static \Illuminate\Database\Eloquent\Builder|FormSubmission canceled() * @method static \AdvisingApp\Form\Database\Factories\FormSubmissionFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Submission licensedToEducatable(string $relationship) * @method static \Illuminate\Database\Eloquent\Builder|FormSubmission newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|FormSubmission newQuery() * @method static \Illuminate\Database\Eloquent\Builder|FormSubmission notCanceled() @@ -1802,6 +1776,7 @@ class IdeHelperTwilioConversation {} * @property-read \AdvisingApp\Interaction\Models\InteractionType|null $type * @property-read \App\Models\User|null $user * @method static \AdvisingApp\Interaction\Database\Factories\InteractionFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Interaction licensedToEducatable(string $relationship) * @method static \Illuminate\Database\Eloquent\Builder|Interaction newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Interaction newQuery() * @method static \Illuminate\Database\Eloquent\Builder|Interaction query() @@ -2501,6 +2476,7 @@ class IdeHelperOutboundDeliverable {} * @property \Illuminate\Support\Carbon|null $updated_at * @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $subscribable * @property-read \App\Models\User $user + * @method static \Illuminate\Database\Eloquent\Builder|Subscription licensedToEducatable(string $relationship) * @method static \Illuminate\Database\Eloquent\Builder|Subscription newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Subscription newQuery() * @method static \Illuminate\Database\Eloquent\Builder|Subscription query() @@ -2719,6 +2695,7 @@ class IdeHelperProspectStatus {} * @property-read \AdvisingApp\ServiceManagement\Models\ServiceRequestStatus|null $status * @property-read \AdvisingApp\ServiceManagement\Models\ServiceRequestType|null $type * @method static \AdvisingApp\ServiceManagement\Database\Factories\ServiceRequestFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|ServiceRequest licensedToEducatable(string $relationship) * @method static \Illuminate\Database\Eloquent\Builder|ServiceRequest newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|ServiceRequest newQuery() * @method static \Illuminate\Database\Eloquent\Builder|ServiceRequest onlyTrashed() @@ -3204,6 +3181,7 @@ class IdeHelperSurveyStep {} * @property-read \AdvisingApp\Survey\Models\Survey $submissible * @method static \Illuminate\Database\Eloquent\Builder|SurveySubmission canceled() * @method static \AdvisingApp\Survey\Database\Factories\SurveySubmissionFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Submission licensedToEducatable(string $relationship) * @method static \Illuminate\Database\Eloquent\Builder|SurveySubmission newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|SurveySubmission newQuery() * @method static \Illuminate\Database\Eloquent\Builder|SurveySubmission notCanceled() @@ -3252,6 +3230,7 @@ class IdeHelperSurveySubmission {} * @property-read \App\Models\User|null $createdBy * @method static \Illuminate\Database\Eloquent\Builder|Task byNextDue() * @method static \AdvisingApp\Task\Database\Factories\TaskFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Task licensedToEducatable(string $relationship) * @method static \Illuminate\Database\Eloquent\Builder|Task newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Task newQuery() * @method static \Illuminate\Database\Eloquent\Builder|Task onlyTrashed() diff --git a/app-modules/alert/src/Filament/Resources/AlertResource/Pages/ListAlerts.php b/app-modules/alert/src/Filament/Resources/AlertResource/Pages/ListAlerts.php index f34dc91f50..ee0d9fb0bf 100644 --- a/app-modules/alert/src/Filament/Resources/AlertResource/Pages/ListAlerts.php +++ b/app-modules/alert/src/Filament/Resources/AlertResource/Pages/ListAlerts.php @@ -36,7 +36,6 @@ namespace AdvisingApp\Alert\Filament\Resources\AlertResource\Pages; -use App\Filament\Fields\EducatableSelect; use Filament\Tables\Table; use Filament\Infolists\Infolist; use App\Filament\Columns\IdColumn; @@ -51,16 +50,15 @@ use Illuminate\Database\Eloquent\Model; use AdvisingApp\Alert\Enums\AlertStatus; use AdvisingApp\Prospect\Models\Prospect; +use App\Filament\Fields\EducatableSelect; use Filament\Resources\Pages\ListRecords; use Filament\Tables\Filters\SelectFilter; use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Alert\Enums\AlertSeverity; -use Filament\Forms\Components\MorphToSelect; use Filament\Infolists\Components\TextEntry; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DeleteBulkAction; use AdvisingApp\StudentDataModel\Models\Student; -use Filament\Forms\Components\MorphToSelect\Type; use AdvisingApp\CaseloadManagement\Models\Caseload; use AdvisingApp\Alert\Filament\Resources\AlertResource; use AdvisingApp\StudentDataModel\Models\Scopes\EducatableSearch; diff --git a/app-modules/alert/src/Models/Alert.php b/app-modules/alert/src/Models/Alert.php index e97430b0c2..66c042bbc3 100644 --- a/app-modules/alert/src/Models/Alert.php +++ b/app-modules/alert/src/Models/Alert.php @@ -50,6 +50,7 @@ use AdvisingApp\Notification\Models\Contracts\Subscribable; use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; use AdvisingApp\Notification\Models\Contracts\CanTriggerAutoSubscription; @@ -62,6 +63,7 @@ class Alert extends BaseModel implements Auditable, CanTriggerAutoSubscription, { use SoftDeletes; use AuditableTrait; + use BelongsToEducatable; protected $fillable = [ 'concern_id', @@ -113,4 +115,11 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s // Do we need to be able to relate campaigns/actions to the RESULT of their actions? } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->licensedToEducatable('concern'); + }); + } } diff --git a/app-modules/alert/src/Policies/AlertPolicy.php b/app-modules/alert/src/Policies/AlertPolicy.php index fe6a8e3ef2..48c4088f16 100644 --- a/app-modules/alert/src/Policies/AlertPolicy.php +++ b/app-modules/alert/src/Policies/AlertPolicy.php @@ -39,11 +39,16 @@ use App\Models\Authenticatable; use AdvisingApp\Alert\Models\Alert; use Illuminate\Auth\Access\Response; +use AdvisingApp\Authorization\Enums\LicenseType; class AlertPolicy { public function viewAny(Authenticatable $authenticatable): Response { + if (! $authenticatable->hasAnyLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])) { + return Response::deny('You do not have permission to view alerts.'); + } + return $authenticatable->canOrElse( abilities: 'alert.view-any', denyResponse: 'You do not have permission to view alerts.' @@ -52,6 +57,10 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, Alert $alert): Response { + if (! $authenticatable->hasLicense($alert->concern?->getLicenseType())) { + return Response::deny('You do not have permission to view this alert.'); + } + return $authenticatable->canOrElse( abilities: ['alert.*.view', "alert.{$alert->id}.view"], denyResponse: 'You do not have permission to view this alert.' @@ -68,6 +77,10 @@ public function create(Authenticatable $authenticatable): Response public function update(Authenticatable $authenticatable, Alert $alert): Response { + if (! $authenticatable->hasLicense($alert->concern?->getLicenseType())) { + return Response::deny('You do not have permission to update this alert.'); + } + return $authenticatable->canOrElse( abilities: ['alert.*.update', "alert.{$alert->id}.update"], denyResponse: 'You do not have permission to update this alert.' @@ -76,6 +89,10 @@ public function update(Authenticatable $authenticatable, Alert $alert): Response public function delete(Authenticatable $authenticatable, Alert $alert): Response { + if (! $authenticatable->hasLicense($alert->concern?->getLicenseType())) { + return Response::deny('You do not have permission to delete this alert.'); + } + return $authenticatable->canOrElse( abilities: ['alert.*.delete', "alert.{$alert->id}.delete"], denyResponse: 'You do not have permission to delete this alert.' @@ -84,6 +101,10 @@ public function delete(Authenticatable $authenticatable, Alert $alert): Response public function restore(Authenticatable $authenticatable, Alert $alert): Response { + if (! $authenticatable->hasLicense($alert->concern?->getLicenseType())) { + return Response::deny('You do not have permission to restore this alert.'); + } + return $authenticatable->canOrElse( abilities: ['alert.*.restore', "alert.{$alert->id}.restore"], denyResponse: 'You do not have permission to restore this alert.' @@ -92,6 +113,10 @@ public function restore(Authenticatable $authenticatable, Alert $alert): Respons public function forceDelete(Authenticatable $authenticatable, Alert $alert): Response { + if (! $authenticatable->hasLicense($alert->concern?->getLicenseType())) { + return Response::deny('You do not have permission to permanently delete this alert.'); + } + return $authenticatable->canOrElse( abilities: ['alert.*.force-delete', "alert.{$alert->id}.force-delete"], denyResponse: 'You do not have permission to permanently delete this alert.' diff --git a/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/Concerns/HasSharedFormConfiguration.php b/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/Concerns/HasSharedFormConfiguration.php index d1741b2aa2..14ad57b5f4 100644 --- a/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/Concerns/HasSharedFormConfiguration.php +++ b/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/Concerns/HasSharedFormConfiguration.php @@ -36,24 +36,24 @@ namespace AdvisingApp\Application\Filament\Resources\ApplicationResource\Pages\Concerns; -use AdvisingApp\Application\Models\Application; -use AdvisingApp\Application\Models\ApplicationField; -use AdvisingApp\Application\Models\ApplicationStep; +use Filament\Forms\Get; +use Filament\Forms\Components\Grid; use AdvisingApp\Form\Enums\Rounding; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use AdvisingApp\Form\Rules\IsDomain; use App\Filament\Fields\ColorSelect; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Repeater; -use Filament\Forms\Components\Section; use Filament\Forms\Components\Select; -use Filament\Forms\Components\TagsInput; +use Filament\Forms\Components\Toggle; +use Filament\Forms\Components\Section; +use FilamentTiptapEditor\TiptapEditor; +use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TagsInput; use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Get; use FilamentTiptapEditor\Enums\TiptapOutput; -use FilamentTiptapEditor\TiptapEditor; +use AdvisingApp\Application\Models\Application; +use AdvisingApp\Application\Models\ApplicationStep; +use AdvisingApp\Application\Models\ApplicationField; +use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; trait HasSharedFormConfiguration diff --git a/app-modules/authorization/src/Enums/LicenseType.php b/app-modules/authorization/src/Enums/LicenseType.php index 5e7e9d06db..83a9e79999 100644 --- a/app-modules/authorization/src/Enums/LicenseType.php +++ b/app-modules/authorization/src/Enums/LicenseType.php @@ -61,14 +61,22 @@ public function hasAvailableLicenses(): bool { $totalLicensesInUse = License::query()->where('type', $this)->count(); + return $totalLicensesInUse < $this->getSeats(); + } + + public function isLicenseable(): bool + { + return $this->getSeats() > 0; + } + + public function getSeats(): int + { $licenseSettings = app(LicenseSettings::class); - $licenseLimit = match ($this) { + return match ($this) { LicenseType::ConversationalAi => $licenseSettings->data->limits->conversationalAiSeats, LicenseType::RetentionCrm => $licenseSettings->data->limits->retentionCrmSeats, LicenseType::RecruitmentCrm => $licenseSettings->data->limits->recruitmentCrmSeats, }; - - return $totalLicensesInUse < $licenseLimit; } } diff --git a/app-modules/campaign/src/Models/Campaign.php b/app-modules/campaign/src/Models/Campaign.php index 33e510865c..35228fec54 100644 --- a/app-modules/campaign/src/Models/Campaign.php +++ b/app-modules/campaign/src/Models/Campaign.php @@ -90,4 +90,15 @@ public function hasBeenExecuted(): bool { return $this->actions->contains(fn (CampaignAction $action) => $action->hasBeenExecuted()); } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + if (! auth()->check()) { + return; + } + + $builder->whereHas('caseload'); + }); + } } diff --git a/app-modules/campaign/src/Policies/CampaignPolicy.php b/app-modules/campaign/src/Policies/CampaignPolicy.php index 560c4f50bb..dd43c108da 100644 --- a/app-modules/campaign/src/Policies/CampaignPolicy.php +++ b/app-modules/campaign/src/Policies/CampaignPolicy.php @@ -52,6 +52,10 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, Campaign $campaign): Response { + if ($authenticatable->cannot('view', $campaign->caseload)) { + return Response::deny('You do not have permission to view this campaign.'); + } + return $authenticatable->canOrElse( abilities: ['campaign.*.view', "campaign.{$campaign->id}.view"], denyResponse: 'You do not have permission to view this campaign.' @@ -68,6 +72,10 @@ public function create(Authenticatable $authenticatable): Response public function update(Authenticatable $authenticatable, Campaign $campaign): Response { + if ($authenticatable->cannot('view', $campaign->caseload)) { + return Response::deny('You do not have permission to update this campaign.'); + } + return $authenticatable->canOrElse( abilities: ['campaign.*.update', "campaign.{$campaign->id}.update"], denyResponse: 'You do not have permission to update this campaign.' @@ -76,6 +84,10 @@ public function update(Authenticatable $authenticatable, Campaign $campaign): Re public function delete(Authenticatable $authenticatable, Campaign $campaign): Response { + if ($authenticatable->cannot('view', $campaign->caseload)) { + return Response::deny('You do not have permission to delete this campaign.'); + } + return $authenticatable->canOrElse( abilities: ['campaign.*.delete', "campaign.{$campaign->id}.delete"], denyResponse: 'You do not have permission to delete this campaign.' @@ -84,6 +96,10 @@ public function delete(Authenticatable $authenticatable, Campaign $campaign): Re public function restore(Authenticatable $authenticatable, Campaign $campaign): Response { + if ($authenticatable->cannot('view', $campaign->caseload)) { + return Response::deny('You do not have permission to restore this campaign.'); + } + return $authenticatable->canOrElse( abilities: ['campaign.*.restore', "campaign.{$campaign->id}.restore"], denyResponse: 'You do not have permission to restore this campaign.' @@ -92,6 +108,10 @@ public function restore(Authenticatable $authenticatable, Campaign $campaign): R public function forceDelete(Authenticatable $authenticatable, Campaign $campaign): Response { + if ($authenticatable->cannot('view', $campaign->caseload)) { + return Response::deny('You do not have permission to permanently delete this campaign.'); + } + return $authenticatable->canOrElse( abilities: ['campaign.*.force-delete', "campaign.{$campaign->id}.force-delete"], denyResponse: 'You do not have permission to permanently delete this campaign.' diff --git a/app-modules/caseload-management/src/Enums/CaseloadModel.php b/app-modules/caseload-management/src/Enums/CaseloadModel.php index 0d3bb2067e..e88cdaaa00 100644 --- a/app-modules/caseload-management/src/Enums/CaseloadModel.php +++ b/app-modules/caseload-management/src/Enums/CaseloadModel.php @@ -39,6 +39,7 @@ use Filament\Support\Contracts\HasLabel; use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Builder; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\CaseloadManagement\Importers\StudentCaseloadSubjectImporter; use AdvisingApp\CaseloadManagement\Importers\ProspectCaseloadSubjectImporter; @@ -94,4 +95,12 @@ public function getSubjectImporter(): string CaseloadModel::Student => StudentCaseloadSubjectImporter::class, }; } + + public function getLicenseType(): LicenseType + { + return match ($this) { + CaseloadModel::Student => LicenseType::RetentionCrm, + CaseloadModel::Prospect => LicenseType::RecruitmentCrm, + }; + } } diff --git a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php index 6a7e50f13b..05993e7488 100644 --- a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php +++ b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php @@ -37,6 +37,7 @@ namespace AdvisingApp\CaseloadManagement\Filament\Resources\CaseloadResource\Pages; use Iterator; +use Exception; use App\Models\User; use Filament\Forms\Get; use Filament\Tables\Table; @@ -59,6 +60,7 @@ use Illuminate\Contracts\Support\Htmlable; use Filament\Actions\Imports\Models\Import; use Filament\Actions\Imports\Jobs\ImportCsv; +use AdvisingApp\Authorization\Enums\LicenseType; use Filament\Tables\Concerns\InteractsWithTable; use AdvisingApp\CaseloadManagement\Enums\CaseloadType; use AdvisingApp\CaseloadManagement\Enums\CaseloadModel; @@ -98,7 +100,8 @@ public function getSteps(): array $this->resetTableFiltersForm(); }), ]) - ->columns(2), + ->columns(2) + ->visible(auth()->user()->hasLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])), Step::make('Identify Population') ->schema([ Select::make('type') @@ -121,7 +124,7 @@ public function getSteps(): array ->required() ->hiddenLabel() ->visible(fn (Get $get): bool => CaseloadType::tryFromCaseOrValue($get('type')) === CaseloadType::Static) - ->helperText(fn (Get $get): string => match (CaseloadModel::tryFromCaseOrValue($get('model'))) { + ->helperText(fn (): string => match ($this->getCaseloadModel()) { CaseloadModel::Student => 'Upload a file of Student IDs or Other IDs, with each on a new line.', CaseloadModel::Prospect => 'Upload a file of prospect email addresses, with each on a new line.', }), @@ -131,21 +134,25 @@ public function getSteps(): array public function table(Table $table): Table { + $model = $this->getCaseloadModel(); + return $table - ->columns(CaseloadResource::columns($this->data['model'])) - ->filters(CaseloadResource::filters($this->data['model']), layout: FiltersLayout::AboveContent) - // ->actions(CaseloadResource::actions($this->data['model'])) - ->query(fn () => $this->data['model']->query()); + ->columns(CaseloadResource::columns($model)) + ->filters(CaseloadResource::filters($model), layout: FiltersLayout::AboveContent) + // ->actions(CaseloadResource::actions($model)) + ->query(fn () => $model->query()); } public function afterCreate(): void { - if (CaseloadType::tryFromCaseOrValue($this->data['type']) === CaseloadType::Dynamic) { + $data = $this->form->getRawState(); + + if (CaseloadType::tryFromCaseOrValue($data['type']) === CaseloadType::Dynamic) { return; } /** @var TemporaryUploadedFile $file */ - $file = Arr::first($this->data['file']); + $file = Arr::first($data['file']); $fileStream = $this->getUploadedFileStream($file); @@ -181,7 +188,7 @@ public function afterCreate(): void $import->user()->associate($user); $import->file_name = $file->getClientOriginalName(); $import->file_path = $file->getRealPath(); - $import->importer = CaseloadModel::tryFromCaseOrValue($this->data['model'])->getSubjectImporter(); + $import->importer = $this->getCaseloadModel()->getSubjectImporter(); $import->total_rows = $totalRows; $import->save(); @@ -289,9 +296,27 @@ public function getUploadedFileStream(TemporaryUploadedFile $file) ])); } + protected function getCaseloadModel(): CaseloadModel + { + $hasStudents = auth()->user()->hasLicense(LicenseType::RetentionCrm); + $hasProspects = auth()->user()->hasLicense(LicenseType::RecruitmentCrm); + + if ($hasStudents && $hasProspects) { + return CaseloadModel::tryFromCaseOrValue($this->form->getRawState()['model']) ?? throw new Exception('Neither students nor prospects were selected.'); + } + + return match (true) { + $hasStudents => CaseloadModel::Student, + $hasProspects => CaseloadModel::Prospect, + default => throw new Exception('User cannot access students or prospects.'), + }; + } + protected function mutateFormDataBeforeCreate(array $data): array { - if (CaseloadType::tryFromCaseOrValue($this->data['type']) === CaseloadType::Dynamic) { + $data['model'] = $this->getCaseloadModel(); + + if (CaseloadType::tryFromCaseOrValue($data['type']) === CaseloadType::Dynamic) { $data['filters'] = $this->tableFilters ?? []; } else { $data['filters'] = []; diff --git a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/EditCaseload.php b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/EditCaseload.php index 9add875e05..13c5d73719 100644 --- a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/EditCaseload.php +++ b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/EditCaseload.php @@ -46,6 +46,7 @@ use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; use Filament\Tables\Enums\FiltersLayout; +use AdvisingApp\Authorization\Enums\LicenseType; use Filament\Tables\Concerns\InteractsWithTable; use AdvisingApp\CaseloadManagement\Enums\CaseloadType; use AdvisingApp\CaseloadManagement\Enums\CaseloadModel; @@ -87,8 +88,10 @@ public function form(Form $form): Form Select::make('model') ->label('Population') ->options(CaseloadModel::class) - ->disabled(), + ->disabled() + ->visible(auth()->user()->hasLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])), TextInput::make('user.name') + ->label('User') ->disabled(), ]) ->columns(3), diff --git a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php index 0c3b0bbcb7..b46c7f7a4a 100644 --- a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php +++ b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php @@ -44,6 +44,7 @@ use Filament\Tables\Columns\TextColumn; use Filament\Resources\Pages\ListRecords; use Filament\Tables\Actions\DeleteAction; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\CaseloadManagement\Filament\Resources\CaseloadResource; class ListCaseloads extends ListRecords @@ -59,7 +60,8 @@ public function table(Table $table): Table ->sortable(), TextColumn::make('model') ->label('Population') - ->sortable(), + ->sortable() + ->visible(auth()->user()->hasLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])), TextColumn::make('type') ->sortable(), TextColumn::make('user.name') diff --git a/app-modules/caseload-management/src/Models/Caseload.php b/app-modules/caseload-management/src/Models/Caseload.php index 13059d148a..c48c511557 100644 --- a/app-modules/caseload-management/src/Models/Caseload.php +++ b/app-modules/caseload-management/src/Models/Caseload.php @@ -38,6 +38,7 @@ use App\Models\User; use App\Models\BaseModel; +use App\Models\Authenticatable; use Illuminate\Support\Collection; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -97,4 +98,22 @@ public function retrieveRecords(): Collection ) ->get(); } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + if (! auth()->check()) { + return; + } + + /** @var Authenticatable $user */ + $user = auth()->user(); + + foreach (CaseloadModel::cases() as $model) { + if (! $user->hasLicense($model->getLicenseType())) { + $builder->where('model', '!=', $model); + } + } + }); + } } diff --git a/app-modules/caseload-management/src/Policies/CaseloadPolicy.php b/app-modules/caseload-management/src/Policies/CaseloadPolicy.php index 2e05d39415..234f93a2e9 100644 --- a/app-modules/caseload-management/src/Policies/CaseloadPolicy.php +++ b/app-modules/caseload-management/src/Policies/CaseloadPolicy.php @@ -38,12 +38,17 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\CaseloadManagement\Models\Caseload; class CaseloadPolicy { public function viewAny(Authenticatable $authenticatable): Response { + if (! $authenticatable->hasAnyLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])) { + return Response::deny('You do not have permission to view caseloads.'); + } + return $authenticatable->canOrElse( abilities: 'caseload.view-any', denyResponse: 'You do not have permission to view caseloads.' @@ -52,6 +57,10 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, Caseload $caseload): Response { + if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + return Response::deny('You do not have permission to view this caseload.'); + } + return $authenticatable->canOrElse( abilities: ['caseload.*.view', "caseload.{$caseload->id}.view"], denyResponse: 'You do not have permission to view this caseload.' @@ -68,6 +77,10 @@ public function create(Authenticatable $authenticatable): Response public function update(Authenticatable $authenticatable, Caseload $caseload): Response { + if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + return Response::deny('You do not have permission to update this caseload.'); + } + return $authenticatable->canOrElse( abilities: ['caseload.*.update', "caseload.{$caseload->id}.update"], denyResponse: 'You do not have permission to update this caseload.' @@ -76,6 +89,10 @@ public function update(Authenticatable $authenticatable, Caseload $caseload): Re public function delete(Authenticatable $authenticatable, Caseload $caseload): Response { + if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + return Response::deny('You do not have permission to delete this caseload.'); + } + return $authenticatable->canOrElse( abilities: ['caseload.*.delete', "caseload.{$caseload->id}.delete"], denyResponse: 'You do not have permission to delete this caseload.' @@ -84,6 +101,10 @@ public function delete(Authenticatable $authenticatable, Caseload $caseload): Re public function restore(Authenticatable $authenticatable, Caseload $caseload): Response { + if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + return Response::deny('You do not have permission to restore this caseload.'); + } + return $authenticatable->canOrElse( abilities: ['caseload.*.restore', "caseload.{$caseload->id}.restore"], denyResponse: 'You do not have permission to restore this caseload.' @@ -92,6 +113,10 @@ public function restore(Authenticatable $authenticatable, Caseload $caseload): R public function forceDelete(Authenticatable $authenticatable, Caseload $caseload): Response { + if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + return Response::deny('You do not have permission to permanently delete this caseload.'); + } + return $authenticatable->canOrElse( abilities: ['caseload.*.force-delete', "caseload.{$caseload->id}.force-delete"], denyResponse: 'You do not have permission to permanently delete this caseload.' diff --git a/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/CreateEngagement.php b/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/CreateEngagement.php index 78e54aa8c5..937847fe50 100644 --- a/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/CreateEngagement.php +++ b/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/CreateEngagement.php @@ -36,7 +36,6 @@ namespace AdvisingApp\Engagement\Filament\Resources\EngagementResource\Pages; -use App\Filament\Fields\EducatableSelect; use Filament\Forms\Get; use Filament\Forms\Set; use Filament\Forms\Form; @@ -46,16 +45,14 @@ use Filament\Forms\Components\Checkbox; use Filament\Forms\Components\Fieldset; use Filament\Forms\Components\TextInput; -use AdvisingApp\Prospect\Models\Prospect; +use App\Filament\Fields\EducatableSelect; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Expression; use Filament\Resources\Pages\CreateRecord; -use Filament\Forms\Components\MorphToSelect; use FilamentTiptapEditor\Enums\TiptapOutput; use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\DateTimePicker; use AdvisingApp\Engagement\Models\EmailTemplate; -use AdvisingApp\StudentDataModel\Models\Student; use Filament\Resources\Pages\ManageRelatedRecords; use Filament\Resources\RelationManagers\RelationManager; use AdvisingApp\Engagement\Enums\EngagementDeliveryMethod; diff --git a/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/EditEngagement.php b/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/EditEngagement.php index 55f96ef382..107ba99394 100644 --- a/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/EditEngagement.php +++ b/app-modules/engagement/src/Filament/Resources/EngagementResource/Pages/EditEngagement.php @@ -36,7 +36,6 @@ namespace AdvisingApp\Engagement\Filament\Resources\EngagementResource\Pages; -use App\Filament\Fields\EducatableSelect; use Filament\Forms\Get; use Filament\Forms\Set; use Filament\Forms\Form; @@ -50,16 +49,14 @@ use Filament\Forms\Components\Fieldset; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; -use AdvisingApp\Prospect\Models\Prospect; +use App\Filament\Fields\EducatableSelect; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Expression; -use Filament\Forms\Components\MorphToSelect; use FilamentTiptapEditor\Enums\TiptapOutput; use AdvisingApp\Engagement\Models\Engagement; use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\DateTimePicker; use AdvisingApp\Engagement\Models\EmailTemplate; -use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\Engagement\Enums\EngagementDeliveryMethod; use AdvisingApp\Engagement\Filament\Resources\EngagementResource; use AdvisingApp\Engagement\Filament\Resources\EngagementResource\Fields\EngagementSmsBodyField; diff --git a/app-modules/engagement/src/Models/Engagement.php b/app-modules/engagement/src/Models/Engagement.php index 1db65d748c..197607d3a5 100644 --- a/app-modules/engagement/src/Models/Engagement.php +++ b/app-modules/engagement/src/Models/Engagement.php @@ -43,9 +43,9 @@ use OwenIt\Auditing\Contracts\Auditable; use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\Timeline\Models\Timeline; +use Illuminate\Database\Eloquent\Builder; use AdvisingApp\StudentDataModel\Models\Student; use Illuminate\Database\Eloquent\Relations\HasOne; -use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\MorphOne; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -56,6 +56,7 @@ use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\Engagement\Actions\GenerateEmailMarkdownContent; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Notification\Models\Contracts\CanTriggerAutoSubscription; /** @@ -66,6 +67,7 @@ class Engagement extends BaseModel implements Auditable, CanTriggerAutoSubscription, ProvidesATimeline { use AuditableTrait; + use BelongsToEducatable; protected $fillable = [ 'user_id', @@ -205,4 +207,11 @@ public function getMergeData(): array 'student email' => $this->recipient->getAttribute($this->recipient->displayEmailKey()), ]; } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->licensedToEducatable('recipient'); + }); + } } diff --git a/app-modules/engagement/src/Policies/EngagementPolicy.php b/app-modules/engagement/src/Policies/EngagementPolicy.php index 1d31f947ab..903c91e0b7 100644 --- a/app-modules/engagement/src/Policies/EngagementPolicy.php +++ b/app-modules/engagement/src/Policies/EngagementPolicy.php @@ -39,11 +39,16 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; use AdvisingApp\Engagement\Models\Engagement; +use AdvisingApp\Authorization\Enums\LicenseType; class EngagementPolicy { public function viewAny(Authenticatable $authenticatable): Response { + if (! $authenticatable->hasAnyLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])) { + return Response::deny('You do not have permission to view engagements.'); + } + return $authenticatable->canOrElse( abilities: 'engagement.view-any', denyResponse: 'You do not have permission to view engagements.' @@ -52,6 +57,10 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, Engagement $engagement): Response { + if (! $authenticatable->hasLicense($engagement->recipient?->getLicenseType())) { + return Response::deny('You do not have permission to view this engagement.'); + } + return $authenticatable->canOrElse( abilities: ['engagement.*.view', "engagement.{$engagement->id}.view"], denyResponse: 'You do not have permission to view this engagement.' @@ -72,6 +81,10 @@ public function update(Authenticatable $authenticatable, Engagement $engagement) return Response::deny('You do not have permission to update this engagement because it has already been delivered.'); } + if (! $authenticatable->hasLicense($engagement->recipient?->getLicenseType())) { + return Response::deny('You do not have permission to update this engagement.'); + } + return $authenticatable->canOrElse( abilities: ['engagement.*.update', "engagement.{$engagement->id}.update"], denyResponse: 'You do not have permission to update this engagement.' @@ -84,6 +97,10 @@ public function delete(Authenticatable $authenticatable, Engagement $engagement) return Response::deny('You do not have permission to delete this engagement because it has already been delivered.'); } + if (! $authenticatable->hasLicense($engagement->recipient?->getLicenseType())) { + return Response::deny('You do not have permission to delete this engagement.'); + } + return $authenticatable->canOrElse( abilities: ['engagement.*.delete', "engagement.{$engagement->id}.delete"], denyResponse: 'You do not have permission to delete this engagement.' @@ -92,6 +109,10 @@ public function delete(Authenticatable $authenticatable, Engagement $engagement) public function restore(Authenticatable $authenticatable, Engagement $engagement): Response { + if (! $authenticatable->hasLicense($engagement->recipient?->getLicenseType())) { + return Response::deny('You do not have permission to restore this engagement.'); + } + return $authenticatable->canOrElse( abilities: ['engagement.*.restore', "engagement.{$engagement->id}.restore"], denyResponse: 'You do not have permission to restore this engagement.' @@ -104,6 +125,10 @@ public function forceDelete(Authenticatable $authenticatable, Engagement $engage return Response::deny('You cannot permanently delete this engagement because it has already been delivered.'); } + if (! $authenticatable->hasLicense($engagement->recipient?->getLicenseType())) { + return Response::deny('You do not have permission to permanently delete this engagement.'); + } + return $authenticatable->canOrElse( abilities: ['engagement.*.force-delete', "engagement.{$engagement->id}.force-delete"], denyResponse: 'You do not have permission to permanently delete this engagement.' diff --git a/app-modules/form/src/Filament/Resources/FormResource/Pages/Concerns/HasSharedFormConfiguration.php b/app-modules/form/src/Filament/Resources/FormResource/Pages/Concerns/HasSharedFormConfiguration.php index 74b78db340..d291edd0fd 100644 --- a/app-modules/form/src/Filament/Resources/FormResource/Pages/Concerns/HasSharedFormConfiguration.php +++ b/app-modules/form/src/Filament/Resources/FormResource/Pages/Concerns/HasSharedFormConfiguration.php @@ -36,26 +36,26 @@ namespace AdvisingApp\Form\Filament\Resources\FormResource\Pages\Concerns; -use AdvisingApp\Form\Enums\Rounding; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use Filament\Forms\Get; use AdvisingApp\Form\Models\Form; -use AdvisingApp\Form\Models\FormField; -use AdvisingApp\Form\Models\FormStep; +use Filament\Forms\Components\Grid; +use AdvisingApp\Form\Enums\Rounding; use AdvisingApp\Form\Rules\IsDomain; -use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; use App\Filament\Fields\ColorSelect; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Repeater; -use Filament\Forms\Components\Section; +use AdvisingApp\Form\Models\FormStep; use Filament\Forms\Components\Select; -use Filament\Forms\Components\TagsInput; +use Filament\Forms\Components\Toggle; +use AdvisingApp\Form\Models\FormField; +use Filament\Forms\Components\Section; +use FilamentTiptapEditor\TiptapEditor; +use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TagsInput; use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Get; use FilamentTiptapEditor\Enums\TiptapOutput; -use FilamentTiptapEditor\TiptapEditor; +use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; +use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; trait HasSharedFormConfiguration { diff --git a/app-modules/form/src/Models/Submission.php b/app-modules/form/src/Models/Submission.php index aa948d8ca1..863066fd29 100644 --- a/app-modules/form/src/Models/Submission.php +++ b/app-modules/form/src/Models/Submission.php @@ -38,11 +38,13 @@ use App\Models\BaseModel; use AdvisingApp\Prospect\Models\Prospect; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use AdvisingApp\StudentDataModel\Models\Student; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; /** * @property-read Submissible $submissible @@ -51,6 +53,8 @@ */ abstract class Submission extends BaseModel { + use BelongsToEducatable; + abstract public function submissible(): BelongsTo; abstract public function fields(): BelongsToMany; @@ -60,4 +64,11 @@ public function author(): MorphTo return $this ->morphTo('author'); } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->licensedToEducatable('author'); + }); + } } diff --git a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php index 0b44739cdc..4c31e07ac2 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php @@ -46,6 +46,7 @@ use Filament\Resources\Pages\CreateRecord; use Filament\Forms\Components\MorphToSelect; use Filament\Forms\Components\DateTimePicker; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\Interaction\Models\InteractionType; @@ -72,9 +73,9 @@ public function form(Form $form): Form ->searchable() ->required() ->types([ - ...(auth()->user()->canAccessStudents() ? [MorphToSelect\Type::make(Student::class) + ...(auth()->user()->hasLicense(LicenseType::RetentionCrm) ? [MorphToSelect\Type::make(Student::class) ->titleAttribute(Student::displayNameKey())] : []), - ...(auth()->user()->canAccessProspects() ? [MorphToSelect\Type::make(Prospect::class) + ...(auth()->user()->hasLicense(LicenseType::RecruitmentCrm) ? [MorphToSelect\Type::make(Prospect::class) ->titleAttribute(Prospect::displayNameKey())] : []), MorphToSelect\Type::make(ServiceRequest::class) ->label('Service Request') diff --git a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php index 5e03823ca2..ca6a484056 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php @@ -47,6 +47,7 @@ use AdvisingApp\Prospect\Models\Prospect; use Filament\Forms\Components\MorphToSelect; use Filament\Forms\Components\DateTimePicker; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\Interaction\Models\InteractionType; use AdvisingApp\Interaction\Models\InteractionDriver; @@ -71,9 +72,9 @@ public function form(Form $form): Form ->searchable() ->required() ->types([ - ...(auth()->user()->canAccessStudents() ? [MorphToSelect\Type::make(Student::class) + ...(auth()->user()->hasLicense(LicenseType::RetentionCrm) ? [MorphToSelect\Type::make(Student::class) ->titleAttribute(Student::displayNameKey())] : []), - ...(auth()->user()->canAccessProspects() ? [MorphToSelect\Type::make(Prospect::class) + ...(auth()->user()->hasLicense(LicenseType::RecruitmentCrm) ? [MorphToSelect\Type::make(Prospect::class) ->titleAttribute(Prospect::displayNameKey())] : []), MorphToSelect\Type::make(ServiceRequest::class) ->label('Service Request') diff --git a/app-modules/interaction/src/Models/Interaction.php b/app-modules/interaction/src/Models/Interaction.php index a72002c23d..4bbddadc90 100644 --- a/app-modules/interaction/src/Models/Interaction.php +++ b/app-modules/interaction/src/Models/Interaction.php @@ -42,12 +42,14 @@ use Illuminate\Support\Collection; use OwenIt\Auditing\Contracts\Auditable; use AdvisingApp\Division\Models\Division; +use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Campaign\Models\CampaignAction; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Notification\Models\Contracts\Subscribable; use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; use AdvisingApp\Notification\Models\Contracts\CanTriggerAutoSubscription; @@ -57,6 +59,7 @@ class Interaction extends BaseModel implements Auditable, CanTriggerAutoSubscription, ExecutableFromACampaignAction { use AuditableTrait; + use BelongsToEducatable; protected $fillable = [ 'user_id', @@ -164,4 +167,11 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s // Do we need to be able to relate campaigns/actions to the RESULT of their actions? } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->licensedToEducatable('interactable'); + }); + } } diff --git a/app-modules/interaction/src/Policies/InteractionPolicy.php b/app-modules/interaction/src/Policies/InteractionPolicy.php index 929427cddf..f21f5ffd0c 100644 --- a/app-modules/interaction/src/Policies/InteractionPolicy.php +++ b/app-modules/interaction/src/Policies/InteractionPolicy.php @@ -39,6 +39,7 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; use AdvisingApp\Interaction\Models\Interaction; +use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; class InteractionPolicy { @@ -52,6 +53,13 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, Interaction $interaction): Response { + if ( + ($interaction->interactable instanceof Educatable) && + (! $authenticatable->hasLicense($interaction->interactable->getLicenseType())) + ) { + return Response::deny('You do not have permission to view this interaction.'); + } + return $authenticatable->canOrElse( abilities: ['interaction.*.view', "interaction.{$interaction->id}.view"], denyResponse: 'You do not have permission to view this interaction.' @@ -68,6 +76,13 @@ public function create(Authenticatable $authenticatable): Response public function update(Authenticatable $authenticatable, Interaction $interaction): Response { + if ( + ($interaction->interactable instanceof Educatable) && + (! $authenticatable->hasLicense($interaction->interactable->getLicenseType())) + ) { + return Response::deny('You do not have permission to update this interaction.'); + } + return $authenticatable->canOrElse( abilities: ['interaction.*.update', "interaction.{$interaction->id}.update"], denyResponse: 'You do not have permission to update this interaction.' @@ -76,6 +91,13 @@ public function update(Authenticatable $authenticatable, Interaction $interactio public function delete(Authenticatable $authenticatable, Interaction $interaction): Response { + if ( + ($interaction->interactable instanceof Educatable) && + (! $authenticatable->hasLicense($interaction->interactable->getLicenseType())) + ) { + return Response::deny('You do not have permission to delete this interaction.'); + } + return $authenticatable->canOrElse( abilities: ['interaction.*.delete', "interaction.{$interaction->id}.delete"], denyResponse: 'You do not have permission to delete this interaction.' @@ -84,6 +106,13 @@ public function delete(Authenticatable $authenticatable, Interaction $interactio public function restore(Authenticatable $authenticatable, Interaction $interaction): Response { + if ( + ($interaction->interactable instanceof Educatable) && + (! $authenticatable->hasLicense($interaction->interactable->getLicenseType())) + ) { + return Response::deny('You do not have permission to restore this interaction.'); + } + return $authenticatable->canOrElse( abilities: ['interaction.*.restore', "interaction.{$interaction->id}.restore"], denyResponse: 'You do not have permission to restore this interaction.' @@ -92,6 +121,13 @@ public function restore(Authenticatable $authenticatable, Interaction $interacti public function forceDelete(Authenticatable $authenticatable, Interaction $interaction): Response { + if ( + ($interaction->interactable instanceof Educatable) && + (! $authenticatable->hasLicense($interaction->interactable->getLicenseType())) + ) { + return Response::deny('You do not have permission to permanently delete this interaction.'); + } + return $authenticatable->canOrElse( abilities: ['interaction.*.force-delete', "interaction.{$interaction->id}.force-delete"], denyResponse: 'You do not have permission to permanently delete this interaction.' diff --git a/app-modules/notification/src/Models/Subscription.php b/app-modules/notification/src/Models/Subscription.php index e84c87cc32..165406157a 100644 --- a/app-modules/notification/src/Models/Subscription.php +++ b/app-modules/notification/src/Models/Subscription.php @@ -40,6 +40,7 @@ use App\Models\User; use DateTimeInterface; use Illuminate\Support\Facades\DB; +use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Campaign\Models\CampaignAction; use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Relations\MorphTo; @@ -49,6 +50,7 @@ use AdvisingApp\Notification\Actions\SubscriptionCreate; use AdvisingApp\Notification\Models\Contracts\Subscribable; use AdvisingApp\Authorization\Models\Concerns\DefinesPermissions; +use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; /** @@ -56,6 +58,7 @@ */ class Subscription extends MorphPivot implements ExecutableFromACampaignAction { + use BelongsToEducatable; use HasFactory; use DefinesPermissions; use HasUuids; @@ -109,6 +112,13 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s // Do we need to be able to relate campaigns/actions to the RESULT of their actions? } + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->licensedToEducatable('subscribable'); + }); + } + protected function serializeDate(DateTimeInterface $date): string { return $date->format(config('project.datetime_format') ?? 'Y-m-d H:i:s'); diff --git a/app-modules/notification/src/Policies/SubscriptionPolicy.php b/app-modules/notification/src/Policies/SubscriptionPolicy.php index 1c45130294..4c1f7bc6d3 100644 --- a/app-modules/notification/src/Policies/SubscriptionPolicy.php +++ b/app-modules/notification/src/Policies/SubscriptionPolicy.php @@ -52,6 +52,10 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, Subscription $subscription): Response { + if (! $authenticatable->hasLicense($subscription->subscribable?->getLicenseType())) { + return Response::deny('You do not have permission to view this alert.'); + } + return $authenticatable->canOrElse( abilities: ['subscription.*.view', "subscription.{$subscription->id}.view"], denyResponse: 'You do not have permission to view this subscription.' @@ -68,6 +72,10 @@ public function create(Authenticatable $authenticatable): Response public function update(Authenticatable $authenticatable, Subscription $subscription): Response { + if (! $authenticatable->hasLicense($subscription->subscribable?->getLicenseType())) { + return Response::deny('You do not have permission to update this subscription.'); + } + return $authenticatable->canOrElse( abilities: ['subscription.*.update', "subscription.{$subscription->id}.update"], denyResponse: 'You do not have permission to update this subscription.' @@ -76,6 +84,10 @@ public function update(Authenticatable $authenticatable, Subscription $subscript public function delete(Authenticatable $authenticatable, Subscription $subscription): Response { + if (! $authenticatable->hasLicense($subscription->subscribable?->getLicenseType())) { + return Response::deny('You do not have permission to delete this subscription.'); + } + return $authenticatable->canOrElse( abilities: ['subscription.*.delete', "subscription.{$subscription->id}.delete"], denyResponse: 'You do not have permission to delete this subscription.' @@ -84,6 +96,10 @@ public function delete(Authenticatable $authenticatable, Subscription $subscript public function restore(Authenticatable $authenticatable, Subscription $subscription): Response { + if (! $authenticatable->hasLicense($subscription->subscribable?->getLicenseType())) { + return Response::deny('You do not have permission to restore this subscription.'); + } + return $authenticatable->canOrElse( abilities: ['subscription.*.restore', "subscription.{$subscription->id}.restore"], denyResponse: 'You do not have permission to restore this subscription.' @@ -92,6 +108,10 @@ public function restore(Authenticatable $authenticatable, Subscription $subscrip public function forceDelete(Authenticatable $authenticatable, Subscription $subscription): Response { + if (! $authenticatable->hasLicense($subscription->subscribable?->getLicenseType())) { + return Response::deny('You do not have permission to permanently delete this subscription.'); + } + return $authenticatable->canOrElse( abilities: ['subscription.*.force-delete', "subscription.{$subscription->id}.force-delete"], denyResponse: 'You do not have permission to permanently delete this subscription.' diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php index 742cae01c9..2548748ea3 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php @@ -44,9 +44,11 @@ use Filament\Forms\Components\TextInput; use AdvisingApp\Prospect\Models\Prospect; use Filament\Forms\Components\DatePicker; +use Illuminate\Database\Eloquent\Builder; use Filament\Resources\Pages\CreateRecord; use AdvisingApp\Prospect\Models\ProspectSource; use AdvisingApp\Prospect\Models\ProspectStatus; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Prospect\Filament\Resources\ProspectResource; class CreateProspect extends CreateRecord @@ -133,7 +135,11 @@ public function form(Form $form): Form ->maxValue(now()->addYears(25)->year), Select::make('assigned_to_id') ->label('Assigned To') - ->relationship('assignedTo', 'name') + ->relationship( + 'assignedTo', + 'name', + fn (Builder $query) => $query->hasLicense(LicenseType::RecruitmentCrm), + ) ->searchable() ->nullable() ->exists( diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php index ec40d0a8a6..4b854381de 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php @@ -47,8 +47,10 @@ use Filament\Resources\Pages\EditRecord; use AdvisingApp\Prospect\Models\Prospect; use Filament\Forms\Components\DatePicker; +use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Prospect\Models\ProspectSource; use AdvisingApp\Prospect\Models\ProspectStatus; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Prospect\Filament\Resources\ProspectResource; class EditProspect extends EditRecord @@ -136,12 +138,16 @@ public function form(Form $form): Form ->maxValue(now()->addYears(25)->year), Select::make('assigned_to_id') ->label('Assigned To') - ->relationship('assignedTo', 'name') + ->relationship( + 'assignedTo', + 'name', + fn (Builder $query) => $query->hasLicense(LicenseType::RecruitmentCrm), + ) ->searchable() ->nullable() ->exists( table: (new User())->getTable(), - column: (new User())->getKeyName() + column: (new User())->getKeyName(), ), Select::make('created_by_id') ->label('Created By') diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php index 5d4937933f..f6c52eb8d6 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php @@ -45,8 +45,10 @@ use AdvisingApp\Prospect\Models\Prospect; use Filament\Tables\Actions\AttachAction; use Filament\Tables\Actions\DetachAction; +use Illuminate\Database\Eloquent\Builder; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DetachBulkAction; +use AdvisingApp\Authorization\Enums\LicenseType; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\Prospect\Filament\Resources\ProspectResource; @@ -93,6 +95,9 @@ public function table(Table $table): Table ->recordSelect( fn (Select $select) => $select->placeholder('Select a User'), ) + ->recordSelectOptionsQuery( + fn (Builder $query) => $query->hasLicense(LicenseType::RecruitmentCrm), + ) ->successNotificationTitle(function (User $record) { /** @var Prospect $prospect */ $prospect = $this->getOwnerRecord(); diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php index 1e1e6e9c59..5b5ddbb874 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php @@ -45,8 +45,10 @@ use AdvisingApp\Prospect\Models\Prospect; use Filament\Tables\Actions\AttachAction; use Filament\Tables\Actions\DetachAction; +use Illuminate\Database\Eloquent\Builder; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DetachBulkAction; +use AdvisingApp\Authorization\Enums\LicenseType; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\Prospect\Filament\Resources\ProspectResource; @@ -95,6 +97,9 @@ public function table(Table $table): Table ->recordSelect( fn (Select $select) => $select->placeholder('Select a User'), ) + ->recordSelectOptionsQuery( + fn (Builder $query) => $query->hasLicense(LicenseType::RecruitmentCrm), + ) ->successNotificationTitle(function (User $record) { /** @var Prospect $prospect */ $prospect = $this->getOwnerRecord(); diff --git a/app-modules/prospect/src/Models/Prospect.php b/app-modules/prospect/src/Models/Prospect.php index 00baff3249..1387eee866 100644 --- a/app-modules/prospect/src/Models/Prospect.php +++ b/app-modules/prospect/src/Models/Prospect.php @@ -39,15 +39,18 @@ use App\Models\User; use DateTimeInterface; use App\Models\BaseModel; +use App\Models\Authenticatable; use AdvisingApp\Task\Models\Task; use Illuminate\Support\Collection; use AdvisingApp\Alert\Models\Alert; use Illuminate\Notifications\Notifiable; use OwenIt\Auditing\Contracts\Auditable; use AdvisingApp\CareTeam\Models\CareTeam; +use Illuminate\Database\Eloquent\Builder; use OpenSearch\ScoutDriverPlus\Searchable; use AdvisingApp\Form\Models\FormSubmission; use Illuminate\Database\Eloquent\SoftDeletes; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Engagement\Models\EngagementFile; use AdvisingApp\Notification\Models\Subscription; use Illuminate\Database\Eloquent\Casts\Attribute; @@ -217,7 +220,8 @@ public function careTeam(): MorphToMany ) ->using(CareTeam::class) ->withPivot('id') - ->withTimestamps(); + ->withTimestamps() + ->hasLicense($this->getLicenseType()); } public function formSubmissions(): MorphMany @@ -259,7 +263,29 @@ public function subscribedUsers(): MorphToMany ) ->using(Subscription::class) ->withPivot('id') - ->withTimestamps(); + ->withTimestamps() + ->hasLicense($this->getLicenseType()); + } + + public function getLicenseType(): LicenseType + { + return LicenseType::RecruitmentCrm; + } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + if (! auth()->check()) { + return; + } + + /** @var Authenticatable $user */ + $user = auth()->user(); + + if (! $user->hasLicense(LicenseType::RecruitmentCrm)) { + $builder->whereRaw('1 = 0'); + } + }); } protected function serializeDate(DateTimeInterface $date): string diff --git a/app-modules/prospect/src/Policies/ProspectPolicy.php b/app-modules/prospect/src/Policies/ProspectPolicy.php index a3fb6742fb..c378359f86 100644 --- a/app-modules/prospect/src/Policies/ProspectPolicy.php +++ b/app-modules/prospect/src/Policies/ProspectPolicy.php @@ -39,12 +39,13 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; use AdvisingApp\Prospect\Models\Prospect; +use AdvisingApp\Authorization\Enums\LicenseType; class ProspectPolicy { public function viewAny(Authenticatable $authenticatable): Response { - if (! $authenticatable->canAccessProspects()) { + if (! $authenticatable->hasLicense(LicenseType::RecruitmentCrm)) { return Response::deny('You do not have permission to view prospects.'); } diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/CreateServiceRequest.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/CreateServiceRequest.php index f2ec035cb4..c2ca513929 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/CreateServiceRequest.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/CreateServiceRequest.php @@ -36,16 +36,13 @@ namespace AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestResource\Pages; -use App\Filament\Fields\EducatableSelect; use Filament\Forms\Form; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; use AdvisingApp\Division\Models\Division; -use AdvisingApp\Prospect\Models\Prospect; +use App\Filament\Fields\EducatableSelect; use Illuminate\Database\Eloquent\Builder; use Filament\Resources\Pages\CreateRecord; -use Filament\Forms\Components\MorphToSelect; -use AdvisingApp\StudentDataModel\Models\Student; use Filament\Resources\Pages\ManageRelatedRecords; use Filament\Resources\RelationManagers\RelationManager; use AdvisingApp\ServiceManagement\Models\ServiceRequestType; diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/EditServiceRequest.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/EditServiceRequest.php index 4ff35982b6..6535df0f40 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/EditServiceRequest.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/EditServiceRequest.php @@ -36,17 +36,14 @@ namespace AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestResource\Pages; -use App\Filament\Fields\EducatableSelect; use Filament\Actions; use Filament\Forms\Form; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; use Filament\Resources\Pages\EditRecord; use AdvisingApp\Division\Models\Division; -use AdvisingApp\Prospect\Models\Prospect; +use App\Filament\Fields\EducatableSelect; use Illuminate\Database\Eloquent\Builder; -use Filament\Forms\Components\MorphToSelect; -use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\ServiceManagement\Models\ServiceRequestType; use AdvisingApp\ServiceManagement\Models\ServiceRequestStatus; use AdvisingApp\ServiceManagement\Models\ServiceRequestPriority; diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/RelationManagers/AssignedToRelationManager.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/RelationManagers/AssignedToRelationManager.php index aa6ce609ef..2af2d6c64a 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/RelationManagers/AssignedToRelationManager.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/RelationManagers/AssignedToRelationManager.php @@ -46,6 +46,7 @@ use Filament\Tables\Columns\TextColumn; use App\Filament\Resources\UserResource; use Filament\Forms\Components\TextInput; +use Illuminate\Database\Query\Expression; use AdvisingApp\ServiceManagement\Models\ServiceRequest; use App\Filament\Resources\RelationManagers\RelationManager; use AdvisingApp\ServiceManagement\Models\ServiceRequestAssignment; @@ -80,22 +81,21 @@ public function table(Table $table): Table Action::make('reassign-service-request') ->label('Reassign Service Request') ->color('gray') - ->action(function (array $data): void { - /** @var ServiceRequest $serviceRequest */ - $serviceRequest = $this->ownerRecord; - - $serviceRequest->assignments()->create([ - 'user_id' => $data['userId'], - 'assigned_by_id' => auth()->user()?->id ?? null, - 'assigned_at' => now(), - 'status' => ServiceRequestAssignmentStatus::Active, - ]); - }) + ->action(fn (array $data) => $this->getOwnerRecord()->assignments()->create([ + 'user_id' => $data['userId'], + 'assigned_by_id' => auth()->user()?->id ?? null, + 'assigned_at' => now(), + 'status' => ServiceRequestAssignmentStatus::Active, + ])) ->form([ Select::make('userId') ->label('Reassign Service Request To') ->searchable() - ->getSearchResultsUsing(fn (string $search): array => User::whereRaw('LOWER(name) LIKE ? ', ['%' . str($search)->lower() . '%'])->pluck('name', 'id')->toArray()) + ->getSearchResultsUsing(fn (string $search): array => User::query() + ->hasLicense($this->getOwnerRecord()->respondent?->getLicenseType()) + ->where(new Expression('lower(name)'), 'like', '%' . str($search)->lower() . '%') + ->pluck('name', 'id') + ->all()) ->getOptionLabelUsing(fn ($value): ?string => User::find($value)?->name) ->placeholder('Search for and select a User') ->required(), @@ -106,4 +106,12 @@ public function table(Table $table): Table ->url(fn (ServiceRequestAssignment $assignment) => UserResource::getUrl('view', ['record' => $assignment->user])), ]); } + + public function getOwnerRecord(): ServiceRequest + { + /** @var ServiceRequest $record */ + $record = parent::getOwnerRecord(); + + return $record; + } } diff --git a/app-modules/service-management/src/Models/ServiceRequest.php b/app-modules/service-management/src/Models/ServiceRequest.php index 1d4d1cf198..5cd2b3c32b 100644 --- a/app-modules/service-management/src/Models/ServiceRequest.php +++ b/app-modules/service-management/src/Models/ServiceRequest.php @@ -60,6 +60,7 @@ use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\StudentDataModel\Models\Contracts\Identifiable; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Interaction\Models\Concerns\HasManyMorphedInteractions; use AdvisingApp\ServiceManagement\Enums\ServiceRequestAssignmentStatus; use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; @@ -75,6 +76,7 @@ */ class ServiceRequest extends BaseModel implements Auditable, CanTriggerAutoSubscription, Identifiable, ExecutableFromACampaignAction { + use BelongsToEducatable; use SoftDeletes; use PowerJoins; use AuditableTrait; @@ -244,6 +246,13 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s } } + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->licensedToEducatable('respondent'); + }); + } + protected function serializeDate(DateTimeInterface $date): string { return $date->format(config('project.datetime_format') ?? 'Y-m-d H:i:s'); diff --git a/app-modules/service-management/src/Policies/ServiceRequestPolicy.php b/app-modules/service-management/src/Policies/ServiceRequestPolicy.php index 53a2e0d6ba..764e157912 100644 --- a/app-modules/service-management/src/Policies/ServiceRequestPolicy.php +++ b/app-modules/service-management/src/Policies/ServiceRequestPolicy.php @@ -57,6 +57,10 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, ServiceRequest $serviceRequest): Response { + if (! $authenticatable->hasLicense($serviceRequest->respondent?->getLicenseType())) { + return Response::deny('You do not have permission to view this service request.'); + } + return $authenticatable->canOrElse( abilities: ['service_request.*.view', "service_request.{$serviceRequest->id}.view"], denyResponse: 'You do not have permission to view this service request.' @@ -73,6 +77,10 @@ public function create(Authenticatable $authenticatable): Response public function update(Authenticatable $authenticatable, ServiceRequest $serviceRequest): Response { + if (! $authenticatable->hasLicense($serviceRequest->respondent?->getLicenseType())) { + return Response::deny('You do not have permission to update this service request.'); + } + return $authenticatable->canOrElse( abilities: ['service_request.*.update', "service_request.{$serviceRequest->id}.update"], denyResponse: 'You do not have permission to update this service request.' @@ -81,6 +89,10 @@ public function update(Authenticatable $authenticatable, ServiceRequest $service public function delete(Authenticatable $authenticatable, ServiceRequest $serviceRequest): Response { + if (! $authenticatable->hasLicense($serviceRequest->respondent?->getLicenseType())) { + return Response::deny('You do not have permission to delete this service request.'); + } + return $authenticatable->canOrElse( abilities: ['service_request.*.delete', "service_request.{$serviceRequest->id}.delete"], denyResponse: 'You do not have permission to delete this service request.' @@ -89,6 +101,10 @@ public function delete(Authenticatable $authenticatable, ServiceRequest $service public function restore(Authenticatable $authenticatable, ServiceRequest $serviceRequest): Response { + if (! $authenticatable->hasLicense($serviceRequest->respondent?->getLicenseType())) { + return Response::deny('You do not have permission to restore this service request.'); + } + return $authenticatable->canOrElse( abilities: ['service_request.*.restore', "service_request.{$serviceRequest->id}.restore"], denyResponse: 'You do not have permission to restore this service request.' @@ -97,6 +113,10 @@ public function restore(Authenticatable $authenticatable, ServiceRequest $servic public function forceDelete(Authenticatable $authenticatable, ServiceRequest $serviceRequest): Response { + if (! $authenticatable->hasLicense($serviceRequest->respondent?->getLicenseType())) { + return Response::deny('You do not have permission to permanently delete this service request.'); + } + return $authenticatable->canOrElse( abilities: ['service_request.*.force-delete', "service_request.{$serviceRequest->id}.force-delete"], denyResponse: 'You do not have permission to permanently delete this service request.' diff --git a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php index 13b99ce2cd..6735368010 100644 --- a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php +++ b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php @@ -44,8 +44,10 @@ use App\Filament\Resources\UserResource; use Filament\Tables\Actions\AttachAction; use Filament\Tables\Actions\DetachAction; +use Illuminate\Database\Eloquent\Builder; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DetachBulkAction; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\StudentDataModel\Filament\Resources\StudentResource; @@ -93,6 +95,9 @@ public function table(Table $table): Table ->recordSelect( fn (Select $select) => $select->placeholder('Select a User'), ) + ->recordSelectOptionsQuery( + fn (Builder $query) => $query->hasLicense(LicenseType::RetentionCrm), + ) ->successNotificationTitle(function (User $record) { /** @var Student $student */ $student = $this->getOwnerRecord(); diff --git a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php index 9dff21c43c..484ded5c89 100644 --- a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php +++ b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php @@ -44,8 +44,10 @@ use App\Filament\Resources\UserResource; use Filament\Tables\Actions\AttachAction; use Filament\Tables\Actions\DetachAction; +use Illuminate\Database\Eloquent\Builder; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DetachBulkAction; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\StudentDataModel\Filament\Resources\StudentResource; @@ -95,6 +97,9 @@ public function table(Table $table): Table ->recordSelect( fn (Select $select) => $select->placeholder('Select a User'), ) + ->recordSelectOptionsQuery( + fn (Builder $query) => $query->hasLicense(LicenseType::RetentionCrm), + ) ->successNotificationTitle(function (User $record) { /** @var Student $student */ $student = $this->getOwnerRecord(); diff --git a/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php b/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php new file mode 100644 index 0000000000..c0365eb6ee --- /dev/null +++ b/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php @@ -0,0 +1,43 @@ +check()) { + return $query; + } + + /** @var Authenticatable $user */ + $user = auth()->user(); + + if ( + (! method_exists($this, $relationship)) || + (! ($this->{$relationship}() instanceof MorphTo)) + ) { + throw new Exception('The [' . static::class . "] model does not have a [{$relationship}] [" . MorphTo::class . '] relationship where educatables can be assigned.'); + } + + $typeColumn = $this->{$relationship}()->getMorphType(); + + return $query + ->when( + ! $user->hasLicense(LicenseType::RetentionCrm), + fn (Builder $query) => $query->where($typeColumn, '!=', app(Student::class)->getMorphClass()), + ) + ->when( + ! $user->hasLicense(LicenseType::RecruitmentCrm), + fn (Builder $query) => $query->where($typeColumn, '!=', app(Prospect::class)->getMorphClass()), + ); + } +} diff --git a/app-modules/student-data-model/src/Models/Contracts/Educatable.php b/app-modules/student-data-model/src/Models/Contracts/Educatable.php index 0c6bbb8c3d..006bd09e3c 100644 --- a/app-modules/student-data-model/src/Models/Contracts/Educatable.php +++ b/app-modules/student-data-model/src/Models/Contracts/Educatable.php @@ -37,6 +37,7 @@ namespace AdvisingApp\StudentDataModel\Models\Contracts; use Illuminate\Database\Eloquent\Collection; +use AdvisingApp\Authorization\Enums\LicenseType; use Illuminate\Database\Eloquent\Relations\MorphToMany; /** @@ -49,4 +50,6 @@ public static function displayNameKey(): string; public static function displayEmailKey(): string; public function careTeam(): MorphToMany; + + public function getLicenseType(): LicenseType; } diff --git a/app-modules/student-data-model/src/Models/Student.php b/app-modules/student-data-model/src/Models/Student.php index 00d7c98355..9cf55e246c 100644 --- a/app-modules/student-data-model/src/Models/Student.php +++ b/app-modules/student-data-model/src/Models/Student.php @@ -37,6 +37,7 @@ namespace AdvisingApp\StudentDataModel\Models; use App\Models\User; +use App\Models\Authenticatable; use AdvisingApp\Task\Models\Task; use Illuminate\Support\Collection; use AdvisingApp\Alert\Models\Alert; @@ -44,7 +45,9 @@ use Illuminate\Notifications\Notifiable; use OwenIt\Auditing\Contracts\Auditable; use AdvisingApp\CareTeam\Models\CareTeam; +use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Form\Models\FormSubmission; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Engagement\Models\EngagementFile; use AdvisingApp\Notification\Models\Subscription; use Illuminate\Database\Eloquent\Casts\Attribute; @@ -192,7 +195,8 @@ public function careTeam(): MorphToMany ) ->using(CareTeam::class) ->withPivot('id') - ->withTimestamps(); + ->withTimestamps() + ->hasLicense($this->getLicenseType()); } public function subscribedUsers(): MorphToMany @@ -204,7 +208,8 @@ public function subscribedUsers(): MorphToMany ) ->using(Subscription::class) ->withPivot('id') - ->withTimestamps(); + ->withTimestamps() + ->hasLicense($this->getLicenseType()); } public static function filamentResource(): string @@ -222,6 +227,27 @@ public function getApiPermissions(): Collection return collect([]); } + public function getLicenseType(): LicenseType + { + return LicenseType::RetentionCrm; + } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + if (! auth()->check()) { + return; + } + + /** @var Authenticatable $user */ + $user = auth()->user(); + + if (! $user->hasLicense(LicenseType::RetentionCrm)) { + $builder->whereRaw('1 = 0'); + } + }); + } + protected function displayName(): Attribute { return Attribute::make( diff --git a/app-modules/student-data-model/src/Policies/StudentPolicy.php b/app-modules/student-data-model/src/Policies/StudentPolicy.php index 7157a5d018..aa95a1c832 100644 --- a/app-modules/student-data-model/src/Policies/StudentPolicy.php +++ b/app-modules/student-data-model/src/Policies/StudentPolicy.php @@ -38,13 +38,14 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; class StudentPolicy { public function viewAny(Authenticatable $authenticatable): Response { - if (! $authenticatable->canAccessStudents()) { + if (! $authenticatable->hasLicense(LicenseType::RetentionCrm)) { return Response::deny('You do not have permission to view students.'); } diff --git a/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/Concerns/HasSharedFormConfiguration.php b/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/Concerns/HasSharedFormConfiguration.php index 4cd81fc8c5..edcbb2881d 100644 --- a/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/Concerns/HasSharedFormConfiguration.php +++ b/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/Concerns/HasSharedFormConfiguration.php @@ -36,26 +36,26 @@ namespace AdvisingApp\Survey\Filament\Resources\SurveyResource\Pages\Concerns; +use Filament\Forms\Get; +use Filament\Forms\Components\Grid; use AdvisingApp\Form\Enums\Rounding; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use AdvisingApp\Form\Rules\IsDomain; -use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; -use AdvisingApp\Survey\Models\Survey; -use AdvisingApp\Survey\Models\SurveyField; -use AdvisingApp\Survey\Models\SurveyStep; use App\Filament\Fields\ColorSelect; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\Repeater; -use Filament\Forms\Components\Section; +use AdvisingApp\Survey\Models\Survey; use Filament\Forms\Components\Select; -use Filament\Forms\Components\TagsInput; +use Filament\Forms\Components\Toggle; +use Filament\Forms\Components\Section; +use FilamentTiptapEditor\TiptapEditor; +use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TagsInput; use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Get; +use AdvisingApp\Survey\Models\SurveyStep; +use AdvisingApp\Survey\Models\SurveyField; use FilamentTiptapEditor\Enums\TiptapOutput; -use FilamentTiptapEditor\TiptapEditor; +use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; +use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; trait HasSharedFormConfiguration { diff --git a/app-modules/task/src/Filament/Concerns/TaskEditForm.php b/app-modules/task/src/Filament/Concerns/TaskEditForm.php index 5340f9c8bd..a7814d8bb2 100644 --- a/app-modules/task/src/Filament/Concerns/TaskEditForm.php +++ b/app-modules/task/src/Filament/Concerns/TaskEditForm.php @@ -36,18 +36,16 @@ namespace AdvisingApp\Task\Filament\Concerns; -use App\Filament\Fields\EducatableSelect; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; -use AdvisingApp\Prospect\Models\Prospect; -use Filament\Forms\Components\MorphToSelect; +use App\Filament\Fields\EducatableSelect; use Filament\Forms\Components\DateTimePicker; -use AdvisingApp\StudentDataModel\Models\Student; -use Filament\Forms\Components\MorphToSelect\Type; trait TaskEditForm { + use TaskForm; + public function editFormFields(): array { return [ @@ -63,12 +61,13 @@ public function editFormFields(): array ->native(false), Select::make('assigned_to') ->label('Assigned To') - ->relationship('assignedTo', 'name') + ->relationship('assignedTo', 'name', $this->scopeAssignmentRelationshipBasedOnConcern()) ->nullable() ->searchable(['name', 'email']) ->default(auth()->id()), EducatableSelect::make('concern') - ->label('Related To'), + ->label('Related To') + ->afterStateUpdated($this->updateAssignmentAfterConcernSelected()), ]; } } diff --git a/app-modules/task/src/Filament/Concerns/TaskForm.php b/app-modules/task/src/Filament/Concerns/TaskForm.php new file mode 100644 index 0000000000..b4a3939561 --- /dev/null +++ b/app-modules/task/src/Filament/Concerns/TaskForm.php @@ -0,0 +1,125 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Task\Filament\Concerns; + +use Closure; +use App\Models\User; +use Filament\Forms\Get; +use Filament\Forms\Set; +use App\Models\Authenticatable; +use AdvisingApp\Prospect\Models\Prospect; +use Illuminate\Database\Eloquent\Builder; +use AdvisingApp\Authorization\Enums\LicenseType; +use AdvisingApp\StudentDataModel\Models\Student; +use Illuminate\Database\Eloquent\Relations\Relation; + +trait TaskForm +{ + protected function scopeAssignmentRelationshipBasedOnConcern(): Closure + { + return function (Get $get, Builder $query) { + $concernType = $get('concern_type'); + + if (filled($concernType = (Relation::getMorphedModel($concernType) ?? $concernType))) { + return match ($concernType) { + Student::class => $query->hasLicense(LicenseType::RetentionCrm), + Prospect::class => $query->hasLicense(LicenseType::RecruitmentCrm), + default => $query, + }; + } + + /** @var Authenticatable $user */ + $user = auth()->user(); + + $canAccessStudents = $user->hasLicense(LicenseType::RetentionCrm); + $canAccessProspects = $user->hasLicense(LicenseType::RecruitmentCrm); + + if ($canAccessStudents && $canAccessProspects) { + return $query; + } + + return match (true) { + $canAccessStudents => $query->hasLicense(LicenseType::RetentionCrm), + $canAccessProspects => $query->hasLicense(LicenseType::RecruitmentCrm), + default => $query, + }; + }; + } + + protected function updateAssignmentAfterConcernSelected(): Closure + { + return function (Get $get, Set $set) { + $concernId = $get('concern_id'); + + if (blank($concernId)) { + return; + } + + $assignedTo = $get('assigned_to'); + + if (blank($assignedTo)) { + return; + } + + /** @var Authenticatable $user */ + $user = auth()->user(); + + $canAccessStudents = $user->hasLicense(LicenseType::RetentionCrm); + $canAccessProspects = $user->hasLicense(LicenseType::RecruitmentCrm); + + $concernType = $get('concern_type'); + + if ($canAccessStudents && $canAccessProspects && blank($concernType)) { + return; + } + + $concernType = match (true) { + $canAccessStudents && $canAccessProspects => Relation::getMorphedModel($concernType) ?? $concernType, + $canAccessStudents => Student::class, + $canAccessProspects => Prospect::class, + }; + + $assignedTo = User::find($assignedTo); + + if ($assignedTo->hasLicense(app($concernType))->getLicenseType()) { + return; + } + + $set('assigned_to', null); + }; + } +} diff --git a/app-modules/task/src/Filament/RelationManagers/BaseTaskRelationManager.php b/app-modules/task/src/Filament/RelationManagers/BaseTaskRelationManager.php index 2933b48eb0..3e5e6f3d6b 100644 --- a/app-modules/task/src/Filament/RelationManagers/BaseTaskRelationManager.php +++ b/app-modules/task/src/Filament/RelationManagers/BaseTaskRelationManager.php @@ -52,6 +52,7 @@ use Filament\Tables\Actions\CreateAction; use Filament\Tables\Actions\DetachAction; use Filament\Tables\Filters\SelectFilter; +use Illuminate\Database\Eloquent\Builder; use Filament\Tables\Actions\BulkActionGroup; use Filament\Forms\Components\DateTimePicker; use Filament\Tables\Actions\DetachBulkAction; @@ -80,7 +81,11 @@ public function form(Form $form): Form ->native(false), Select::make('assigned_to') ->label('Assigned To') - ->relationship('assignedTo', 'name') + ->relationship( + 'assignedTo', + 'name', + fn (Builder $query) => $query->hasLicense($this->getOwnerRecord()->getLicenseType()), + ) ->nullable() ->searchable(['name', 'email']) ->default(auth()->id()), @@ -122,7 +127,11 @@ public function table(Table $table): Table ), SelectFilter::make('assignedTo') ->label('Assigned To') - ->relationship('assignedTo', 'name') + ->relationship( + 'assignedTo', + 'name', + fn (Builder $query) => $query->hasLicense($this->getOwnerRecord()->getLicenseType()), + ) ->searchable() ->multiple(), SelectFilter::make('status') diff --git a/app-modules/task/src/Filament/Resources/TaskResource/Pages/CreateTask.php b/app-modules/task/src/Filament/Resources/TaskResource/Pages/CreateTask.php index 62a9ffeced..a7e04605d9 100644 --- a/app-modules/task/src/Filament/Resources/TaskResource/Pages/CreateTask.php +++ b/app-modules/task/src/Filament/Resources/TaskResource/Pages/CreateTask.php @@ -36,7 +36,6 @@ namespace AdvisingApp\Task\Filament\Resources\TaskResource\Pages; -use App\Filament\Fields\EducatableSelect; use Filament\Forms\Form; use Illuminate\Support\Arr; use AdvisingApp\Task\Models\Task; @@ -44,16 +43,16 @@ use Filament\Forms\Components\Textarea; use Illuminate\Database\Eloquent\Model; use Filament\Forms\Components\TextInput; -use AdvisingApp\Prospect\Models\Prospect; +use App\Filament\Fields\EducatableSelect; use Filament\Resources\Pages\CreateRecord; -use Filament\Forms\Components\MorphToSelect; use Filament\Forms\Components\DateTimePicker; -use AdvisingApp\StudentDataModel\Models\Student; -use Filament\Forms\Components\MorphToSelect\Type; +use AdvisingApp\Task\Filament\Concerns\TaskForm; use AdvisingApp\Task\Filament\Resources\TaskResource; class CreateTask extends CreateRecord { + use TaskForm; + protected static string $resource = TaskResource::class; public function form(Form $form): Form @@ -72,12 +71,13 @@ public function form(Form $form): Form ->native(false), Select::make('assigned_to') ->label('Assigned To') - ->relationship('assignedTo', 'name') + ->relationship('assignedTo', 'name', $this->scopeAssignmentRelationshipBasedOnConcern()) ->nullable() ->searchable(['name', 'email']) ->default(auth()->id()), EducatableSelect::make('concern') - ->label('Related To'), + ->label('Related To') + ->afterStateUpdated($this->updateAssignmentAfterConcernSelected()), ]); } diff --git a/app-modules/task/src/Models/Task.php b/app-modules/task/src/Models/Task.php index c73221c2d3..8fdbd5560b 100644 --- a/app-modules/task/src/Models/Task.php +++ b/app-modules/task/src/Models/Task.php @@ -56,6 +56,7 @@ use AdvisingApp\Notification\Models\Contracts\Subscribable; use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; use AdvisingApp\Notification\Models\Contracts\CanTriggerAutoSubscription; @@ -66,6 +67,7 @@ */ class Task extends BaseModel implements Auditable, CanTriggerAutoSubscription, ExecutableFromACampaignAction { + use BelongsToEducatable; use HasFactory; use HasUuids; use AuditableTrait; @@ -162,4 +164,11 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s // Do we need to be able to relate campaigns/actions to the RESULT of their actions? } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->licensedToEducatable('concern'); + }); + } } diff --git a/app-modules/task/src/Policies/TaskPolicy.php b/app-modules/task/src/Policies/TaskPolicy.php index 8cfd7703ff..6d3dc1fca7 100644 --- a/app-modules/task/src/Policies/TaskPolicy.php +++ b/app-modules/task/src/Policies/TaskPolicy.php @@ -52,6 +52,10 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, Task $task): Response { + if (! $authenticatable->hasLicense($task->concern?->getLicenseType())) { + return Response::deny('You do not have permission to view this task.'); + } + return $authenticatable->canOrElse( abilities: ['task.*.view', "task.{$task->id}.view"], denyResponse: 'You do not have permission to view this task.' @@ -68,6 +72,10 @@ public function create(Authenticatable $authenticatable): Response public function update(Authenticatable $authenticatable, Task $task): Response { + if (! $authenticatable->hasLicense($task->concern?->getLicenseType())) { + return Response::deny('You do not have permission to update this task.'); + } + return $authenticatable->canOrElse( abilities: ['task.*.update', "task.{$task->id}.update"], denyResponse: 'You do not have permission to update this task.' @@ -76,6 +84,10 @@ public function update(Authenticatable $authenticatable, Task $task): Response public function delete(Authenticatable $authenticatable, Task $task): Response { + if (! $authenticatable->hasLicense($task->concern?->getLicenseType())) { + return Response::deny('You do not have permission to delete this task.'); + } + return $authenticatable->canOrElse( abilities: ['task.*.delete', "task.{$task->id}.delete"], denyResponse: 'You do not have permission to delete this task.' @@ -84,6 +96,10 @@ public function delete(Authenticatable $authenticatable, Task $task): Response public function restore(Authenticatable $authenticatable, Task $task): Response { + if (! $authenticatable->hasLicense($task->concern?->getLicenseType())) { + return Response::deny('You do not have permission to restore this task.'); + } + return $authenticatable->canOrElse( abilities: ['task.*.restore', "task.{$task->id}.restore"], denyResponse: 'You do not have permission to restore this task.' @@ -92,6 +108,10 @@ public function restore(Authenticatable $authenticatable, Task $task): Response public function forceDelete(Authenticatable $authenticatable, Task $task): Response { + if (! $authenticatable->hasLicense($task->concern?->getLicenseType())) { + return Response::deny('You do not have permission to permanently delete this task.'); + } + return $authenticatable->canOrElse( abilities: ['task.*.force-delete', "task.{$task->id}.force-delete"], denyResponse: 'You do not have permission to permanently delete this task.' diff --git a/app/Filament/Fields/ColorSelect.php b/app/Filament/Fields/ColorSelect.php index 51ca0c0638..023b388510 100644 --- a/app/Filament/Fields/ColorSelect.php +++ b/app/Filament/Fields/ColorSelect.php @@ -36,8 +36,8 @@ namespace App\Filament\Fields; -use Filament\Forms\Components\Select; use Filament\Support\Colors\Color; +use Filament\Forms\Components\Select; class ColorSelect extends Select { diff --git a/app/Filament/Fields/EducatableSelect.php b/app/Filament/Fields/EducatableSelect.php index cc324d878f..ef084ba849 100644 --- a/app/Filament/Fields/EducatableSelect.php +++ b/app/Filament/Fields/EducatableSelect.php @@ -2,20 +2,17 @@ namespace App\Filament\Fields; -use AdvisingApp\Authorization\Enums\LicenseType; -use AdvisingApp\Prospect\Models\Prospect; -use AdvisingApp\StudentDataModel\Models\Student; use Closure; -use Exception; -use Filament\Forms\Components\Component; -use Filament\Forms\Components\Concerns\HasName; -use Filament\Forms\Components\Group; +use App\Models\Authenticatable; use Filament\Forms\Components\Hidden; +use Filament\Forms\Components\Select; +use Filament\Forms\Components\Component; +use AdvisingApp\Prospect\Models\Prospect; use Filament\Forms\Components\MorphToSelect; +use Filament\Forms\Components\Concerns\HasName; +use AdvisingApp\Authorization\Enums\LicenseType; +use AdvisingApp\StudentDataModel\Models\Student; use Filament\Forms\Components\MorphToSelect\Type; -use Filament\Forms\Components\Select; -use Filament\Forms\Get; -use Filament\Forms\Set; use Illuminate\Database\Eloquent\Relations\MorphTo; class EducatableSelect extends Component @@ -62,9 +59,12 @@ public static function getProspectType(): Type public function getChildComponents(): array { + /** @var Authenticatable $user */ + $user = auth()->user(); + $type = match (true) { - auth()->user()->hasLicense(LicenseType::RetentionCrm) => static::getStudentType(), - auth()->user()->hasLicense(LicenseType::RecruitmentCrm) => static::getProspectType(), + $user->hasLicense(LicenseType::RetentionCrm) => static::getStudentType(), + $user->hasLicense(LicenseType::RecruitmentCrm) => static::getProspectType(), default => null, }; @@ -83,7 +83,10 @@ public function getChildComponents(): array ->getSearchResultsUsing($type->getSearchResultsUsing) ->getOptionLabelUsing($type->getOptionLabelUsing) ->required($this->isRequired()) - ->searchable(), + ->searchable() + ->afterStateUpdated(function () { + $this->callAfterStateUpdated(); + }), ]; } diff --git a/app/Filament/Resources/NotificationSettingResource/Pages/CreateNotificationSetting.php b/app/Filament/Resources/NotificationSettingResource/Pages/CreateNotificationSetting.php index b269579e47..db1e1592e0 100644 --- a/app/Filament/Resources/NotificationSettingResource/Pages/CreateNotificationSetting.php +++ b/app/Filament/Resources/NotificationSettingResource/Pages/CreateNotificationSetting.php @@ -36,14 +36,14 @@ namespace App\Filament\Resources\NotificationSettingResource\Pages; +use Filament\Forms\Form; use App\Filament\Fields\ColorSelect; -use App\Filament\Pages\EmailConfiguration; -use App\Filament\Resources\NotificationSettingResource; -use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; +use App\Filament\Pages\EmailConfiguration; use Filament\Resources\Pages\CreateRecord; +use App\Filament\Resources\NotificationSettingResource; +use Filament\Forms\Components\SpatieMediaLibraryFileUpload; class CreateNotificationSetting extends CreateRecord { diff --git a/app/Filament/Resources/NotificationSettingResource/Pages/EditNotificationSetting.php b/app/Filament/Resources/NotificationSettingResource/Pages/EditNotificationSetting.php index 57cbf5dcc4..e3f36a2e49 100644 --- a/app/Filament/Resources/NotificationSettingResource/Pages/EditNotificationSetting.php +++ b/app/Filament/Resources/NotificationSettingResource/Pages/EditNotificationSetting.php @@ -36,15 +36,15 @@ namespace App\Filament\Resources\NotificationSettingResource\Pages; -use App\Filament\Fields\ColorSelect; -use App\Filament\Pages\EmailConfiguration; -use App\Filament\Resources\NotificationSettingResource; +use Filament\Forms\Form; use Filament\Actions\DeleteAction; -use Filament\Forms\Components\SpatieMediaLibraryFileUpload; +use App\Filament\Fields\ColorSelect; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; -use Filament\Forms\Form; use Filament\Resources\Pages\EditRecord; +use App\Filament\Pages\EmailConfiguration; +use App\Filament\Resources\NotificationSettingResource; +use Filament\Forms\Components\SpatieMediaLibraryFileUpload; class EditNotificationSetting extends EditRecord { diff --git a/app/Livewire/TaskKanban.php b/app/Livewire/TaskKanban.php index f31b227225..32a1237a6d 100644 --- a/app/Livewire/TaskKanban.php +++ b/app/Livewire/TaskKanban.php @@ -36,7 +36,6 @@ namespace App\Livewire; -use App\Filament\Fields\EducatableSelect; use Exception; use Livewire\Component; use Illuminate\Support\Arr; @@ -51,13 +50,10 @@ use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Notifications\Notification; -use AdvisingApp\Prospect\Models\Prospect; +use App\Filament\Fields\EducatableSelect; use Filament\Actions\Contracts\HasActions; -use Filament\Forms\Components\MorphToSelect; use Filament\Forms\Components\DateTimePicker; use Filament\Forms\Concerns\InteractsWithForms; -use AdvisingApp\StudentDataModel\Models\Student; -use Filament\Forms\Components\MorphToSelect\Type; use Filament\Actions\Concerns\InteractsWithActions; use AdvisingApp\Task\Filament\Concerns\TaskEditForm; use Filament\Widgets\Concerns\InteractsWithPageTable; diff --git a/app/Models/Authenticatable.php b/app/Models/Authenticatable.php index 7a2a600d93..0490b7dbb7 100644 --- a/app/Models/Authenticatable.php +++ b/app/Models/Authenticatable.php @@ -37,6 +37,7 @@ namespace App\Models; use App\Models\Concerns\CanOrElse; +use AdvisingApp\Authorization\Enums\LicenseType; use Illuminate\Foundation\Auth\User as BaseAuthenticatable; use AdvisingApp\Authorization\Models\Concerns\HasRoleGroups; use AdvisingApp\Authorization\Models\Concerns\HasRolesWithPivot; @@ -50,4 +51,14 @@ abstract class Authenticatable extends BaseAuthenticatable use HasRolesWithPivot; use DefinesPermissions; use CanOrElse; + + /** + * @param LicenseType | string | array | null $type + */ + abstract public function hasLicense(LicenseType | string | array | null $type): bool; + + /** + * @param LicenseType | string | array | null $type + */ + abstract public function hasAnyLicense(LicenseType | string | array | null $type): bool; } diff --git a/app/Models/SystemUser.php b/app/Models/SystemUser.php index 99f8b19b2b..9809b962d3 100644 --- a/app/Models/SystemUser.php +++ b/app/Models/SystemUser.php @@ -36,9 +36,11 @@ namespace App\Models; +use Illuminate\Support\Arr; use Laravel\Sanctum\HasApiTokens; use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\SoftDeletes; +use AdvisingApp\Authorization\Enums\LicenseType; use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; @@ -57,4 +59,48 @@ class SystemUser extends Authenticatable implements Auditable protected $fillable = [ 'name', ]; + + /** + * @param LicenseType | string | array| null $type + */ + public function hasLicense(LicenseType | string | array | null $type): bool + { + if (blank($type)) { + return true; + } + + foreach (Arr::wrap($type) as $type) { + if (! ($type instanceof LicenseType)) { + $type = LicenseType::from($type); + } + + if (! $type->isLicenseable()) { + return false; + } + } + + return true; + } + + /** + * @param LicenseType | string | array | null $type + */ + public function hasAnyLicense(LicenseType | string | array | null $type): bool + { + if (blank($type)) { + return true; + } + + foreach (Arr::wrap($type) as $type) { + if (! ($type instanceof LicenseType)) { + $type = LicenseType::from($type); + } + + if ($type->isLicenseable()) { + return true; + } + } + + return false; + } } diff --git a/app/Models/User.php b/app/Models/User.php index 8d0a94f63b..b5ea36bbf4 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -36,12 +36,11 @@ namespace App\Models; -use AdvisingApp\Authorization\Enums\LicenseType; use Filament\Panel; use DateTimeInterface; +use Illuminate\Support\Arr; use AdvisingApp\Task\Models\Task; use AdvisingApp\Team\Models\Team; -use Illuminate\Support\Arr; use Spatie\MediaLibrary\HasMedia; use App\Support\HasAdvancedFilter; use AdvisingApp\Team\Models\TeamUser; @@ -50,6 +49,7 @@ use OwenIt\Auditing\Contracts\Auditable; use AdvisingApp\CareTeam\Models\CareTeam; use AdvisingApp\Prospect\Models\Prospect; +use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Authorization\Models\Role; use Lab404\Impersonate\Models\Impersonate; use Filament\Models\Contracts\FilamentUser; @@ -58,6 +58,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use AdvisingApp\MeetingCenter\Models\Calendar; use AdvisingApp\Assistant\Models\AssistantChat; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Staudenmeir\EloquentHasManyDeep\HasManyDeep; use AdvisingApp\Notification\Models\Subscription; @@ -376,16 +377,15 @@ public function getFilamentAvatarUrl(): ?string return $this->avatar_url ?: $this->getFirstTemporaryUrl(now()->addMinutes(5), 'avatar', 'avatar-height-250px'); } - protected function serializeDate(DateTimeInterface $date): string - { - return $date->format(config('project.datetime_format') ?? 'Y-m-d H:i:s'); - } - /** - * @param LicenseType | string | array $type + * @param LicenseType | string | array | null $type */ - public function hasLicense(LicenseType | string | array $type): bool + public function hasLicense(LicenseType | string | array | null $type): bool { + if (blank($type)) { + return true; + } + foreach (Arr::wrap($type) as $type) { if (! ($type instanceof LicenseType)) { $type = LicenseType::from($type); @@ -400,10 +400,14 @@ public function hasLicense(LicenseType | string | array $type): bool } /** - * @param LicenseType | string | array $type + * @param LicenseType | string | array | null $type */ - public function hasAnyLicense(LicenseType | string | array $type): bool + public function hasAnyLicense(LicenseType | string | array | null $type): bool { + if (blank($type)) { + return true; + } + foreach (Arr::wrap($type) as $type) { if (! ($type instanceof LicenseType)) { $type = LicenseType::from($type); @@ -416,4 +420,40 @@ public function hasAnyLicense(LicenseType | string | array $type): bool return false; } + + /** + * @param LicenseType | string | array | null $type + */ + public function scopeHasLicense(Builder $query, LicenseType | string | array | null $type): Builder + { + if (blank($type)) { + return $query; + } + + foreach (Arr::wrap($type) as $type) { + $query->whereRelation('licenses', 'type', $type); + } + + return $query; + } + + /** + * @param LicenseType | string | array | null $type + */ + public function scopeHasAnyLicense(Builder $query, LicenseType | string | array | null $type): Builder + { + if (blank($type)) { + return $query; + } + + return $query->whereHas( + 'licenses', + fn (Builder $query) => $query->whereIn('type', Arr::wrap($type)), + ); + } + + protected function serializeDate(DateTimeInterface $date): string + { + return $date->format(config('project.datetime_format') ?? 'Y-m-d H:i:s'); + } } From 8eee448e563647c6711ce5221c6594795e571ee1 Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Wed, 3 Jan 2024 17:36:46 -0500 Subject: [PATCH 061/152] wip --- .../src/Actions/GenerateFormKitSchema.php | 28 ++++++++----- .../LikertScaleAscendingSurveyBlock.php | 18 ++++++++ .../LikertScaleDescendingSurveyBlock.php | 42 +++++++++++++++++++ .../Blocks/SurveyFieldBlockRegistry.php | 3 ++ 4 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 app-modules/survey/src/Filament/Blocks/LikertScaleAscendingSurveyBlock.php create mode 100644 app-modules/survey/src/Filament/Blocks/LikertScaleDescendingSurveyBlock.php diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index 1ce5fa3530..a788cfd118 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -36,10 +36,13 @@ namespace AdvisingApp\Form\Actions; +use AdvisingApp\Form\Models\Form; +use AdvisingApp\Survey\Models\Survey; use AdvisingApp\Form\Models\Submissible; use AdvisingApp\Form\Models\SubmissibleStep; use Illuminate\Database\Eloquent\Collection; use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; class GenerateFormKitSchema { @@ -58,8 +61,13 @@ public function __invoke(Submissible $submissible): array 'fields', ]); + $blocks = match ($submissible::class) { + Form::class => FormFieldBlockRegistry::keyByType(), + Survey::class => SurveyFieldBlockRegistry::keyByType(), + }; + $content = [ - ...$this->content($submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), + ...$this->content($blocks, $submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), [ '$formkit' => 'submit', 'label' => 'Submit', @@ -81,21 +89,19 @@ public function __invoke(Submissible $submissible): array ]; } - public function content(array $content, ?Collection $fields = null): array + public function content(array $blocks, array $content, ?Collection $fields = null): array { - $blocks = FormFieldBlockRegistry::keyByType(); - return array_map( fn (array $component): array | string => match ($component['type'] ?? null) { - 'bulletList' => ['$el' => 'ul', 'children' => $this->content($component['content'] ?? [], $fields)], + 'bulletList' => ['$el' => 'ul', 'children' => $this->content($blocks, $component['content'] ?? [], $fields)], 'grid' => $this->grid($component, $fields), - 'gridColumn' => ['$el' => 'div', 'children' => $this->content($component['content'], $fields), 'attrs' => ['class' => ['grid-col' => true]]], - 'heading' => ['$el' => "h{$component['attrs']['level']}", 'children' => $this->content($component['content'], $fields)], + 'gridColumn' => ['$el' => 'div', 'children' => $this->content($blocks, $component['content'], $fields), 'attrs' => ['class' => ['grid-col' => true]]], + 'heading' => ['$el' => "h{$component['attrs']['level']}", 'children' => $this->content($blocks, $component['content'], $fields)], 'horizontalRule' => ['$el' => 'hr'], - 'listItem' => ['$el' => 'li', 'children' => $this->content($component['content'] ?? [], $fields)], - 'orderedList' => ['$el' => 'ol', 'children' => $this->content($component['content'] ?? [], $fields)], - 'paragraph' => ['$el' => 'p', 'children' => $this->content($component['content'] ?? [], $fields)], - 'small' => ['$el' => 'small', 'children' => $this->content($component['content'] ?? [], $fields)], + 'listItem' => ['$el' => 'li', 'children' => $this->content($blocks, $component['content'] ?? [], $fields)], + 'orderedList' => ['$el' => 'ol', 'children' => $this->content($blocks, $component['content'] ?? [], $fields)], + 'paragraph' => ['$el' => 'p', 'children' => $this->content($blocks, $component['content'] ?? [], $fields)], + 'small' => ['$el' => 'small', 'children' => $this->content($blocks, $component['content'] ?? [], $fields)], 'text' => $this->text($component), 'tiptapBlock' => ($field = ($fields[$component['attrs']['id']] ?? null)) ? $blocks[$component['attrs']['type']]::getFormKitSchema($field) : [], default => [], diff --git a/app-modules/survey/src/Filament/Blocks/LikertScaleAscendingSurveyBlock.php b/app-modules/survey/src/Filament/Blocks/LikertScaleAscendingSurveyBlock.php new file mode 100644 index 0000000000..e982cdf897 --- /dev/null +++ b/app-modules/survey/src/Filament/Blocks/LikertScaleAscendingSurveyBlock.php @@ -0,0 +1,18 @@ +reverse()->toArray(); + } +} diff --git a/app-modules/survey/src/Filament/Blocks/LikertScaleDescendingSurveyBlock.php b/app-modules/survey/src/Filament/Blocks/LikertScaleDescendingSurveyBlock.php new file mode 100644 index 0000000000..84710df3b2 --- /dev/null +++ b/app-modules/survey/src/Filament/Blocks/LikertScaleDescendingSurveyBlock.php @@ -0,0 +1,42 @@ +keyLabel('Value') + ->valueLabel('Label') + ->default($this->values()) + ->addable(false) + ->deletable(false) + ->editableKeys(false), + ]; + } + + protected function values(): array + { + return [ + 'strongly-agree' => 'Strongly agree', + 'agree' => 'Agree', + 'neutral' => 'Neither agree nor disagree', + 'disagree' => 'Disagree', + 'strongly-disagree' => 'Strongly disagree', + ]; + } +} diff --git a/app-modules/survey/src/Filament/Blocks/SurveyFieldBlockRegistry.php b/app-modules/survey/src/Filament/Blocks/SurveyFieldBlockRegistry.php index 2b37c5e8ff..dd4eb1e0fc 100644 --- a/app-modules/survey/src/Filament/Blocks/SurveyFieldBlockRegistry.php +++ b/app-modules/survey/src/Filament/Blocks/SurveyFieldBlockRegistry.php @@ -36,6 +36,7 @@ namespace AdvisingApp\Survey\Filament\Blocks; +use AdvisingApp\Form\Filament\Blocks\FormFieldBlock; use AdvisingApp\Form\Filament\Blocks\EmailFormFieldBlock; use AdvisingApp\Form\Filament\Blocks\NumberFormFieldBlock; use AdvisingApp\Form\Filament\Blocks\EducatableEmailFormFieldBlock; @@ -56,6 +57,8 @@ public static function get(): array CheckboxSurveyFieldBlock::class, EmailFormFieldBlock::class, NumberFormFieldBlock::class, + LikertScaleDescendingSurveyBlock::class, + LikertScaleAscendingSurveyBlock::class, ]; } From eddecdf829fd7d911c910c1dc77e42b5db1817db Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Wed, 3 Jan 2024 18:14:47 -0500 Subject: [PATCH 062/152] wip --- .../components/submissions/content.blade.php | 16 ++++++++++---- .../Actions/GenerateSubmissibleValidation.php | 21 ++++++++++++++----- ...InjectSubmissionStateIntoTipTapContent.php | 9 ++++---- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/app-modules/form/resources/views/components/submissions/content.blade.php b/app-modules/form/resources/views/components/submissions/content.blade.php index 4ec9712ae0..c4130c890c 100644 --- a/app-modules/form/resources/views/components/submissions/content.blade.php +++ b/app-modules/form/resources/views/components/submissions/content.blade.php @@ -34,12 +34,20 @@ @props(['content', 'submission']) @php - use AdvisingApp\Form\Actions\InjectSubmissionStateIntoTipTapContent; + use AdvisingApp\Form\Models\Form; + use AdvisingApp\Survey\Models\Survey; use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; - - $content['content'] = app(InjectSubmissionStateIntoTipTapContent::class)($submission, $content['content']); + use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; + use AdvisingApp\Form\Actions\InjectSubmissionStateIntoTipTapContent; + + $blocks = match ($submission->submissible::class) { + Form::class => FormFieldBlockRegistry::keyByType(), + Survey::class => SurveyFieldBlockRegistry::keyByType(), + }; + + $content['content'] = app(InjectSubmissionStateIntoTipTapContent::class)($submission, $content['content'], $blocks); @endphp
- {!! tiptap_converter()->blocks(FormFieldBlockRegistry::get())->asHTML($content) !!} + {!! tiptap_converter()->blocks($blocks)->asHTML($content) !!}
diff --git a/app-modules/form/src/Actions/GenerateSubmissibleValidation.php b/app-modules/form/src/Actions/GenerateSubmissibleValidation.php index ff2ddb56ac..45476f5b73 100644 --- a/app-modules/form/src/Actions/GenerateSubmissibleValidation.php +++ b/app-modules/form/src/Actions/GenerateSubmissibleValidation.php @@ -37,10 +37,13 @@ namespace AdvisingApp\Form\Actions; use Illuminate\Support\Arr; +use AdvisingApp\Form\Models\Form; +use AdvisingApp\Survey\Models\Survey; use AdvisingApp\Form\Models\Submissible; use Illuminate\Database\Eloquent\Collection; use AdvisingApp\Form\Models\SubmissibleField; use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; use AdvisingApp\IntegrationGoogleRecaptcha\Rules\RecaptchaTokenValid; class GenerateSubmissibleValidation @@ -57,13 +60,16 @@ public function __invoke(Submissible $submissible): array return array_merge($rules, $this->wizardRules($submissible)); } - return array_merge($rules, $this->fields($submissible->fields)); + $blocks = match ($submissible::class) { + Form::class => FormFieldBlockRegistry::keyByType(), + Survey::class => SurveyFieldBlockRegistry::keyByType(), + }; + + return array_merge($rules, $this->fields($blocks, $submissible->fields)); } - public function fields(Collection $fields): array + public function fields(array $blocks, Collection $fields): array { - $blocks = FormFieldBlockRegistry::keyByType(); - return $fields ->mapWithKeys(function (SubmissibleField $field) use ($blocks) { $rules = collect(); @@ -85,10 +91,15 @@ public function wizardRules(Submissible $submissible): array { $rules = collect(); + $blocks = match ($submissible::class) { + Form::class => FormFieldBlockRegistry::keyByType(), + Survey::class => SurveyFieldBlockRegistry::keyByType(), + }; + foreach ($submissible->steps as $step) { $rules = $rules->merge( Arr::prependKeysWith( - $this->fields($step->fields), + $this->fields($blocks, $step->fields), prependWith: "{$step->label}.", ), ); diff --git a/app-modules/form/src/Actions/InjectSubmissionStateIntoTipTapContent.php b/app-modules/form/src/Actions/InjectSubmissionStateIntoTipTapContent.php index 4ab91f4fc3..0d2b4c05a2 100644 --- a/app-modules/form/src/Actions/InjectSubmissionStateIntoTipTapContent.php +++ b/app-modules/form/src/Actions/InjectSubmissionStateIntoTipTapContent.php @@ -36,16 +36,17 @@ namespace AdvisingApp\Form\Actions; +use AdvisingApp\Form\Models\Form; use AdvisingApp\Form\Models\Submission; use AdvisingApp\Form\Models\SubmissibleField; use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; +use AdvisingApp\Survey\Models\Survey; class InjectSubmissionStateIntoTipTapContent { - public function __invoke(Submission $submission, array $content, ?array $blocks = null): array + public function __invoke(Submission $submission, array $content, array $blocks): array { - $blocks ??= FormFieldBlockRegistry::keyByType(); - foreach ($content as $componentKey => $component) { if (! is_array($component)) { continue; @@ -81,7 +82,7 @@ public function __invoke(Submission $submission, array $content, ?array $blocks } $content[$componentKey]['attrs']['data'] = [ - ...$content[$componentKey]['attrs']['data'], + ...$component['attrs']['data'], ...$block::getSubmissionState($field->pivot->response), ]; } From 6421ee9ae8dc05047e562f62aa332b9881a36cf5 Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Wed, 3 Jan 2024 18:33:46 -0500 Subject: [PATCH 063/152] Fix tests. --- .../views/components/submissions/content.blade.php | 11 +++++++---- .../form/src/Actions/GenerateFormKitSchema.php | 3 ++- .../src/Actions/GenerateSubmissibleValidation.php | 5 +++-- .../InjectSubmissionStateIntoTipTapContent.php | 4 ---- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app-modules/form/resources/views/components/submissions/content.blade.php b/app-modules/form/resources/views/components/submissions/content.blade.php index c4130c890c..283a68f150 100644 --- a/app-modules/form/resources/views/components/submissions/content.blade.php +++ b/app-modules/form/resources/views/components/submissions/content.blade.php @@ -36,15 +36,18 @@ @php use AdvisingApp\Form\Models\Form; use AdvisingApp\Survey\Models\Survey; + use AdvisingApp\Application\Models\Application; use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; use AdvisingApp\Form\Actions\InjectSubmissionStateIntoTipTapContent; - - $blocks = match ($submission->submissible::class) { - Form::class => FormFieldBlockRegistry::keyByType(), + + $submissible = $submission->submissible; + + $blocks = match ($submissible::class) { + Form::class, Application::class => FormFieldBlockRegistry::keyByType(), Survey::class => SurveyFieldBlockRegistry::keyByType(), }; - + $content['content'] = app(InjectSubmissionStateIntoTipTapContent::class)($submission, $content['content'], $blocks); @endphp diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index a788cfd118..b1f35d7baa 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -41,6 +41,7 @@ use AdvisingApp\Form\Models\Submissible; use AdvisingApp\Form\Models\SubmissibleStep; use Illuminate\Database\Eloquent\Collection; +use AdvisingApp\Application\Models\Application; use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; @@ -62,7 +63,7 @@ public function __invoke(Submissible $submissible): array ]); $blocks = match ($submissible::class) { - Form::class => FormFieldBlockRegistry::keyByType(), + Form::class, Application::class => FormFieldBlockRegistry::keyByType(), Survey::class => SurveyFieldBlockRegistry::keyByType(), }; diff --git a/app-modules/form/src/Actions/GenerateSubmissibleValidation.php b/app-modules/form/src/Actions/GenerateSubmissibleValidation.php index 45476f5b73..dcfe14bef8 100644 --- a/app-modules/form/src/Actions/GenerateSubmissibleValidation.php +++ b/app-modules/form/src/Actions/GenerateSubmissibleValidation.php @@ -42,6 +42,7 @@ use AdvisingApp\Form\Models\Submissible; use Illuminate\Database\Eloquent\Collection; use AdvisingApp\Form\Models\SubmissibleField; +use AdvisingApp\Application\Models\Application; use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; use AdvisingApp\IntegrationGoogleRecaptcha\Rules\RecaptchaTokenValid; @@ -61,7 +62,7 @@ public function __invoke(Submissible $submissible): array } $blocks = match ($submissible::class) { - Form::class => FormFieldBlockRegistry::keyByType(), + Form::class, Application::class => FormFieldBlockRegistry::keyByType(), Survey::class => SurveyFieldBlockRegistry::keyByType(), }; @@ -92,7 +93,7 @@ public function wizardRules(Submissible $submissible): array $rules = collect(); $blocks = match ($submissible::class) { - Form::class => FormFieldBlockRegistry::keyByType(), + Form::class, Application::class => FormFieldBlockRegistry::keyByType(), Survey::class => SurveyFieldBlockRegistry::keyByType(), }; diff --git a/app-modules/form/src/Actions/InjectSubmissionStateIntoTipTapContent.php b/app-modules/form/src/Actions/InjectSubmissionStateIntoTipTapContent.php index 0d2b4c05a2..eab7140282 100644 --- a/app-modules/form/src/Actions/InjectSubmissionStateIntoTipTapContent.php +++ b/app-modules/form/src/Actions/InjectSubmissionStateIntoTipTapContent.php @@ -36,12 +36,8 @@ namespace AdvisingApp\Form\Actions; -use AdvisingApp\Form\Models\Form; use AdvisingApp\Form\Models\Submission; use AdvisingApp\Form\Models\SubmissibleField; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; -use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; -use AdvisingApp\Survey\Models\Survey; class InjectSubmissionStateIntoTipTapContent { From b4536a47f3176acd0d18a76ddd34736e0dc1dd46 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 13:31:10 +0000 Subject: [PATCH 064/152] Refactor license type retrieval to be static to avoid arbitrary license type checks --- .../alert/src/Policies/AlertPolicy.php | 5 ++-- .../src/Enums/CaseloadModel.php | 9 ------- .../CaseloadResource/Pages/CreateCaseload.php | 15 ++++++------ .../CaseloadResource/Pages/EditCaseload.php | 5 ++-- .../CaseloadResource/Pages/ListCaseloads.php | 5 ++-- .../src/Models/Caseload.php | 2 +- .../src/Policies/CaseloadPolicy.php | 15 ++++++------ .../views/components/filters.blade.php | 24 ++++++++++++------- .../src/Filament/Pages/MessageCenter.php | 12 ++++++++++ .../src/Policies/EngagementPolicy.php | 5 ++-- .../Pages/CreateInteraction.php | 5 ++-- .../Pages/EditInteraction.php | 5 ++-- .../ProspectResource/Pages/CreateProspect.php | 3 +-- .../ProspectResource/Pages/EditProspect.php | 3 +-- .../Pages/ManageProspectCareTeam.php | 3 +-- .../Pages/ManageProspectSubscriptions.php | 3 +-- app-modules/prospect/src/Models/Prospect.php | 4 ++-- .../prospect/src/Policies/ProspectPolicy.php | 3 +-- .../Pages/ManageStudentCareTeam.php | 3 +-- .../Pages/ManageStudentSubscriptions.php | 3 +-- .../Models/Concerns/BelongsToEducatable.php | 5 ++-- .../src/Models/Contracts/Educatable.php | 2 +- .../student-data-model/src/Models/Student.php | 4 ++-- .../src/Policies/StudentPolicy.php | 3 +-- .../task/src/Filament/Concerns/TaskForm.php | 21 +++++++--------- app/Filament/Fields/EducatableSelect.php | 9 ++++--- database/seeders/UsersTableSeeder.php | 5 ++++ 27 files changed, 93 insertions(+), 88 deletions(-) diff --git a/app-modules/alert/src/Policies/AlertPolicy.php b/app-modules/alert/src/Policies/AlertPolicy.php index 48c4088f16..3f290b2491 100644 --- a/app-modules/alert/src/Policies/AlertPolicy.php +++ b/app-modules/alert/src/Policies/AlertPolicy.php @@ -39,13 +39,14 @@ use App\Models\Authenticatable; use AdvisingApp\Alert\Models\Alert; use Illuminate\Auth\Access\Response; -use AdvisingApp\Authorization\Enums\LicenseType; +use AdvisingApp\Prospect\Models\Prospect; +use AdvisingApp\StudentDataModel\Models\Student; class AlertPolicy { public function viewAny(Authenticatable $authenticatable): Response { - if (! $authenticatable->hasAnyLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])) { + if (! $authenticatable->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { return Response::deny('You do not have permission to view alerts.'); } diff --git a/app-modules/caseload-management/src/Enums/CaseloadModel.php b/app-modules/caseload-management/src/Enums/CaseloadModel.php index e88cdaaa00..0d3bb2067e 100644 --- a/app-modules/caseload-management/src/Enums/CaseloadModel.php +++ b/app-modules/caseload-management/src/Enums/CaseloadModel.php @@ -39,7 +39,6 @@ use Filament\Support\Contracts\HasLabel; use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Builder; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\CaseloadManagement\Importers\StudentCaseloadSubjectImporter; use AdvisingApp\CaseloadManagement\Importers\ProspectCaseloadSubjectImporter; @@ -95,12 +94,4 @@ public function getSubjectImporter(): string CaseloadModel::Student => StudentCaseloadSubjectImporter::class, }; } - - public function getLicenseType(): LicenseType - { - return match ($this) { - CaseloadModel::Student => LicenseType::RetentionCrm, - CaseloadModel::Prospect => LicenseType::RecruitmentCrm, - }; - } } diff --git a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php index 05993e7488..3d3400125e 100644 --- a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php +++ b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php @@ -52,6 +52,7 @@ use Filament\Forms\Components\TextInput; use Filament\Notifications\Notification; use Filament\Tables\Enums\FiltersLayout; +use AdvisingApp\Prospect\Models\Prospect; use Filament\Forms\Components\FileUpload; use Illuminate\Filesystem\AwsS3V3Adapter; use Filament\Forms\Components\Placeholder; @@ -60,7 +61,7 @@ use Illuminate\Contracts\Support\Htmlable; use Filament\Actions\Imports\Models\Import; use Filament\Actions\Imports\Jobs\ImportCsv; -use AdvisingApp\Authorization\Enums\LicenseType; +use AdvisingApp\StudentDataModel\Models\Student; use Filament\Tables\Concerns\InteractsWithTable; use AdvisingApp\CaseloadManagement\Enums\CaseloadType; use AdvisingApp\CaseloadManagement\Enums\CaseloadModel; @@ -101,7 +102,7 @@ public function getSteps(): array }), ]) ->columns(2) - ->visible(auth()->user()->hasLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])), + ->visible(auth()->user()->hasLicense([Student::getLicenseType(), Prospect::getLicenseType()])), Step::make('Identify Population') ->schema([ Select::make('type') @@ -298,16 +299,16 @@ public function getUploadedFileStream(TemporaryUploadedFile $file) protected function getCaseloadModel(): CaseloadModel { - $hasStudents = auth()->user()->hasLicense(LicenseType::RetentionCrm); - $hasProspects = auth()->user()->hasLicense(LicenseType::RecruitmentCrm); + $canAccessStudents = auth()->user()->hasLicense(Student::getLicenseType()); + $canAccessProspects = auth()->user()->hasLicense(Prospect::getLicenseType()); - if ($hasStudents && $hasProspects) { + if ($canAccessStudents && $canAccessProspects) { return CaseloadModel::tryFromCaseOrValue($this->form->getRawState()['model']) ?? throw new Exception('Neither students nor prospects were selected.'); } return match (true) { - $hasStudents => CaseloadModel::Student, - $hasProspects => CaseloadModel::Prospect, + $canAccessStudents => CaseloadModel::Student, + $canAccessProspects => CaseloadModel::Prospect, default => throw new Exception('User cannot access students or prospects.'), }; } diff --git a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/EditCaseload.php b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/EditCaseload.php index 13c5d73719..4fe0b09d11 100644 --- a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/EditCaseload.php +++ b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/EditCaseload.php @@ -46,7 +46,8 @@ use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; use Filament\Tables\Enums\FiltersLayout; -use AdvisingApp\Authorization\Enums\LicenseType; +use AdvisingApp\Prospect\Models\Prospect; +use AdvisingApp\StudentDataModel\Models\Student; use Filament\Tables\Concerns\InteractsWithTable; use AdvisingApp\CaseloadManagement\Enums\CaseloadType; use AdvisingApp\CaseloadManagement\Enums\CaseloadModel; @@ -89,7 +90,7 @@ public function form(Form $form): Form ->label('Population') ->options(CaseloadModel::class) ->disabled() - ->visible(auth()->user()->hasLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])), + ->visible(auth()->user()->hasLicense([Student::getLicenseType(), Prospect::getLicenseType()])), TextInput::make('user.name') ->label('User') ->disabled(), diff --git a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php index b46c7f7a4a..24b6b714cc 100644 --- a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php +++ b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php @@ -42,9 +42,10 @@ use Filament\Tables\Filters\Filter; use Filament\Tables\Actions\EditAction; use Filament\Tables\Columns\TextColumn; +use AdvisingApp\Prospect\Models\Prospect; use Filament\Resources\Pages\ListRecords; use Filament\Tables\Actions\DeleteAction; -use AdvisingApp\Authorization\Enums\LicenseType; +use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\CaseloadManagement\Filament\Resources\CaseloadResource; class ListCaseloads extends ListRecords @@ -61,7 +62,7 @@ public function table(Table $table): Table TextColumn::make('model') ->label('Population') ->sortable() - ->visible(auth()->user()->hasLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])), + ->visible(auth()->user()->hasLicense([Student::getLicenseType(), Prospect::getLicenseType()])), TextColumn::make('type') ->sortable(), TextColumn::make('user.name') diff --git a/app-modules/caseload-management/src/Models/Caseload.php b/app-modules/caseload-management/src/Models/Caseload.php index c48c511557..3f3bdbe6e1 100644 --- a/app-modules/caseload-management/src/Models/Caseload.php +++ b/app-modules/caseload-management/src/Models/Caseload.php @@ -110,7 +110,7 @@ protected static function booted(): void $user = auth()->user(); foreach (CaseloadModel::cases() as $model) { - if (! $user->hasLicense($model->getLicenseType())) { + if (! $user->hasLicense($model->class()::getLicenseType())) { $builder->where('model', '!=', $model); } } diff --git a/app-modules/caseload-management/src/Policies/CaseloadPolicy.php b/app-modules/caseload-management/src/Policies/CaseloadPolicy.php index 234f93a2e9..6888520ff8 100644 --- a/app-modules/caseload-management/src/Policies/CaseloadPolicy.php +++ b/app-modules/caseload-management/src/Policies/CaseloadPolicy.php @@ -38,14 +38,15 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; -use AdvisingApp\Authorization\Enums\LicenseType; +use AdvisingApp\Prospect\Models\Prospect; +use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\CaseloadManagement\Models\Caseload; class CaseloadPolicy { public function viewAny(Authenticatable $authenticatable): Response { - if (! $authenticatable->hasAnyLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])) { + if (! $authenticatable->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { return Response::deny('You do not have permission to view caseloads.'); } @@ -57,7 +58,7 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, Caseload $caseload): Response { - if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + if (! $authenticatable->hasLicense($caseload->model?->class()::getLicenseType())) { return Response::deny('You do not have permission to view this caseload.'); } @@ -77,7 +78,7 @@ public function create(Authenticatable $authenticatable): Response public function update(Authenticatable $authenticatable, Caseload $caseload): Response { - if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + if (! $authenticatable->hasLicense($caseload->model?->class()::getLicenseType())) { return Response::deny('You do not have permission to update this caseload.'); } @@ -89,7 +90,7 @@ public function update(Authenticatable $authenticatable, Caseload $caseload): Re public function delete(Authenticatable $authenticatable, Caseload $caseload): Response { - if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + if (! $authenticatable->hasLicense($caseload->model?->class()::getLicenseType())) { return Response::deny('You do not have permission to delete this caseload.'); } @@ -101,7 +102,7 @@ public function delete(Authenticatable $authenticatable, Caseload $caseload): Re public function restore(Authenticatable $authenticatable, Caseload $caseload): Response { - if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + if (! $authenticatable->hasLicense($caseload->model?->class()::getLicenseType())) { return Response::deny('You do not have permission to restore this caseload.'); } @@ -113,7 +114,7 @@ public function restore(Authenticatable $authenticatable, Caseload $caseload): R public function forceDelete(Authenticatable $authenticatable, Caseload $caseload): Response { - if (! $authenticatable->hasLicense($caseload->model?->getLicenseType())) { + if (! $authenticatable->hasLicense($caseload->model?->class()::getLicenseType())) { return Response::deny('You do not have permission to permanently delete this caseload.'); } diff --git a/app-modules/engagement/resources/views/components/filters.blade.php b/app-modules/engagement/resources/views/components/filters.blade.php index 684a2b0074..3d9f5dedad 100644 --- a/app-modules/engagement/resources/views/components/filters.blade.php +++ b/app-modules/engagement/resources/views/components/filters.blade.php @@ -31,19 +31,27 @@ --}} +@php + use AdvisingApp\Authorization\Enums\LicenseType; + use AdvisingApp\Prospect\Models\Prospect; + use AdvisingApp\StudentDataModel\Models\Student; +@endphp +
- Filter Engagements by: - + @if (auth()->user()->hasLicense([Student::getLicenseType(), Prospect::getLicenseType()])) + Filter Engagements by: - - - - - - + + + + + + + + @endif
Date Range diff --git a/app-modules/engagement/src/Filament/Pages/MessageCenter.php b/app-modules/engagement/src/Filament/Pages/MessageCenter.php index 414a5b634c..950ad5b34d 100644 --- a/app-modules/engagement/src/Filament/Pages/MessageCenter.php +++ b/app-modules/engagement/src/Filament/Pages/MessageCenter.php @@ -41,6 +41,7 @@ use Filament\Pages\Page; use Livewire\Attributes\Url; use Livewire\WithPagination; +use App\Models\Authenticatable; use Filament\Actions\ViewAction; use AdvisingApp\Task\Models\Task; use Filament\Actions\CreateAction; @@ -133,6 +134,7 @@ public function mount(): void $this->timelineRecords = collect(); + $this->authorize('viewAny', Engagement::class); $this->authorize('engagement.view_message_center'); } @@ -317,6 +319,16 @@ protected function getViewData(): array ? 'students_local' : 'students'; + /** @var Authenticatable $user */ + $user = auth()->user(); + + $canAccessStudents = $user->hasLicense(Student::getLicenseType()); + $canAccessProspects = $user->hasLicense(Prospect::getLicenseType()); + + if (! ($canAccessStudents && $canAccessProspects)) { + $this->filterPeopleType = $canAccessStudents ? 'students' : 'prospects'; + } + if ($this->filterPeopleType === 'students' || $this->filterPeopleType === 'all') { $studentIds = $this->getStudentIds(); $studentLatestActivity = $this->getLatestActivityForEducatables($studentIds); diff --git a/app-modules/engagement/src/Policies/EngagementPolicy.php b/app-modules/engagement/src/Policies/EngagementPolicy.php index 903c91e0b7..bb4287966a 100644 --- a/app-modules/engagement/src/Policies/EngagementPolicy.php +++ b/app-modules/engagement/src/Policies/EngagementPolicy.php @@ -38,14 +38,15 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; +use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\Engagement\Models\Engagement; -use AdvisingApp\Authorization\Enums\LicenseType; +use AdvisingApp\StudentDataModel\Models\Student; class EngagementPolicy { public function viewAny(Authenticatable $authenticatable): Response { - if (! $authenticatable->hasAnyLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])) { + if (! $authenticatable->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { return Response::deny('You do not have permission to view engagements.'); } diff --git a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php index 4c31e07ac2..850f36dd3b 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/CreateInteraction.php @@ -46,7 +46,6 @@ use Filament\Resources\Pages\CreateRecord; use Filament\Forms\Components\MorphToSelect; use Filament\Forms\Components\DateTimePicker; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\Interaction\Models\InteractionType; @@ -73,9 +72,9 @@ public function form(Form $form): Form ->searchable() ->required() ->types([ - ...(auth()->user()->hasLicense(LicenseType::RetentionCrm) ? [MorphToSelect\Type::make(Student::class) + ...(auth()->user()->hasLicense(Student::getLicenseType()) ? [MorphToSelect\Type::make(Student::class) ->titleAttribute(Student::displayNameKey())] : []), - ...(auth()->user()->hasLicense(LicenseType::RecruitmentCrm) ? [MorphToSelect\Type::make(Prospect::class) + ...(auth()->user()->hasLicense(Prospect::getLicenseType()) ? [MorphToSelect\Type::make(Prospect::class) ->titleAttribute(Prospect::displayNameKey())] : []), MorphToSelect\Type::make(ServiceRequest::class) ->label('Service Request') diff --git a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php index ca6a484056..879a8f0c52 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionResource/Pages/EditInteraction.php @@ -47,7 +47,6 @@ use AdvisingApp\Prospect\Models\Prospect; use Filament\Forms\Components\MorphToSelect; use Filament\Forms\Components\DateTimePicker; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\Interaction\Models\InteractionType; use AdvisingApp\Interaction\Models\InteractionDriver; @@ -72,9 +71,9 @@ public function form(Form $form): Form ->searchable() ->required() ->types([ - ...(auth()->user()->hasLicense(LicenseType::RetentionCrm) ? [MorphToSelect\Type::make(Student::class) + ...(auth()->user()->hasLicense(Student::getLicenseType()) ? [MorphToSelect\Type::make(Student::class) ->titleAttribute(Student::displayNameKey())] : []), - ...(auth()->user()->hasLicense(LicenseType::RecruitmentCrm) ? [MorphToSelect\Type::make(Prospect::class) + ...(auth()->user()->hasLicense(Prospect::getLicenseType()) ? [MorphToSelect\Type::make(Prospect::class) ->titleAttribute(Prospect::displayNameKey())] : []), MorphToSelect\Type::make(ServiceRequest::class) ->label('Service Request') diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php index 2548748ea3..ceff760d48 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php @@ -48,7 +48,6 @@ use Filament\Resources\Pages\CreateRecord; use AdvisingApp\Prospect\Models\ProspectSource; use AdvisingApp\Prospect\Models\ProspectStatus; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Prospect\Filament\Resources\ProspectResource; class CreateProspect extends CreateRecord @@ -138,7 +137,7 @@ public function form(Form $form): Form ->relationship( 'assignedTo', 'name', - fn (Builder $query) => $query->hasLicense(LicenseType::RecruitmentCrm), + fn (Builder $query) => $query->hasLicense(Prospect::getLicenseType()), ) ->searchable() ->nullable() diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php index 4b854381de..ce7a51fc21 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php @@ -50,7 +50,6 @@ use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Prospect\Models\ProspectSource; use AdvisingApp\Prospect\Models\ProspectStatus; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Prospect\Filament\Resources\ProspectResource; class EditProspect extends EditRecord @@ -141,7 +140,7 @@ public function form(Form $form): Form ->relationship( 'assignedTo', 'name', - fn (Builder $query) => $query->hasLicense(LicenseType::RecruitmentCrm), + fn (Builder $query) => $query->hasLicense(Prospect::getLicenseType()), ) ->searchable() ->nullable() diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php index f6c52eb8d6..1b34c33dfb 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php @@ -48,7 +48,6 @@ use Illuminate\Database\Eloquent\Builder; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DetachBulkAction; -use AdvisingApp\Authorization\Enums\LicenseType; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\Prospect\Filament\Resources\ProspectResource; @@ -96,7 +95,7 @@ public function table(Table $table): Table fn (Select $select) => $select->placeholder('Select a User'), ) ->recordSelectOptionsQuery( - fn (Builder $query) => $query->hasLicense(LicenseType::RecruitmentCrm), + fn (Builder $query) => $query->hasLicense(Prospect::getLicenseType()), ) ->successNotificationTitle(function (User $record) { /** @var Prospect $prospect */ diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php index 5b5ddbb874..b147d9e5dc 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php @@ -48,7 +48,6 @@ use Illuminate\Database\Eloquent\Builder; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DetachBulkAction; -use AdvisingApp\Authorization\Enums\LicenseType; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\Prospect\Filament\Resources\ProspectResource; @@ -98,7 +97,7 @@ public function table(Table $table): Table fn (Select $select) => $select->placeholder('Select a User'), ) ->recordSelectOptionsQuery( - fn (Builder $query) => $query->hasLicense(LicenseType::RecruitmentCrm), + fn (Builder $query) => $query->hasLicense(Prospect::getLicenseType()), ) ->successNotificationTitle(function (User $record) { /** @var Prospect $prospect */ diff --git a/app-modules/prospect/src/Models/Prospect.php b/app-modules/prospect/src/Models/Prospect.php index 004a601434..7b4befead0 100644 --- a/app-modules/prospect/src/Models/Prospect.php +++ b/app-modules/prospect/src/Models/Prospect.php @@ -232,7 +232,7 @@ public function subscribedUsers(): MorphToMany ->hasLicense($this->getLicenseType()); } - public function getLicenseType(): LicenseType + public static function getLicenseType(): LicenseType { return LicenseType::RecruitmentCrm; } @@ -247,7 +247,7 @@ protected static function booted(): void /** @var Authenticatable $user */ $user = auth()->user(); - if (! $user->hasLicense(LicenseType::RecruitmentCrm)) { + if (! $user->hasLicense(Prospect::getLicenseType())) { $builder->whereRaw('1 = 0'); } }); diff --git a/app-modules/prospect/src/Policies/ProspectPolicy.php b/app-modules/prospect/src/Policies/ProspectPolicy.php index c378359f86..7c3006a22a 100644 --- a/app-modules/prospect/src/Policies/ProspectPolicy.php +++ b/app-modules/prospect/src/Policies/ProspectPolicy.php @@ -39,13 +39,12 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; use AdvisingApp\Prospect\Models\Prospect; -use AdvisingApp\Authorization\Enums\LicenseType; class ProspectPolicy { public function viewAny(Authenticatable $authenticatable): Response { - if (! $authenticatable->hasLicense(LicenseType::RecruitmentCrm)) { + if (! $authenticatable->hasLicense(Prospect::getLicenseType())) { return Response::deny('You do not have permission to view prospects.'); } diff --git a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php index 6735368010..a93fe6b03d 100644 --- a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php +++ b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php @@ -47,7 +47,6 @@ use Illuminate\Database\Eloquent\Builder; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DetachBulkAction; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\StudentDataModel\Filament\Resources\StudentResource; @@ -96,7 +95,7 @@ public function table(Table $table): Table fn (Select $select) => $select->placeholder('Select a User'), ) ->recordSelectOptionsQuery( - fn (Builder $query) => $query->hasLicense(LicenseType::RetentionCrm), + fn (Builder $query) => $query->hasLicense(Student::getLicenseType()), ) ->successNotificationTitle(function (User $record) { /** @var Student $student */ diff --git a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php index 484ded5c89..4fef1e04e8 100644 --- a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php +++ b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php @@ -47,7 +47,6 @@ use Illuminate\Database\Eloquent\Builder; use Filament\Tables\Actions\BulkActionGroup; use Filament\Tables\Actions\DetachBulkAction; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\StudentDataModel\Filament\Resources\StudentResource; @@ -98,7 +97,7 @@ public function table(Table $table): Table fn (Select $select) => $select->placeholder('Select a User'), ) ->recordSelectOptionsQuery( - fn (Builder $query) => $query->hasLicense(LicenseType::RetentionCrm), + fn (Builder $query) => $query->hasLicense(Student::getLicenseType()), ) ->successNotificationTitle(function (User $record) { /** @var Student $student */ diff --git a/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php b/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php index c0365eb6ee..0a5de7c58a 100644 --- a/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php +++ b/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php @@ -6,7 +6,6 @@ use App\Models\Authenticatable; use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Builder; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Illuminate\Database\Eloquent\Relations\MorphTo; @@ -32,11 +31,11 @@ public function scopeLicensedToEducatable(Builder $query, string $relationship): return $query ->when( - ! $user->hasLicense(LicenseType::RetentionCrm), + ! $user->hasLicense(Student::getLicenseType()), fn (Builder $query) => $query->where($typeColumn, '!=', app(Student::class)->getMorphClass()), ) ->when( - ! $user->hasLicense(LicenseType::RecruitmentCrm), + ! $user->hasLicense(Prospect::getLicenseType()), fn (Builder $query) => $query->where($typeColumn, '!=', app(Prospect::class)->getMorphClass()), ); } diff --git a/app-modules/student-data-model/src/Models/Contracts/Educatable.php b/app-modules/student-data-model/src/Models/Contracts/Educatable.php index 006bd09e3c..4322d9c0c7 100644 --- a/app-modules/student-data-model/src/Models/Contracts/Educatable.php +++ b/app-modules/student-data-model/src/Models/Contracts/Educatable.php @@ -51,5 +51,5 @@ public static function displayEmailKey(): string; public function careTeam(): MorphToMany; - public function getLicenseType(): LicenseType; + public static function getLicenseType(): LicenseType; } diff --git a/app-modules/student-data-model/src/Models/Student.php b/app-modules/student-data-model/src/Models/Student.php index 9cf55e246c..4c31386bcf 100644 --- a/app-modules/student-data-model/src/Models/Student.php +++ b/app-modules/student-data-model/src/Models/Student.php @@ -227,7 +227,7 @@ public function getApiPermissions(): Collection return collect([]); } - public function getLicenseType(): LicenseType + public static function getLicenseType(): LicenseType { return LicenseType::RetentionCrm; } @@ -242,7 +242,7 @@ protected static function booted(): void /** @var Authenticatable $user */ $user = auth()->user(); - if (! $user->hasLicense(LicenseType::RetentionCrm)) { + if (! $user->hasLicense(Student::getLicenseType())) { $builder->whereRaw('1 = 0'); } }); diff --git a/app-modules/student-data-model/src/Policies/StudentPolicy.php b/app-modules/student-data-model/src/Policies/StudentPolicy.php index aa95a1c832..66210d7c84 100644 --- a/app-modules/student-data-model/src/Policies/StudentPolicy.php +++ b/app-modules/student-data-model/src/Policies/StudentPolicy.php @@ -38,14 +38,13 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; class StudentPolicy { public function viewAny(Authenticatable $authenticatable): Response { - if (! $authenticatable->hasLicense(LicenseType::RetentionCrm)) { + if (! $authenticatable->hasLicense(Student::getLicenseType())) { return Response::deny('You do not have permission to view students.'); } diff --git a/app-modules/task/src/Filament/Concerns/TaskForm.php b/app-modules/task/src/Filament/Concerns/TaskForm.php index b4a3939561..fed62a3e0d 100644 --- a/app-modules/task/src/Filament/Concerns/TaskForm.php +++ b/app-modules/task/src/Filament/Concerns/TaskForm.php @@ -43,7 +43,6 @@ use App\Models\Authenticatable; use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Builder; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Illuminate\Database\Eloquent\Relations\Relation; @@ -55,26 +54,22 @@ protected function scopeAssignmentRelationshipBasedOnConcern(): Closure $concernType = $get('concern_type'); if (filled($concernType = (Relation::getMorphedModel($concernType) ?? $concernType))) { - return match ($concernType) { - Student::class => $query->hasLicense(LicenseType::RetentionCrm), - Prospect::class => $query->hasLicense(LicenseType::RecruitmentCrm), - default => $query, - }; + return $query->hasLicense($concernType::getLicenseType()); } /** @var Authenticatable $user */ $user = auth()->user(); - $canAccessStudents = $user->hasLicense(LicenseType::RetentionCrm); - $canAccessProspects = $user->hasLicense(LicenseType::RecruitmentCrm); + $canAccessStudents = $user->hasLicense(Student::getLicenseType()); + $canAccessProspects = $user->hasLicense(Prospect::getLicenseType()); if ($canAccessStudents && $canAccessProspects) { return $query; } return match (true) { - $canAccessStudents => $query->hasLicense(LicenseType::RetentionCrm), - $canAccessProspects => $query->hasLicense(LicenseType::RecruitmentCrm), + $canAccessStudents => $query->hasLicense(Student::getLicenseType()), + $canAccessProspects => $query->hasLicense(Prospect::getLicenseType()), default => $query, }; }; @@ -98,8 +93,8 @@ protected function updateAssignmentAfterConcernSelected(): Closure /** @var Authenticatable $user */ $user = auth()->user(); - $canAccessStudents = $user->hasLicense(LicenseType::RetentionCrm); - $canAccessProspects = $user->hasLicense(LicenseType::RecruitmentCrm); + $canAccessStudents = $user->hasLicense(Student::getLicenseType()); + $canAccessProspects = $user->hasLicense(Prospect::getLicenseType()); $concernType = $get('concern_type'); @@ -115,7 +110,7 @@ protected function updateAssignmentAfterConcernSelected(): Closure $assignedTo = User::find($assignedTo); - if ($assignedTo->hasLicense(app($concernType))->getLicenseType()) { + if ($assignedTo->hasLicense($concernType::getLicenseType())) { return; } diff --git a/app/Filament/Fields/EducatableSelect.php b/app/Filament/Fields/EducatableSelect.php index ef084ba849..d7524536d0 100644 --- a/app/Filament/Fields/EducatableSelect.php +++ b/app/Filament/Fields/EducatableSelect.php @@ -10,7 +10,6 @@ use AdvisingApp\Prospect\Models\Prospect; use Filament\Forms\Components\MorphToSelect; use Filament\Forms\Components\Concerns\HasName; -use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use Filament\Forms\Components\MorphToSelect\Type; use Illuminate\Database\Eloquent\Relations\MorphTo; @@ -30,7 +29,7 @@ final public function __construct(string $name) public static function make(string $name): EducatableSelect | MorphToSelect { - if (auth()->user()->hasLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm])) { + if (auth()->user()->hasLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { return MorphToSelect::make($name) ->searchable() ->types([ @@ -63,8 +62,8 @@ public function getChildComponents(): array $user = auth()->user(); $type = match (true) { - $user->hasLicense(LicenseType::RetentionCrm) => static::getStudentType(), - $user->hasLicense(LicenseType::RecruitmentCrm) => static::getProspectType(), + $user->hasLicense(Student::getLicenseType()) => static::getStudentType(), + $user->hasLicense(Prospect::getLicenseType()) => static::getProspectType(), default => null, }; @@ -117,6 +116,6 @@ public function isHidden(): bool return false; } - return ! auth()->user()->hasAnyLicense([LicenseType::RetentionCrm, LicenseType::RecruitmentCrm]); + return ! auth()->user()->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()]); } } diff --git a/database/seeders/UsersTableSeeder.php b/database/seeders/UsersTableSeeder.php index 650359fbe8..f2fbc10378 100644 --- a/database/seeders/UsersTableSeeder.php +++ b/database/seeders/UsersTableSeeder.php @@ -41,6 +41,7 @@ use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Hash; use AdvisingApp\Authorization\Models\RoleGroup; +use AdvisingApp\Authorization\Enums\LicenseType; class UsersTableSeeder extends Seeder { @@ -56,6 +57,10 @@ public function run(): void ]); $superAdmin->roleGroups()->sync($superAdminRoleGroup); + + foreach (LicenseType::cases() as $licenseType) { + $superAdmin->licenses()->create(['type' => $licenseType]); + } } collect(config('internal-users.emails'))->each(function ($email) use ($superAdminRoleGroup) { From 9e90536bd5c3203fe0c154a5f20cb70e4976a4c3 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 14:34:04 +0000 Subject: [PATCH 065/152] importers --- .../src/Imports/InteractionsImporter.php | 64 +++++++++------ app-modules/task/src/Imports/TaskImporter.php | 78 +++++++++++++------ 2 files changed, 92 insertions(+), 50 deletions(-) diff --git a/app-modules/interaction/src/Imports/InteractionsImporter.php b/app-modules/interaction/src/Imports/InteractionsImporter.php index 86e720cf6c..fd1e537606 100644 --- a/app-modules/interaction/src/Imports/InteractionsImporter.php +++ b/app-modules/interaction/src/Imports/InteractionsImporter.php @@ -39,6 +39,7 @@ use App\Models\User; use Illuminate\Support\Str; use Filament\Actions\Imports\Importer; +use Illuminate\Database\Eloquent\Model; use AdvisingApp\Division\Models\Division; use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Builder; @@ -63,35 +64,48 @@ public static function getColumns(): array return [ ImportColumn::make('interactable') ->relationship( - resolveUsing: function (mixed $state) { - $type = str($state)->before(':'); - $value = str($state)->after(':'); - - return match ($type->toString()) { - 'prospect' => Prospect::query() - ->when( - str($value)->isUuid(), - fn (Builder $query) => $query->whereKey($value), - fn (Builder $query) => $query->where('email', $value), - ) - ->first(), - 'student' => Student::query() - ->when( - str($value)->isUuid(), - fn (Builder $query) => $query->whereKey($value), - fn (Builder $query) => $query->where('email', $value), - ) - ->first(), + resolveUsing: function (InteractionsImporter $importer, mixed $state): ?Model { + $resolveFromModel = fn (string $model, string $identifier): ?Model => $model::query() + ->when( + str($identifier)->isUuid(), + fn (Builder $query) => $query->whereKey($identifier), + fn (Builder $query) => $query->where('email', $identifier), + ) + ->first(); + + if (str($state)->contains(':')) { + return $resolveFromModel(match ((string) str($state)->before(':')) { + 'prospect' => Prospect::class, + 'student' => Student::class, + }, (string) str($state)->after(':')); + } + + $user = $importer->getImport()->user; + + $model = match (true) { + $user->hasLicense(Student::getLicenseType()) => Student::class, + $user->hasLicense(Prospect::getLicenseType()) => Prospect::class, + default => null, }; + + return filled($model) ? $resolveFromModel($model, $state) : null; }, ) ->requiredMapping() - ->rules( - [ - 'starts_with:prospect:,student:', - ] - ) - ->example('student:johnsmith@gmail.com'), + ->rules(function (InteractionsImporter $importer) { + if (! $importer->getImport()->user->hasLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { + return []; + } + + return ['starts_with:prospect:,student:']; + }) + ->example(function () { + if (auth()->user()?->hasLicense([Student::getLicenseType(), Prospect::getLicenseType()]) ?? true) { + return 'student:johnsmith@gmail.com'; + } + + return 'johnsmith@gmail.com'; + }), ImportColumn::make('type') ->relationship( resolveUsing: fn (mixed $state) => InteractionType::query() diff --git a/app-modules/task/src/Imports/TaskImporter.php b/app-modules/task/src/Imports/TaskImporter.php index a7efe8fe58..2c89772dd1 100644 --- a/app-modules/task/src/Imports/TaskImporter.php +++ b/app-modules/task/src/Imports/TaskImporter.php @@ -43,11 +43,14 @@ use Illuminate\Validation\Rules\Enum; use AdvisingApp\Task\Enums\TaskStatus; use Filament\Actions\Imports\Importer; +use Illuminate\Database\Eloquent\Model; use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Builder; use Filament\Actions\Imports\ImportColumn; use Filament\Actions\Imports\Models\Import; +use Illuminate\Validation\ValidationException; use AdvisingApp\StudentDataModel\Models\Student; +use AdvisingApp\Interaction\Imports\InteractionsImporter; /** * @property ?Task $record @@ -89,35 +92,48 @@ public static function getColumns(): array ImportColumn::make('concern') ->label('Related To') ->relationship( - resolveUsing: function (mixed $state) { - $type = str($state)->before(':'); - $value = str($state)->after(':'); - - return match ($type->toString()) { - 'prospect' => Prospect::query() - ->when( - str($value)->isUuid(), - fn (Builder $query) => $query->whereKey($value), - fn (Builder $query) => $query->where('email', $value), - ) - ->first(), - 'student' => Student::query() - ->when( - str($value)->isUuid(), - fn (Builder $query) => $query->whereKey($value), - fn (Builder $query) => $query->where('email', $value), - ) - ->first(), + resolveUsing: function (InteractionsImporter $importer, mixed $state): ?Model { + $resolveFromModel = fn (string $model, string $identifier): ?Model => $model::query() + ->when( + str($identifier)->isUuid(), + fn (Builder $query) => $query->whereKey($identifier), + fn (Builder $query) => $query->where('email', $identifier), + ) + ->first(); + + if (str($state)->contains(':')) { + return $resolveFromModel(match ((string) str($state)->before(':')) { + 'prospect' => Prospect::class, + 'student' => Student::class, + }, (string) str($state)->after(':')); + } + + $user = $importer->getImport()->user; + + $model = match (true) { + $user->hasLicense(Student::getLicenseType()) => Student::class, + $user->hasLicense(Prospect::getLicenseType()) => Prospect::class, + default => null, }; + + return filled($model) ? $resolveFromModel($model, $state) : null; }, ) ->requiredMapping() - ->rules( - [ - 'starts_with:prospect:,student:', - ] - ) - ->example('student:johnsmith@gmail.com'), + ->rules(function (InteractionsImporter $importer) { + if (! $importer->getImport()->user->hasLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { + return []; + } + + return ['starts_with:prospect:,student:']; + }) + ->example(function () { + if (auth()->user()?->hasLicense([Student::getLicenseType(), Prospect::getLicenseType()]) ?? true) { + return 'student:johnsmith@gmail.com'; + } + + return 'johnsmith@gmail.com'; + }), ]; } @@ -131,6 +147,18 @@ public function afterFill(): void /** @var Task $record */ $record = $this->record; + if ($this->import->user->cannot('view', $record->concern)) { + throw ValidationException::withMessages([ + 'concern' => 'You do not have permission to create a task for this concern.', + ]); + } + + if ($record->assignedTo?->cannot('view', $record->concern)) { + throw ValidationException::withMessages([ + 'assignedTo' => 'The assigned user does not have permission to view this concern.', + ]); + } + $query = Task::query(); foreach ($record->getAttributes() as $key => $value) { From eaed5a583fba2153a86b53678a3c83b1a4d251a4 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 14:34:15 +0000 Subject: [PATCH 066/152] apply policy filters --- app-modules/alert/src/Policies/AlertPolicy.php | 9 +++++++-- .../src/Policies/CaseloadPolicy.php | 9 +++++++-- .../engagement/src/Policies/EngagementPolicy.php | 9 +++++++-- app-modules/prospect/src/Policies/ProspectPolicy.php | 9 +++++++-- .../prospect/src/Policies/ProspectSourcePolicy.php | 10 ++++++++++ .../prospect/src/Policies/ProspectStatusPolicy.php | 10 ++++++++++ .../student-data-model/src/Policies/StudentPolicy.php | 9 +++++++-- 7 files changed, 55 insertions(+), 10 deletions(-) diff --git a/app-modules/alert/src/Policies/AlertPolicy.php b/app-modules/alert/src/Policies/AlertPolicy.php index 3f290b2491..143300b859 100644 --- a/app-modules/alert/src/Policies/AlertPolicy.php +++ b/app-modules/alert/src/Policies/AlertPolicy.php @@ -44,12 +44,17 @@ class AlertPolicy { - public function viewAny(Authenticatable $authenticatable): Response + public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { - return Response::deny('You do not have permission to view alerts.'); + return Response::deny('You do not have permission to view students or prospects.'); } + return null; + } + + public function viewAny(Authenticatable $authenticatable): Response + { return $authenticatable->canOrElse( abilities: 'alert.view-any', denyResponse: 'You do not have permission to view alerts.' diff --git a/app-modules/caseload-management/src/Policies/CaseloadPolicy.php b/app-modules/caseload-management/src/Policies/CaseloadPolicy.php index 6888520ff8..b41ed07c8c 100644 --- a/app-modules/caseload-management/src/Policies/CaseloadPolicy.php +++ b/app-modules/caseload-management/src/Policies/CaseloadPolicy.php @@ -44,12 +44,17 @@ class CaseloadPolicy { - public function viewAny(Authenticatable $authenticatable): Response + public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { - return Response::deny('You do not have permission to view caseloads.'); + return Response::deny('You do not have permission to view students or prospects.'); } + return null; + } + + public function viewAny(Authenticatable $authenticatable): Response + { return $authenticatable->canOrElse( abilities: 'caseload.view-any', denyResponse: 'You do not have permission to view caseloads.' diff --git a/app-modules/engagement/src/Policies/EngagementPolicy.php b/app-modules/engagement/src/Policies/EngagementPolicy.php index bb4287966a..39790dc2fd 100644 --- a/app-modules/engagement/src/Policies/EngagementPolicy.php +++ b/app-modules/engagement/src/Policies/EngagementPolicy.php @@ -44,12 +44,17 @@ class EngagementPolicy { - public function viewAny(Authenticatable $authenticatable): Response + public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { - return Response::deny('You do not have permission to view engagements.'); + return Response::deny('You do not have permission to view students or prospects.'); } + return null; + } + + public function viewAny(Authenticatable $authenticatable): Response + { return $authenticatable->canOrElse( abilities: 'engagement.view-any', denyResponse: 'You do not have permission to view engagements.' diff --git a/app-modules/prospect/src/Policies/ProspectPolicy.php b/app-modules/prospect/src/Policies/ProspectPolicy.php index 7c3006a22a..aca0724433 100644 --- a/app-modules/prospect/src/Policies/ProspectPolicy.php +++ b/app-modules/prospect/src/Policies/ProspectPolicy.php @@ -42,12 +42,17 @@ class ProspectPolicy { - public function viewAny(Authenticatable $authenticatable): Response + public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasLicense(Prospect::getLicenseType())) { - return Response::deny('You do not have permission to view prospects.'); + return Response::deny('You are not licensed for the recruitment CRM.'); } + return null; + } + + public function viewAny(Authenticatable $authenticatable): Response + { return $authenticatable->canOrElse( abilities: 'prospect.view-any', denyResponse: 'You do not have permission to view prospects.' diff --git a/app-modules/prospect/src/Policies/ProspectSourcePolicy.php b/app-modules/prospect/src/Policies/ProspectSourcePolicy.php index af0674b0fc..ae2a1001c1 100644 --- a/app-modules/prospect/src/Policies/ProspectSourcePolicy.php +++ b/app-modules/prospect/src/Policies/ProspectSourcePolicy.php @@ -38,10 +38,20 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; +use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\Prospect\Models\ProspectSource; class ProspectSourcePolicy { + public function before(Authenticatable $authenticatable): ?Response + { + if (! $authenticatable->hasLicense(Prospect::getLicenseType())) { + return Response::deny('You are not licensed for the recruitment CRM.'); + } + + return null; + } + public function viewAny(Authenticatable $authenticatable): Response { return $authenticatable->canOrElse( diff --git a/app-modules/prospect/src/Policies/ProspectStatusPolicy.php b/app-modules/prospect/src/Policies/ProspectStatusPolicy.php index 498c8177a8..ebb37dae87 100644 --- a/app-modules/prospect/src/Policies/ProspectStatusPolicy.php +++ b/app-modules/prospect/src/Policies/ProspectStatusPolicy.php @@ -38,10 +38,20 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; +use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\Prospect\Models\ProspectStatus; class ProspectStatusPolicy { + public function before(Authenticatable $authenticatable): ?Response + { + if (! $authenticatable->hasLicense(Prospect::getLicenseType())) { + return Response::deny('You are not licensed for the recruitment CRM.'); + } + + return null; + } + public function viewAny(Authenticatable $authenticatable): Response { return $authenticatable->canOrElse( diff --git a/app-modules/student-data-model/src/Policies/StudentPolicy.php b/app-modules/student-data-model/src/Policies/StudentPolicy.php index 66210d7c84..68ea835d02 100644 --- a/app-modules/student-data-model/src/Policies/StudentPolicy.php +++ b/app-modules/student-data-model/src/Policies/StudentPolicy.php @@ -42,12 +42,17 @@ class StudentPolicy { - public function viewAny(Authenticatable $authenticatable): Response + public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasLicense(Student::getLicenseType())) { - return Response::deny('You do not have permission to view students.'); + return Response::deny('You are not licensed for the retention CRM.'); } + return null; + } + + public function viewAny(Authenticatable $authenticatable): Response + { return $authenticatable->canOrElse( abilities: 'student.view-any', denyResponse: 'You do not have permission to view students.' From 27be55e263eead4d3a4f1e3e00cfce1f9655a181 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 14:58:27 +0000 Subject: [PATCH 067/152] Update Helpers.php --- tests/Helpers.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Helpers.php b/tests/Helpers.php index 65d170bf43..83fe275081 100644 --- a/tests/Helpers.php +++ b/tests/Helpers.php @@ -39,6 +39,7 @@ use App\Models\User; use App\Actions\Paths\ModulePath; use AdvisingApp\Authorization\Models\Role; +use AdvisingApp\Authorization\Enums\LicenseType; function asSuperAdmin(?User $user = null): TestCase { @@ -48,6 +49,10 @@ function asSuperAdmin(?User $user = null): TestCase $superAdmin->assignRole($superAdminRoles); + foreach (LicenseType::cases() as $licenseType) { + $superAdmin->licenses()->create(['type' => $licenseType]); + } + return test()->actingAs($superAdmin); } From b9597c79e23eb22baee1ccf73935dacf1d02a7db Mon Sep 17 00:00:00 2001 From: danharrin Date: Thu, 4 Jan 2024 15:04:51 +0000 Subject: [PATCH 068/152] chore: fix enforcement of copyright on all files --- _ide_helper_models.php | 34 +++++++++++++++++++ .../Models/Concerns/BelongsToEducatable.php | 34 +++++++++++++++++++ app/Filament/Fields/EducatableSelect.php | 34 +++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/_ide_helper_models.php b/_ide_helper_models.php index 0b68c7ed95..9980430648 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + // @formatter:off /** * A helper file for your Eloquent Models diff --git a/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php b/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php index 0a5de7c58a..cfc3f6ad78 100644 --- a/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php +++ b/app-modules/student-data-model/src/Models/Concerns/BelongsToEducatable.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\StudentDataModel\Models\Concerns; use Exception; diff --git a/app/Filament/Fields/EducatableSelect.php b/app/Filament/Fields/EducatableSelect.php index d7524536d0..bdfcdb880d 100644 --- a/app/Filament/Fields/EducatableSelect.php +++ b/app/Filament/Fields/EducatableSelect.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace App\Filament\Fields; use Closure; From faede217218e40c25c414ba753619ee34cda68de Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Thu, 4 Jan 2024 12:29:56 -0500 Subject: [PATCH 069/152] Cleanup. --- .../components/submissions/content.blade.php | 15 ++---- .../src/Actions/GenerateFormKitSchema.php | 5 +- .../Actions/GenerateSubmissibleValidation.php | 10 +--- .../form/src/Actions/ResolveBlockRegistry.php | 21 ++++++++ .../views/blocks/previews/likert.blade.php | 54 +++++++++++++++++++ .../views/blocks/submissions/likert.blade.php | 48 +++++++++++++++++ .../LikertScaleAscendingSurveyBlock.php | 18 ------- .../LikertScaleDescendingSurveyBlock.php | 42 --------------- .../Blocks/LikertScaleSurveyBlock.php | 52 ++++++++++++++++++ .../Blocks/SurveyFieldBlockRegistry.php | 3 +- 10 files changed, 182 insertions(+), 86 deletions(-) create mode 100644 app-modules/form/src/Actions/ResolveBlockRegistry.php create mode 100644 app-modules/survey/resources/views/blocks/previews/likert.blade.php create mode 100644 app-modules/survey/resources/views/blocks/submissions/likert.blade.php delete mode 100644 app-modules/survey/src/Filament/Blocks/LikertScaleAscendingSurveyBlock.php delete mode 100644 app-modules/survey/src/Filament/Blocks/LikertScaleDescendingSurveyBlock.php create mode 100644 app-modules/survey/src/Filament/Blocks/LikertScaleSurveyBlock.php diff --git a/app-modules/form/resources/views/components/submissions/content.blade.php b/app-modules/form/resources/views/components/submissions/content.blade.php index 283a68f150..b58e79c1d0 100644 --- a/app-modules/form/resources/views/components/submissions/content.blade.php +++ b/app-modules/form/resources/views/components/submissions/content.blade.php @@ -34,20 +34,11 @@ @props(['content', 'submission']) @php - use AdvisingApp\Form\Models\Form; - use AdvisingApp\Survey\Models\Survey; - use AdvisingApp\Application\Models\Application; - use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; - use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; + use AdvisingApp\Form\Actions\ResolveBlockRegistry; use AdvisingApp\Form\Actions\InjectSubmissionStateIntoTipTapContent; - $submissible = $submission->submissible; - - $blocks = match ($submissible::class) { - Form::class, Application::class => FormFieldBlockRegistry::keyByType(), - Survey::class => SurveyFieldBlockRegistry::keyByType(), - }; - + $blocks = app(ResolveBlockRegistry::class)($submission->submissible); + $content['content'] = app(InjectSubmissionStateIntoTipTapContent::class)($submission, $content['content'], $blocks); @endphp diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index b1f35d7baa..8c75466c27 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -62,10 +62,7 @@ public function __invoke(Submissible $submissible): array 'fields', ]); - $blocks = match ($submissible::class) { - Form::class, Application::class => FormFieldBlockRegistry::keyByType(), - Survey::class => SurveyFieldBlockRegistry::keyByType(), - }; + $blocks = app(ResolveBlockRegistry::class)($submissible); $content = [ ...$this->content($blocks, $submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), diff --git a/app-modules/form/src/Actions/GenerateSubmissibleValidation.php b/app-modules/form/src/Actions/GenerateSubmissibleValidation.php index dcfe14bef8..d99332bbd9 100644 --- a/app-modules/form/src/Actions/GenerateSubmissibleValidation.php +++ b/app-modules/form/src/Actions/GenerateSubmissibleValidation.php @@ -61,10 +61,7 @@ public function __invoke(Submissible $submissible): array return array_merge($rules, $this->wizardRules($submissible)); } - $blocks = match ($submissible::class) { - Form::class, Application::class => FormFieldBlockRegistry::keyByType(), - Survey::class => SurveyFieldBlockRegistry::keyByType(), - }; + $blocks = app(ResolveBlockRegistry::class)($submissible); return array_merge($rules, $this->fields($blocks, $submissible->fields)); } @@ -92,10 +89,7 @@ public function wizardRules(Submissible $submissible): array { $rules = collect(); - $blocks = match ($submissible::class) { - Form::class, Application::class => FormFieldBlockRegistry::keyByType(), - Survey::class => SurveyFieldBlockRegistry::keyByType(), - }; + $blocks = app(ResolveBlockRegistry::class)($submissible); foreach ($submissible->steps as $step) { $rules = $rules->merge( diff --git a/app-modules/form/src/Actions/ResolveBlockRegistry.php b/app-modules/form/src/Actions/ResolveBlockRegistry.php new file mode 100644 index 0000000000..7106088932 --- /dev/null +++ b/app-modules/form/src/Actions/ResolveBlockRegistry.php @@ -0,0 +1,21 @@ + FormFieldBlockRegistry::keyByType(), + Survey::class => SurveyFieldBlockRegistry::keyByType(), + }; + } +} diff --git a/app-modules/survey/resources/views/blocks/previews/likert.blade.php b/app-modules/survey/resources/views/blocks/previews/likert.blade.php new file mode 100644 index 0000000000..73c0b2b7ae --- /dev/null +++ b/app-modules/survey/resources/views/blocks/previews/likert.blade.php @@ -0,0 +1,54 @@ +{{-- + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +--}} + +@php + use AdvisingApp\Survey\Filament\Blocks\LikertScaleSurveyBlock; +@endphp + + +
+ @foreach (LikertScaleSurveyBlock::options() as $option) +
+
+ +
+ {{ $option }} +
+
+ @endforeach +
+
diff --git a/app-modules/survey/resources/views/blocks/submissions/likert.blade.php b/app-modules/survey/resources/views/blocks/submissions/likert.blade.php new file mode 100644 index 0000000000..5acf7d8c23 --- /dev/null +++ b/app-modules/survey/resources/views/blocks/submissions/likert.blade.php @@ -0,0 +1,48 @@ +{{-- + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +--}} +@php + use AdvisingApp\Survey\Filament\Blocks\LikertScaleSurveyBlock; +@endphp + + + {{ LikertScaleSurveyBlock::options()[$response ?? null] ?? null }} + + @if (blank($response ?? null)) + No response + @endif + diff --git a/app-modules/survey/src/Filament/Blocks/LikertScaleAscendingSurveyBlock.php b/app-modules/survey/src/Filament/Blocks/LikertScaleAscendingSurveyBlock.php deleted file mode 100644 index e982cdf897..0000000000 --- a/app-modules/survey/src/Filament/Blocks/LikertScaleAscendingSurveyBlock.php +++ /dev/null @@ -1,18 +0,0 @@ -reverse()->toArray(); - } -} diff --git a/app-modules/survey/src/Filament/Blocks/LikertScaleDescendingSurveyBlock.php b/app-modules/survey/src/Filament/Blocks/LikertScaleDescendingSurveyBlock.php deleted file mode 100644 index 84710df3b2..0000000000 --- a/app-modules/survey/src/Filament/Blocks/LikertScaleDescendingSurveyBlock.php +++ /dev/null @@ -1,42 +0,0 @@ -keyLabel('Value') - ->valueLabel('Label') - ->default($this->values()) - ->addable(false) - ->deletable(false) - ->editableKeys(false), - ]; - } - - protected function values(): array - { - return [ - 'strongly-agree' => 'Strongly agree', - 'agree' => 'Agree', - 'neutral' => 'Neither agree nor disagree', - 'disagree' => 'Disagree', - 'strongly-disagree' => 'Strongly disagree', - ]; - } -} diff --git a/app-modules/survey/src/Filament/Blocks/LikertScaleSurveyBlock.php b/app-modules/survey/src/Filament/Blocks/LikertScaleSurveyBlock.php new file mode 100644 index 0000000000..e98c8f8f85 --- /dev/null +++ b/app-modules/survey/src/Filament/Blocks/LikertScaleSurveyBlock.php @@ -0,0 +1,52 @@ + 'radio', + 'label' => $field->label, + 'name' => $field->getKey(), + ...($field->is_required ? ['validation' => 'required'] : []), + 'options' => static::options(), + ]; + } + + public static function getValidationRules(SubmissibleField $field): array + { + return [ + 'string', + 'in:' . collect(static::options())->keys()->join(','), + ]; + } + + public static function options(): array + { + return [ + 'strongly-agree' => 'Strongly agree', + 'agree' => 'Agree', + 'neutral' => 'Neither agree nor disagree', + 'disagree' => 'Disagree', + 'strongly-disagree' => 'Strongly disagree', + ]; + } +} diff --git a/app-modules/survey/src/Filament/Blocks/SurveyFieldBlockRegistry.php b/app-modules/survey/src/Filament/Blocks/SurveyFieldBlockRegistry.php index dd4eb1e0fc..a75b3c671b 100644 --- a/app-modules/survey/src/Filament/Blocks/SurveyFieldBlockRegistry.php +++ b/app-modules/survey/src/Filament/Blocks/SurveyFieldBlockRegistry.php @@ -57,8 +57,7 @@ public static function get(): array CheckboxSurveyFieldBlock::class, EmailFormFieldBlock::class, NumberFormFieldBlock::class, - LikertScaleDescendingSurveyBlock::class, - LikertScaleAscendingSurveyBlock::class, + LikertScaleSurveyBlock::class, ]; } From 96b35866b9d91df71a63fd1e21098b189d49aa2e Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Thu, 4 Jan 2024 12:37:12 -0500 Subject: [PATCH 070/152] Format. --- .../resources/views/components/submissions/content.blade.php | 2 +- app-modules/form/src/Actions/GenerateFormKitSchema.php | 5 ----- .../form/src/Actions/GenerateSubmissibleValidation.php | 5 ----- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/app-modules/form/resources/views/components/submissions/content.blade.php b/app-modules/form/resources/views/components/submissions/content.blade.php index b58e79c1d0..d5e11524f4 100644 --- a/app-modules/form/resources/views/components/submissions/content.blade.php +++ b/app-modules/form/resources/views/components/submissions/content.blade.php @@ -38,7 +38,7 @@ use AdvisingApp\Form\Actions\InjectSubmissionStateIntoTipTapContent; $blocks = app(ResolveBlockRegistry::class)($submission->submissible); - + $content['content'] = app(InjectSubmissionStateIntoTipTapContent::class)($submission, $content['content'], $blocks); @endphp diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index 8c75466c27..0174680ee3 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -36,14 +36,9 @@ namespace AdvisingApp\Form\Actions; -use AdvisingApp\Form\Models\Form; -use AdvisingApp\Survey\Models\Survey; use AdvisingApp\Form\Models\Submissible; use AdvisingApp\Form\Models\SubmissibleStep; use Illuminate\Database\Eloquent\Collection; -use AdvisingApp\Application\Models\Application; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; -use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; class GenerateFormKitSchema { diff --git a/app-modules/form/src/Actions/GenerateSubmissibleValidation.php b/app-modules/form/src/Actions/GenerateSubmissibleValidation.php index d99332bbd9..1c7b76a95b 100644 --- a/app-modules/form/src/Actions/GenerateSubmissibleValidation.php +++ b/app-modules/form/src/Actions/GenerateSubmissibleValidation.php @@ -37,14 +37,9 @@ namespace AdvisingApp\Form\Actions; use Illuminate\Support\Arr; -use AdvisingApp\Form\Models\Form; -use AdvisingApp\Survey\Models\Survey; use AdvisingApp\Form\Models\Submissible; use Illuminate\Database\Eloquent\Collection; use AdvisingApp\Form\Models\SubmissibleField; -use AdvisingApp\Application\Models\Application; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; -use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; use AdvisingApp\IntegrationGoogleRecaptcha\Rules\RecaptchaTokenValid; class GenerateSubmissibleValidation From d06233bcf17b4634abadf4a9e421c80fe482a555 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 13:56:54 -0500 Subject: [PATCH 071/152] Setup the separate column licenses Signed-off-by: Kevin Ullyott --- .../LicenseManagement/LicenseLimitsData.php | 5 +++-- app/Filament/Pages/ManageLicenseSettings.php | 12 ++++++++---- .../2023_11_29_192230_create_license_settings.php | 5 +++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/app/DataTransferObjects/LicenseManagement/LicenseLimitsData.php b/app/DataTransferObjects/LicenseManagement/LicenseLimitsData.php index 21d04a3972..884e07af48 100644 --- a/app/DataTransferObjects/LicenseManagement/LicenseLimitsData.php +++ b/app/DataTransferObjects/LicenseManagement/LicenseLimitsData.php @@ -44,8 +44,9 @@ class LicenseLimitsData extends Data { public function __construct( - public int $crmSeats, - public int $analyticsSeats, + public int $conversationalAiSeats, + public int $retentionCrmSeats, + public int $recruitmentCrmSeats, public int $emails, public int $sms, public string $resetDate, diff --git a/app/Filament/Pages/ManageLicenseSettings.php b/app/Filament/Pages/ManageLicenseSettings.php index 60c226c862..b6c94c6005 100644 --- a/app/Filament/Pages/ManageLicenseSettings.php +++ b/app/Filament/Pages/ManageLicenseSettings.php @@ -96,12 +96,16 @@ public function form(Form $form): Form ->columns() ->schema( [ - TextInput::make('data.limits.crmSeats') - ->label('CRM Seats') + TextInput::make('data.limits.conversationalAiSeats') + ->label('Artificial Intelligence Seats') ->numeric() ->required(), - TextInput::make('data.limits.analyticsSeats') - ->label('Analytics Seats') + TextInput::make('data.limits.retentionCrmSeats') + ->label('Student Success / Retention Seats') + ->numeric() + ->required(), + TextInput::make('data.limits.recruitmentCrmSeats') + ->label('Recruitment CRM Seats') ->numeric() ->required(), TextInput::make('data.limits.emails') diff --git a/database/settings/2023_11_29_192230_create_license_settings.php b/database/settings/2023_11_29_192230_create_license_settings.php index 7f487669cc..cfb3e6bbb4 100644 --- a/database/settings/2023_11_29_192230_create_license_settings.php +++ b/database/settings/2023_11_29_192230_create_license_settings.php @@ -55,8 +55,9 @@ public function up(): void 'end_date' => now()->addYear(), ], 'limits' => [ - 'crm_seats' => 30, - 'analytics_seats' => 15, + 'conversational_ai_seats' => 50, + 'retention_crm_seats' => 25, + 'recruitment_crm_seats' => 10, 'emails' => 1000, 'sms' => 1000, 'reset_date' => now()->format('m-d'), From ab3e3f6179f76469acf123a84617c35fb7565687 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 16:31:00 -0500 Subject: [PATCH 072/152] Update LicenseSettings with addon changes Signed-off-by: Kevin Ullyott --- .../LicenseManagement/LicenseAddonsData.php | 10 +++++----- app/Filament/Pages/ManageLicenseSettings.php | 20 +++++++++---------- ...3_11_29_192230_create_license_settings.php | 10 +++++----- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/DataTransferObjects/LicenseManagement/LicenseAddonsData.php b/app/DataTransferObjects/LicenseManagement/LicenseAddonsData.php index 4f131c4bdf..add8d67d58 100644 --- a/app/DataTransferObjects/LicenseManagement/LicenseAddonsData.php +++ b/app/DataTransferObjects/LicenseManagement/LicenseAddonsData.php @@ -44,13 +44,13 @@ class LicenseAddonsData extends Data { public function __construct( + public bool $onlineForms, + public bool $onlineSurveys, public bool $onlineAdmissions, - public bool $realtimeChat, - public bool $dynamicForms, - public bool $conductSurveys, - public bool $personalAssistant, public bool $serviceManagement, public bool $knowledgeManagement, - public bool $studentAndProspectPortal, + public bool $eventManagement, + public bool $realtimeChat, + public bool $mobileApps, ) {} } diff --git a/app/Filament/Pages/ManageLicenseSettings.php b/app/Filament/Pages/ManageLicenseSettings.php index b6c94c6005..60ac1625a5 100644 --- a/app/Filament/Pages/ManageLicenseSettings.php +++ b/app/Filament/Pages/ManageLicenseSettings.php @@ -125,22 +125,22 @@ public function form(Form $form): Form ->columns() ->schema( [ + Toggle::make('data.addons.onlineForms') + ->label('Online Forms'), + Toggle::make('data.addons.onlineSurveys') + ->label('Online Surveys'), Toggle::make('data.addons.onlineAdmissions') ->label('Online Admissions'), - Toggle::make('data.addons.realtimeChat') - ->label('Realtime Chat'), - Toggle::make('data.addons.dynamicForms') - ->label('Dynamic Forms'), - Toggle::make('data.addons.conductSurveys') - ->label('Conduct Surveys'), - Toggle::make('data.addons.personalAssistant') - ->label('Personal Assistant'), Toggle::make('data.addons.serviceManagement') ->label('Service Management'), Toggle::make('data.addons.knowledgeManagement') ->label('Knowledge Management'), - Toggle::make('data.addons.studentAndProspectPortal') - ->label('Student and Prospect Portal'), + Toggle::make('data.addons.eventManagement') + ->label('Event Management'), + Toggle::make('data.addons.realtimeChat') + ->label('Realtime Chat'), + Toggle::make('data.addons.mobileApps') + ->label('Mobile Apps'), ] ), ]); diff --git a/database/settings/2023_11_29_192230_create_license_settings.php b/database/settings/2023_11_29_192230_create_license_settings.php index cfb3e6bbb4..3d3af1ade5 100644 --- a/database/settings/2023_11_29_192230_create_license_settings.php +++ b/database/settings/2023_11_29_192230_create_license_settings.php @@ -63,14 +63,14 @@ public function up(): void 'reset_date' => now()->format('m-d'), ], 'addons' => [ + 'online_forms' => true, + 'online_surveys' => true, 'online_admissions' => true, - 'realtime_chat' => true, - 'dynamic_forms' => true, - 'conduct_surveys' => true, - 'personal_assistant' => true, 'service_management' => true, 'knowledge_management' => true, - 'student_and_prospect_portal' => true, + 'event_management' => true, + 'realtime_chat' => true, + 'mobileApps' => true, ], ] ); From 49384527ff81282422411b1643350d0a10b38938 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 17:00:00 -0500 Subject: [PATCH 073/152] Update and remove old references Signed-off-by: Kevin Ullyott --- .../src/Filament/Pages/ManageAiSettings.php | 9 ++++++--- .../src/Filament/Pages/PersonalAssistant.php | 8 ++++---- .../Policies/AssistantChatMessageLogPolicy.php | 6 ++---- .../Pages/ListConsentAgreements.php | 5 +++-- .../src/Policies/ConsentAgreementPolicy.php | 6 ++---- app-modules/form/src/Policies/FormPolicy.php | 2 +- .../src/Filament/Pages/ManagePortalSettings.php | 4 ++-- .../Middleware/EnsureSurveysFeatureIsActive.php | 2 +- app/Enums/Feature.php | 15 +++++++-------- .../Resources/UserResource/Pages/ListUsers.php | 13 ++++++------- app/Policies/UserPolicy.php | 10 ---------- 11 files changed, 34 insertions(+), 46 deletions(-) diff --git a/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php b/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php index f2b7567936..5297dc5be9 100644 --- a/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php +++ b/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php @@ -37,7 +37,6 @@ namespace AdvisingApp\Assistant\Filament\Pages; use App\Models\User; -use App\Enums\Feature; use Filament\Forms\Form; use Filament\Pages\SettingsPage; use Filament\Forms\Components\Textarea; @@ -58,7 +57,9 @@ public static function shouldRegisterNavigation(): bool /** @var User $user */ $user = auth()->user(); - return $user->can([Feature::PersonalAssistant->getGateName(), 'assistant.access_ai_settings']); + // TODO: Feature/License Gate | if has AI License + + return $user->can(['assistant.access_ai_settings']); } public function mount(): void @@ -66,7 +67,9 @@ public function mount(): void /** @var User $user */ $user = auth()->user(); - abort_unless($user->can([Feature::PersonalAssistant->getGateName(), 'assistant.access_ai_settings']), 403); + // TODO: Feature/License Gate | if has AI License + + abort_unless($user->can(['assistant.access_ai_settings']), 403); parent::mount(); } diff --git a/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php b/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php index 1683ec61f8..286e93fd51 100644 --- a/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php +++ b/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php @@ -37,7 +37,6 @@ namespace AdvisingApp\Assistant\Filament\Pages; use App\Models\User; -use App\Enums\Feature; use Filament\Forms\Get; use Filament\Pages\Page; use Livewire\Attributes\On; @@ -49,7 +48,6 @@ use Filament\Actions\StaticAction; use Illuminate\Support\Collection; use Filament\Forms\Components\Radio; -use Illuminate\Support\Facades\Gate; use Filament\Forms\Components\Select; use Filament\Support\Enums\Alignment; use Filament\Support\Enums\ActionSize; @@ -110,12 +108,14 @@ public static function shouldRegisterNavigation(): bool /** @var User $user */ $user = auth()->user(); - return Gate::check(Feature::PersonalAssistant->getGateName()) && $user->can('assistant.access'); + // TODO: Feature/License Gate | if has AI License + + return $user->can('assistant.access'); } public function mount(): void { - $this->authorize(Feature::PersonalAssistant->getGateName()); + // TODO: Feature/License Gate | if has AI License $this->authorize('assistant.access'); $this->consentAgreement = ConsentAgreement::where('type', ConsentAgreementType::AzureOpenAI)->first(); diff --git a/app-modules/assistant/src/Policies/AssistantChatMessageLogPolicy.php b/app-modules/assistant/src/Policies/AssistantChatMessageLogPolicy.php index 5addc25240..f0489b5ea9 100644 --- a/app-modules/assistant/src/Policies/AssistantChatMessageLogPolicy.php +++ b/app-modules/assistant/src/Policies/AssistantChatMessageLogPolicy.php @@ -36,7 +36,6 @@ namespace AdvisingApp\Assistant\Policies; -use App\Enums\Feature; use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; use App\Concerns\FeatureAccessEnforcedPolicyBefore; @@ -90,8 +89,7 @@ public function forceDelete(Authenticatable $authenticatable, AssistantChatMessa protected function requiredFeatures(): array { - return [ - Feature::PersonalAssistant, - ]; + // TODO: Feature/License Gate | if has AI License + return []; } } diff --git a/app-modules/consent/src/Filament/Resources/ConsentAgreementResource/Pages/ListConsentAgreements.php b/app-modules/consent/src/Filament/Resources/ConsentAgreementResource/Pages/ListConsentAgreements.php index 60a743fc28..93bc6bc87c 100644 --- a/app-modules/consent/src/Filament/Resources/ConsentAgreementResource/Pages/ListConsentAgreements.php +++ b/app-modules/consent/src/Filament/Resources/ConsentAgreementResource/Pages/ListConsentAgreements.php @@ -37,7 +37,6 @@ namespace AdvisingApp\Consent\Filament\Resources\ConsentAgreementResource\Pages; use App\Models\User; -use App\Enums\Feature; use Filament\Forms\Form; use Filament\Tables\Table; use App\Filament\Columns\IdColumn; @@ -72,7 +71,9 @@ public static function shouldRegisterNavigation(array $parameters = []): bool /** @var User $user */ $user = auth()->user(); - return $user->can([Feature::PersonalAssistant->getGateName(), 'consent_agreement.view-any', 'consent_agreement.*.view', 'consent_agreement.*.update']); + // TODO: Feature/License Gate | if has AI License, may need to prevent mount as well + + return $user->can(['consent_agreement.view-any', 'consent_agreement.*.view', 'consent_agreement.*.update']); } public function form(Form $form): Form diff --git a/app-modules/consent/src/Policies/ConsentAgreementPolicy.php b/app-modules/consent/src/Policies/ConsentAgreementPolicy.php index c1fab30e1c..1f8a71b82f 100644 --- a/app-modules/consent/src/Policies/ConsentAgreementPolicy.php +++ b/app-modules/consent/src/Policies/ConsentAgreementPolicy.php @@ -36,7 +36,6 @@ namespace AdvisingApp\Consent\Policies; -use App\Enums\Feature; use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; use AdvisingApp\Consent\Models\ConsentAgreement; @@ -93,8 +92,7 @@ public function forceDelete(Authenticatable $authenticatable, ConsentAgreement $ protected function requiredFeatures(): array { - return [ - Feature::PersonalAssistant, - ]; + // TODO: Feature/License Gate | if has AI License + return []; } } diff --git a/app-modules/form/src/Policies/FormPolicy.php b/app-modules/form/src/Policies/FormPolicy.php index d6d72f6300..14c33e8645 100644 --- a/app-modules/form/src/Policies/FormPolicy.php +++ b/app-modules/form/src/Policies/FormPolicy.php @@ -105,6 +105,6 @@ public function forceDelete(Authenticatable $authenticatable, Form $form): Respo protected function requiredFeatures(): array { - return [Feature::DynamicForms]; + return [Feature::OnlineForms]; } } diff --git a/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php b/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php index 3b49e86f09..ae234b0eab 100644 --- a/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php +++ b/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php @@ -135,12 +135,12 @@ public function form(Form $form): Form ->label('Files and Documents'), Toggle::make('has_forms') ->label('Forms') - ->disabled(! Gate::check(Feature::DynamicForms->getGateName())) + ->disabled(! Gate::check(Feature::OnlineForms->getGateName())) ->hintIcon(fn (Toggle $component) => $component->isDisabled() ? 'heroicon-m-lock-closed' : null) ->hintIconTooltip('Forms are not a part of your current subscription.'), Toggle::make('has_surveys') ->label('Surveys') - ->disabled(! Gate::check(Feature::ConductSurveys->getGateName())) + ->disabled(! Gate::check(Feature::OnlineSurveys->getGateName())) ->hintIcon(fn (Toggle $component) => $component->isDisabled() ? 'heroicon-m-lock-closed' : null) ->hintIconTooltip('Surveys are not a part of your current subscription.'), ]) diff --git a/app-modules/survey/src/Http/Middleware/EnsureSurveysFeatureIsActive.php b/app-modules/survey/src/Http/Middleware/EnsureSurveysFeatureIsActive.php index 2c0d37c894..9c211af70a 100644 --- a/app-modules/survey/src/Http/Middleware/EnsureSurveysFeatureIsActive.php +++ b/app-modules/survey/src/Http/Middleware/EnsureSurveysFeatureIsActive.php @@ -45,7 +45,7 @@ class EnsureSurveysFeatureIsActive { public function handle(Request $request, Closure $next): Response { - if (! app(LicenseSettings::class)->data->addons->conductSurveys) { + if (! app(LicenseSettings::class)->data->addons->onlineSurveys) { return response()->json(['error' => 'Surveys is not enabled.'], 403); } diff --git a/app/Enums/Feature.php b/app/Enums/Feature.php index 188146291c..a7e8914c0a 100644 --- a/app/Enums/Feature.php +++ b/app/Enums/Feature.php @@ -42,21 +42,20 @@ enum Feature: string { - case OnlineAdmissions = 'online-admissions'; - - case RealtimeChat = 'realtime-chat'; - - case DynamicForms = 'dynamic-forms'; + case OnlineForms = 'online-forms'; - case ConductSurveys = 'conduct-surveys'; + case OnlineSurveys = 'online-surveys'; - case PersonalAssistant = 'personal-assistant'; + case OnlineAdmissions = 'online-admissions'; case ServiceManagement = 'service-management'; case KnowledgeManagement = 'knowledge-management'; - case StudentAndProspectPortal = 'student-and-prospect-portal'; + case EventManagement = 'event-management'; + case RealtimeChat = 'realtime-chat'; + + case MobileApps = 'mobile-apps'; public function generateGate(): void { diff --git a/app/Filament/Resources/UserResource/Pages/ListUsers.php b/app/Filament/Resources/UserResource/Pages/ListUsers.php index 287c793daa..2ec58227e3 100644 --- a/app/Filament/Resources/UserResource/Pages/ListUsers.php +++ b/app/Filament/Resources/UserResource/Pages/ListUsers.php @@ -36,10 +36,7 @@ namespace App\Filament\Resources\UserResource\Pages; -use App\Models\User; -use App\Settings\LicenseSettings; use Filament\Actions\CreateAction; -use Illuminate\Support\HtmlString; use App\Filament\Resources\UserResource; use Filament\Resources\Pages\ListRecords; use Illuminate\Contracts\Support\Htmlable; @@ -50,10 +47,12 @@ class ListUsers extends ListRecords public function getSubheading(): string | Htmlable | null { - return new HtmlString(view('crm-seats', [ - 'count' => User::count(), - 'max' => app(LicenseSettings::class)->data->limits->crmSeats, - ])->render()); + // TODO: Either remove or change to show all possible seats + + //return new HtmlString(view('crm-seats', [ + // 'count' => User::count(), + // 'max' => app(LicenseSettings::class)->data->limits->crmSeats, + //])->render()); } protected function getHeaderActions(): array diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index 120acf24fc..93eb31eb33 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -38,9 +38,7 @@ use App\Models\User; use App\Models\Authenticatable; -use App\Settings\LicenseSettings; use Illuminate\Auth\Access\Response; -use App\Support\FeatureAccessResponse; class UserPolicy { @@ -62,10 +60,6 @@ public function view(Authenticatable $authenticatable, User $model): Response public function create(Authenticatable $authenticatable): Response { - if (User::count() >= app(LicenseSettings::class)->data->limits->crmSeats) { - return FeatureAccessResponse::deny('You have reached the maximum number of users allowed by your license.'); - } - return $authenticatable->canOrElse( abilities: 'user.create', denyResponse: 'You do not have permission to create users.' @@ -90,10 +84,6 @@ public function delete(Authenticatable $authenticatable, User $model): Response public function restore(Authenticatable $authenticatable, User $model): Response { - if (User::count() >= app(LicenseSettings::class)->data->limits->crmSeats) { - return FeatureAccessResponse::deny('You have reached the maximum number of users allowed by your license.'); - } - return $authenticatable->canOrElse( abilities: ['user.*.restore', "user.{$model->id}.restore"], denyResponse: 'You do not have permission to restore this user.' From f218ca324edd79854dd898a3bc0f61b4a3e15697 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 17:11:56 -0500 Subject: [PATCH 074/152] Fix bug with ListUsers header Signed-off-by: Kevin Ullyott --- app/Filament/Resources/UserResource/Pages/ListUsers.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Filament/Resources/UserResource/Pages/ListUsers.php b/app/Filament/Resources/UserResource/Pages/ListUsers.php index 2ec58227e3..3edd59677c 100644 --- a/app/Filament/Resources/UserResource/Pages/ListUsers.php +++ b/app/Filament/Resources/UserResource/Pages/ListUsers.php @@ -53,6 +53,8 @@ public function getSubheading(): string | Htmlable | null // 'count' => User::count(), // 'max' => app(LicenseSettings::class)->data->limits->crmSeats, //])->render()); + + return null; } protected function getHeaderActions(): array From 969732a77fc25fd1da8c087e5fd7c7210002bdda Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 18:52:21 -0500 Subject: [PATCH 075/152] Create a license management processes Signed-off-by: Kevin Ullyott --- .../config/roles/web/license_management.php | 43 ++++++++++++++ ...024_01_02_225406_create_licenses_table.php | 20 +++++++ .../authorization/src/Enums/LicenseType.php | 40 +++++++++++++ .../authorization/src/Models/License.php | 24 ++++++++ .../src/Rules/LicenseTypeUsageRule.php | 19 ++++++ app/Filament/Resources/UserResource.php | 2 + .../LicensesRelationManager.php | 59 +++++++++++++++++++ app/Models/User.php | 6 ++ 8 files changed, 213 insertions(+) create mode 100644 app-modules/authorization/config/roles/web/license_management.php create mode 100644 app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php create mode 100644 app-modules/authorization/src/Enums/LicenseType.php create mode 100644 app-modules/authorization/src/Models/License.php create mode 100644 app-modules/authorization/src/Rules/LicenseTypeUsageRule.php create mode 100644 app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php diff --git a/app-modules/authorization/config/roles/web/license_management.php b/app-modules/authorization/config/roles/web/license_management.php new file mode 100644 index 0000000000..ac07305bb6 --- /dev/null +++ b/app-modules/authorization/config/roles/web/license_management.php @@ -0,0 +1,43 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +return [ + 'model' => [ + 'license' => [ + '*', + ], + ], +]; diff --git a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php new file mode 100644 index 0000000000..475a106a2a --- /dev/null +++ b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php @@ -0,0 +1,20 @@ +uuid('id')->primary(); + $table->foreignUuid('user_id')->constrained('users')->cascadeOnDelete(); + $table->string('type'); + $table->timestamps(); + $table->softDeletes(); + + $table->unique(['user_id', 'type']); + }); + } +}; diff --git a/app-modules/authorization/src/Enums/LicenseType.php b/app-modules/authorization/src/Enums/LicenseType.php new file mode 100644 index 0000000000..b8d00a8293 --- /dev/null +++ b/app-modules/authorization/src/Enums/LicenseType.php @@ -0,0 +1,40 @@ + 'Conversational AI', + LicenseType::RetentionCrm => 'Retention CRM', + LicenseType::RecruitmentCrm => 'Recruitment CRM', + }; + } + + public function hasAvailableLicenses(): bool + { + $totalLicensesInUse = License::query()->where('type', $this)->count(); + + $licenseSettings = app(LicenseSettings::class); + + $licenseLimit = match ($this) { + LicenseType::ConversationalAi => $licenseSettings->data->limits->conversationalAiSeats, + LicenseType::RetentionCrm => $licenseSettings->data->limits->retentionCrmSeats, + LicenseType::RecruitmentCrm => $licenseSettings->data->limits->recruitmentCrmSeats, + }; + + return $totalLicensesInUse < $licenseLimit; + } +} diff --git a/app-modules/authorization/src/Models/License.php b/app-modules/authorization/src/Models/License.php new file mode 100644 index 0000000000..2bd1c9e128 --- /dev/null +++ b/app-modules/authorization/src/Models/License.php @@ -0,0 +1,24 @@ + LicenseType::class, + ]; + + public function user(): BelongsTo + { + return $this->belongsTo(User::class, 'user_id'); + } +} diff --git a/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php b/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php new file mode 100644 index 0000000000..9eaf5bb06f --- /dev/null +++ b/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php @@ -0,0 +1,19 @@ +hasAvailableLicenses()) { + $fail("There are no available {$licenseType->getLabel()} licenses."); + } + } +} diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php index 4ef2fd43ee..e799e88286 100644 --- a/app/Filament/Resources/UserResource.php +++ b/app/Filament/Resources/UserResource.php @@ -55,6 +55,7 @@ use App\Filament\Resources\UserResource\Pages\ListUsers; use App\Filament\Resources\UserResource\Pages\CreateUser; use App\Filament\Resources\UserResource\RelationManagers\RolesRelationManager; +use App\Filament\Resources\UserResource\RelationManagers\LicensesRelationManager; use App\Filament\Resources\UserResource\RelationManagers\RoleGroupsRelationManager; use App\Filament\Resources\UserResource\RelationManagers\PermissionsRelationManager; @@ -128,6 +129,7 @@ public static function getRelations(): array RoleGroupsRelationManager::class, RolesRelationManager::class, PermissionsRelationManager::class, + LicensesRelationManager::class, ]; } diff --git a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php new file mode 100644 index 0000000000..0e83fbc945 --- /dev/null +++ b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php @@ -0,0 +1,59 @@ +schema([ + Select::make('type') + ->options(LicenseType::class) + ->enum(LicenseType::class) + ->rule(Rule::unique('licenses', 'type')->where('user_id', $this->getOwnerRecord()->getKey())) + ->rule(new LicenseTypeUsageRule()) + ->required(), + ]); + } + + public function table(Table $table): Table + { + return $table + ->recordTitleAttribute('type') + ->columns([ + TextColumn::make('type'), + TextColumn::make('created_at') + ->dateTime(), + ]) + ->headerActions([ + CreateAction::make(), + ]) + ->actions([ + DeleteAction::make(), + ]) + ->bulkActions([ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]) + ->emptyStateActions([ + CreateAction::make(), + ]); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 798a326208..d68162d962 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -53,6 +53,7 @@ use Filament\Models\Contracts\FilamentUser; use Spatie\MediaLibrary\InteractsWithMedia; use Illuminate\Database\Eloquent\SoftDeletes; +use AdvisingApp\Authorization\Models\License; use AdvisingApp\MeetingCenter\Models\Calendar; use AdvisingApp\Assistant\Models\AssistantChat; use AdvisingApp\StudentDataModel\Models\Student; @@ -195,6 +196,11 @@ public function caseloads(): HasMany return $this->hasMany(Caseload::class); } + public function licenses(): HasMany + { + return $this->hasMany(License::class, 'user_id'); + } + public function subscriptions(): HasMany { return $this->hasMany(Subscription::class); From 964c8f7c988992e7b5ded5c4d9a9999bbb4e515f Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 19:05:29 -0500 Subject: [PATCH 076/152] Setup rules and auditing Signed-off-by: Kevin Ullyott --- .../2024_01_02_225406_create_licenses_table.php | 7 ++++--- app-modules/authorization/src/Models/License.php | 8 +++++++- .../RelationManagers/LicensesRelationManager.php | 6 +++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php index 475a106a2a..3dee0c08e4 100644 --- a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php +++ b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php @@ -1,8 +1,9 @@ timestamps(); $table->softDeletes(); - $table->unique(['user_id', 'type']); + $table->uniqueIndex(['user_id', 'type'])->where(fn (Builder $condition) => $condition->whereNull('deleted_at')); }); } }; diff --git a/app-modules/authorization/src/Models/License.php b/app-modules/authorization/src/Models/License.php index 2bd1c9e128..6d9872477d 100644 --- a/app-modules/authorization/src/Models/License.php +++ b/app-modules/authorization/src/Models/License.php @@ -4,11 +4,17 @@ use App\Models\User; use App\Models\BaseModel; +use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; use AdvisingApp\Authorization\Enums\LicenseType; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableConcern; -class License extends BaseModel +class License extends BaseModel implements Auditable { + use AuditableConcern; + use SoftDeletes; + protected $fillable = [ 'type', ]; diff --git a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php index 0e83fbc945..d5b64554b1 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php @@ -26,7 +26,11 @@ public function form(Form $form): Form Select::make('type') ->options(LicenseType::class) ->enum(LicenseType::class) - ->rule(Rule::unique('licenses', 'type')->where('user_id', $this->getOwnerRecord()->getKey())) + ->rule( + Rule::unique('licenses', 'type') + ->where('user_id', $this->getOwnerRecord()->getKey()) + ->whereNull('deleted_at'), + ) ->rule(new LicenseTypeUsageRule()) ->required(), ]); From 7492447f3385952b0c842edc6a81ae887c41deb5 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 19:22:19 -0500 Subject: [PATCH 077/152] helpers and disables Signed-off-by: Kevin Ullyott --- _ide_helper_models.php | 290 +++++++++++++++--- .../authorization/src/Models/License.php | 3 + .../src/Observers/LicenseObserver.php | 16 + .../AuthorizationServiceProvider.php | 10 + .../inventory-management/src/Models/Asset.php | 3 + .../src/Models/AssetLocation.php | 3 + .../src/Models/AssetStatus.php | 3 + .../src/Models/AssetType.php | 3 + .../src/Models/MaintenanceActivity.php | 3 + .../src/Models/MaintenanceProvider.php | 3 + .../meeting-center/src/Models/Event.php | 3 + .../LicensesRelationManager.php | 7 + app/Models/User.php | 2 +- 13 files changed, 310 insertions(+), 39 deletions(-) create mode 100644 app-modules/authorization/src/Observers/LicenseObserver.php diff --git a/_ide_helper_models.php b/_ide_helper_models.php index 8414883ba6..450515d50f 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -1,39 +1,5 @@ - - Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. - - Advising App™ is licensed under the Elastic License 2.0. For more details, - see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. - - Notice: - - - You may not provide the software to third parties as a hosted or managed - service, where the service provides users with access to any substantial set of - the features or functionality of the software. - - You may not move, change, disable, or circumvent the license key functionality - in the software, and you may not remove or obscure any functionality in the - software that is protected by the license key. - - You may not alter, remove, or obscure any licensing, copyright, or other notices - of the licensor in the software. Any use of the licensor’s trademarks is subject - to applicable law. - - Canyon GBS LLC respects the intellectual property rights of others and expects the - same in return. Canyon GBS™ and Advising App™ are registered trademarks of - Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks - vigorously. - - The software solution, including services, infrastructure, and code, is offered as a - Software as a Service (SaaS) by Canyon GBS LLC. - - Use of this software implies agreement to the license terms and conditions as stated - in the Elastic License 2.0. - - For more information or inquiries please visit our website at - https://www.canyongbs.com or contact us via email at legal@canyongbs.com. - - -*/ - // @formatter:off /** * A helper file for your Eloquent Models @@ -330,6 +296,8 @@ class IdeHelperSystemUser {} * @property-read \Illuminate\Database\Eloquent\Collection $events * @property-read int|null $events_count * @property-read mixed $is_admin + * @property-read \Illuminate\Database\Eloquent\Collection $licenses + * @property-read int|null $licenses_count * @property-read \Spatie\MediaLibrary\MediaCollections\Models\Collections\MediaCollection $media * @property-read int|null $media_count * @property-read \Illuminate\Notifications\DatabaseNotificationCollection $notifications @@ -820,6 +788,35 @@ class IdeHelperAssistantChatMessageLog {} class IdeHelperAudit {} } +namespace AdvisingApp\Authorization\Models{ +/** + * AdvisingApp\Authorization\Models\License + * + * @property string $id + * @property string $user_id + * @property \AdvisingApp\Authorization\Enums\LicenseType $type + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at + * @property-read \App\Models\User $user + * @method static \Illuminate\Database\Eloquent\Builder|License newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|License newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|License onlyTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|License query() + * @method static \Illuminate\Database\Eloquent\Builder|License whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereDeletedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereType($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereUserId($value) + * @method static \Illuminate\Database\Eloquent\Builder|License withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|License withoutTrashed() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperLicense {} +} + namespace AdvisingApp\Authorization\Models{ /** * AdvisingApp\Authorization\Models\Permission @@ -1011,7 +1008,7 @@ class IdeHelperCampaign {} * @property string $campaign_id * @property \AdvisingApp\Campaign\Enums\CampaignActionType $type * @property array $data - * @property string $execute_at + * @property \Illuminate\Support\Carbon $execute_at * @property string|null $last_execution_attempt_at * @property string|null $last_execution_attempt_error * @property string|null $successfully_executed_at @@ -1311,6 +1308,7 @@ class IdeHelperEmailTemplate {} * @method static \AdvisingApp\Engagement\Database\Factories\EngagementFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|Engagement hasBeenDelivered() * @method static \Illuminate\Database\Eloquent\Builder|Engagement hasNotBeenDelivered() + * @method static \Illuminate\Database\Eloquent\Builder|Engagement isAwaitingDelivery() * @method static \Illuminate\Database\Eloquent\Builder|Engagement isNotPartOfABatch() * @method static \Illuminate\Database\Eloquent\Builder|Engagement isScheduled() * @method static \Illuminate\Database\Eloquent\Builder|Engagement newModelQuery() @@ -1984,6 +1982,189 @@ class IdeHelperInteractionStatus {} class IdeHelperInteractionType {} } +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\Asset + * + * @property string $id + * @property string $serial_number + * @property string $name + * @property string $description + * @property string $type_id + * @property string $status_id + * @property string $location_id + * @property string $purchase_date + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @property-read \AdvisingApp\InventoryManagement\Models\AssetLocation $location + * @property-read \Illuminate\Database\Eloquent\Collection $maintenanceActivities + * @property-read int|null $maintenance_activities_count + * @property-read \AdvisingApp\InventoryManagement\Models\AssetStatus $status + * @property-read \AdvisingApp\InventoryManagement\Models\AssetType $type + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Asset newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Asset newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Asset query() + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereDescription($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereLocationId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset wherePurchaseDate($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereSerialNumber($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereStatusId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereTypeId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAsset {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\AssetLocation + * + * @property string $id + * @property string $name + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $assets + * @property-read int|null $assets_count + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetLocationFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation query() + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAssetLocation {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\AssetStatus + * + * @property string $id + * @property string $name + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $assets + * @property-read int|null $assets_count + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetStatusFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus query() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAssetStatus {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\AssetType + * + * @property string $id + * @property string $name + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $assets + * @property-read int|null $assets_count + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetTypeFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetType newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetType query() + * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAssetType {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\MaintenanceActivity + * + * @property string $id + * @property string $asset_id + * @property string|null $maintenance_provider_id + * @property string $details + * @property \Illuminate\Support\Carbon|null $scheduled_date + * @property \Illuminate\Support\Carbon|null $completed_date + * @property \AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus $status + * @property string|null $notes + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \AdvisingApp\InventoryManagement\Models\Asset $asset + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @property-read \AdvisingApp\InventoryManagement\Models\MaintenanceProvider|null $maintenanceProvider + * @method static \AdvisingApp\InventoryManagement\Database\Factories\MaintenanceActivityFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity query() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereAssetId($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereCompletedDate($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereDetails($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereMaintenanceProviderId($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereNotes($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereScheduledDate($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereStatus($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperMaintenanceActivity {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\MaintenanceProvider + * + * @property string $id + * @property string $name + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @property-read \Illuminate\Database\Eloquent\Collection $maintenanceActivities + * @property-read int|null $maintenance_activities_count + * @method static \AdvisingApp\InventoryManagement\Database\Factories\MaintenanceProviderFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider query() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperMaintenanceProvider {} +} + namespace AdvisingApp\KnowledgeBase\Models{ /** * AdvisingApp\KnowledgeBase\Models\KnowledgeBaseCategory @@ -2022,8 +2203,8 @@ class IdeHelperKnowledgeBaseCategory {} * @property string $id * @property string $question * @property bool $public - * @property string|null $solution - * @property string|null $notes + * @property array|null $solution + * @property array|null $notes * @property string|null $quality_id * @property string|null $status_id * @property string|null $category_id @@ -2194,6 +2375,38 @@ class IdeHelperCalendar {} class IdeHelperCalendarEvent {} } +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\Event + * + * @property string $id + * @property string $title + * @property string|null $description + * @property string|null $location + * @property int|null $capacity + * @property \Illuminate\Support\Carbon $starts_at + * @property \Illuminate\Support\Carbon $ends_at + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @method static \AdvisingApp\MeetingCenter\Database\Factories\EventFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|Event newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Event newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Event query() + * @method static \Illuminate\Database\Eloquent\Builder|Event whereCapacity($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereDescription($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereEndsAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereLocation($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereStartsAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereTitle($value) + * @method static \Illuminate\Database\Eloquent\Builder|Event whereUpdatedAt($value) + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEvent {} +} + namespace AdvisingApp\Notification\Models{ /** * AdvisingApp\Notification\Models\OutboundDeliverable @@ -2290,7 +2503,7 @@ class IdeHelperSubscription {} * @property string|null $phone * @property string|null $address * @property string|null $address_2 - * @property string|null $birthdate + * @property \Illuminate\Support\Carbon|null $birthdate * @property string|null $hsgrad * @property string|null $assigned_to_id * @property string|null $created_by_id @@ -2744,6 +2957,7 @@ class IdeHelperProgram {} * AdvisingApp\StudentDataModel\Models\Student * * @property string $display_name + * @property string $mobile * @property-read \Illuminate\Database\Eloquent\Collection $alerts * @property-read int|null $alerts_count * @property-read \Illuminate\Database\Eloquent\Collection $applicationSubmissions diff --git a/app-modules/authorization/src/Models/License.php b/app-modules/authorization/src/Models/License.php index 6d9872477d..209491a7d3 100644 --- a/app-modules/authorization/src/Models/License.php +++ b/app-modules/authorization/src/Models/License.php @@ -10,6 +10,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableConcern; +/** + * @mixin IdeHelperLicense + */ class License extends BaseModel implements Auditable { use AuditableConcern; diff --git a/app-modules/authorization/src/Observers/LicenseObserver.php b/app-modules/authorization/src/Observers/LicenseObserver.php new file mode 100644 index 0000000000..a06f90af0a --- /dev/null +++ b/app-modules/authorization/src/Observers/LicenseObserver.php @@ -0,0 +1,16 @@ +type->hasAvailableLicenses()) { + throw new Exception("There are no available {$license->type->getLabel()} licenses."); + } + } +} diff --git a/app-modules/authorization/src/Providers/AuthorizationServiceProvider.php b/app-modules/authorization/src/Providers/AuthorizationServiceProvider.php index 22a4eba828..ce36123f8b 100644 --- a/app-modules/authorization/src/Providers/AuthorizationServiceProvider.php +++ b/app-modules/authorization/src/Providers/AuthorizationServiceProvider.php @@ -40,6 +40,7 @@ use Illuminate\Support\Facades\Event; use Illuminate\Support\ServiceProvider; use AdvisingApp\Authorization\Models\Role; +use AdvisingApp\Authorization\Models\License; use AdvisingApp\Authorization\Models\RoleGroup; use AdvisingApp\Authorization\Models\Permission; use AdvisingApp\Authorization\AuthorizationPlugin; @@ -48,6 +49,7 @@ use Illuminate\Database\Eloquent\Relations\Relation; use SocialiteProviders\Google\GoogleExtendSocialite; use AdvisingApp\Authorization\AuthorizationRoleRegistry; +use AdvisingApp\Authorization\Observers\LicenseObserver; use AdvisingApp\Authorization\AuthorizationPermissionRegistry; class AuthorizationServiceProvider extends ServiceProvider @@ -73,8 +75,11 @@ public function boot(AuthorizationPermissionRegistry $permissionRegistry, Author 'role' => Role::class, 'permission' => Permission::class, 'role_group' => RoleGroup::class, + 'license' => License::class, ]); + $this->registerObservers(); + $permissionRegistry->registerApiPermissions( module: 'authorization', path: 'permissions/api/custom' @@ -105,4 +110,9 @@ public function boot(AuthorizationPermissionRegistry $permissionRegistry, Author listener: GoogleExtendSocialite::class . '@handle' ); } + + public function registerObservers(): void + { + License::observe(LicenseObserver::class); + } } diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index a2d9dca12d..0c47192b9e 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -42,6 +42,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAsset + */ class Asset extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/AssetLocation.php b/app-modules/inventory-management/src/Models/AssetLocation.php index 37c656e292..d310c7f8b9 100644 --- a/app-modules/inventory-management/src/Models/AssetLocation.php +++ b/app-modules/inventory-management/src/Models/AssetLocation.php @@ -41,6 +41,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAssetLocation + */ class AssetLocation extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/AssetStatus.php b/app-modules/inventory-management/src/Models/AssetStatus.php index da1000a351..5214a52f50 100644 --- a/app-modules/inventory-management/src/Models/AssetStatus.php +++ b/app-modules/inventory-management/src/Models/AssetStatus.php @@ -41,6 +41,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAssetStatus + */ class AssetStatus extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/AssetType.php b/app-modules/inventory-management/src/Models/AssetType.php index e00d56af4e..f1a9bde9f0 100644 --- a/app-modules/inventory-management/src/Models/AssetType.php +++ b/app-modules/inventory-management/src/Models/AssetType.php @@ -41,6 +41,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAssetType + */ class AssetType extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/MaintenanceActivity.php b/app-modules/inventory-management/src/Models/MaintenanceActivity.php index 71c75c3ad5..7431ad186f 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceActivity.php +++ b/app-modules/inventory-management/src/Models/MaintenanceActivity.php @@ -42,6 +42,9 @@ use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus; +/** + * @mixin IdeHelperMaintenanceActivity + */ class MaintenanceActivity extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/MaintenanceProvider.php b/app-modules/inventory-management/src/Models/MaintenanceProvider.php index c319b8eec9..79c81e28e8 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceProvider.php +++ b/app-modules/inventory-management/src/Models/MaintenanceProvider.php @@ -41,6 +41,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperMaintenanceProvider + */ class MaintenanceProvider extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/meeting-center/src/Models/Event.php b/app-modules/meeting-center/src/Models/Event.php index 401917e9be..6484c5341e 100644 --- a/app-modules/meeting-center/src/Models/Event.php +++ b/app-modules/meeting-center/src/Models/Event.php @@ -38,6 +38,9 @@ use App\Models\BaseModel; +/** + * @mixin IdeHelperEvent + */ class Event extends BaseModel { protected $fillable = [ diff --git a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php index d5b64554b1..62e5dd8653 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php @@ -2,6 +2,7 @@ namespace App\Filament\Resources\UserResource\RelationManagers; +use App\Models\User; use Filament\Forms\Form; use Filament\Tables\Table; use Illuminate\Validation\Rule; @@ -32,6 +33,12 @@ public function form(Form $form): Form ->whereNull('deleted_at'), ) ->rule(new LicenseTypeUsageRule()) + ->disableOptionWhen(function (string $value) { + /** @var User $ownerRecord */ + $ownerRecord = $this->getOwnerRecord(); + + return ! LicenseType::from($value)->hasAvailableLicenses() || $ownerRecord->licenses()->where('type', $value)->exists(); + }) ->required(), ]); } diff --git a/app/Models/User.php b/app/Models/User.php index d68162d962..08cb1dc89b 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -52,8 +52,8 @@ use Lab404\Impersonate\Models\Impersonate; use Filament\Models\Contracts\FilamentUser; use Spatie\MediaLibrary\InteractsWithMedia; -use Illuminate\Database\Eloquent\SoftDeletes; use AdvisingApp\Authorization\Models\License; +use Illuminate\Database\Eloquent\SoftDeletes; use AdvisingApp\MeetingCenter\Models\Calendar; use AdvisingApp\Assistant\Models\AssistantChat; use AdvisingApp\StudentDataModel\Models\Student; From a8f06249160f94a54e76bf205450d9cfaa96b21f Mon Sep 17 00:00:00 2001 From: Orrison Date: Wed, 3 Jan 2024 00:27:06 +0000 Subject: [PATCH 078/152] chore: fix enforcement of copyright on all files --- _ide_helper_models.php | 34 +++++++++++++++++++ ...024_01_02_225406_create_licenses_table.php | 34 +++++++++++++++++++ .../authorization/src/Enums/LicenseType.php | 34 +++++++++++++++++++ .../authorization/src/Models/License.php | 34 +++++++++++++++++++ .../src/Observers/LicenseObserver.php | 34 +++++++++++++++++++ .../src/Rules/LicenseTypeUsageRule.php | 34 +++++++++++++++++++ .../LicensesRelationManager.php | 34 +++++++++++++++++++ 7 files changed, 238 insertions(+) diff --git a/_ide_helper_models.php b/_ide_helper_models.php index 450515d50f..520c0c5be7 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + // @formatter:off /** * A helper file for your Eloquent Models diff --git a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php index 3dee0c08e4..eac079e191 100644 --- a/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php +++ b/app-modules/authorization/database/migrations/2024_01_02_225406_create_licenses_table.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use Illuminate\Database\Query\Builder; use Illuminate\Database\Migrations\Migration; use Tpetry\PostgresqlEnhanced\Schema\Blueprint; diff --git a/app-modules/authorization/src/Enums/LicenseType.php b/app-modules/authorization/src/Enums/LicenseType.php index b8d00a8293..5e7e9d06db 100644 --- a/app-modules/authorization/src/Enums/LicenseType.php +++ b/app-modules/authorization/src/Enums/LicenseType.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Authorization\Enums; use App\Settings\LicenseSettings; diff --git a/app-modules/authorization/src/Models/License.php b/app-modules/authorization/src/Models/License.php index 209491a7d3..91dc3f04c9 100644 --- a/app-modules/authorization/src/Models/License.php +++ b/app-modules/authorization/src/Models/License.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Authorization\Models; use App\Models\User; diff --git a/app-modules/authorization/src/Observers/LicenseObserver.php b/app-modules/authorization/src/Observers/LicenseObserver.php index a06f90af0a..c1280f5f78 100644 --- a/app-modules/authorization/src/Observers/LicenseObserver.php +++ b/app-modules/authorization/src/Observers/LicenseObserver.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Authorization\Observers; use Exception; diff --git a/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php b/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php index 9eaf5bb06f..16ed3c0982 100644 --- a/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php +++ b/app-modules/authorization/src/Rules/LicenseTypeUsageRule.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Authorization\Rules; use Closure; diff --git a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php index 62e5dd8653..1487568274 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/LicensesRelationManager.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace App\Filament\Resources\UserResource\RelationManagers; use App\Models\User; From dd49f2a4ea52995b894342180509aa95e8232ff6 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Thu, 28 Dec 2023 08:32:55 -0500 Subject: [PATCH 079/152] Create AssetExchange model, add soft deletes. --- ..._12_26_181818_create_asset_types_table.php | 1 + ..._26_181828_create_asset_statuses_table.php | 2 + ...26_181837_create_asset_locations_table.php | 1 + .../2023_12_26_181855_create_assets_table.php | 1 + ...502_create_maintenance_providers_table.php | 1 + ...12_create_maintenance_activities_table.php | 1 + ...28_131317_create_asset_exchanges_table.php | 22 +++++++++ .../inventory-management/src/Models/Asset.php | 24 ++++++++-- .../src/Models/AssetExchange.php | 45 +++++++++++++++++++ .../src/Models/AssetLocation.php | 6 ++- .../src/Models/AssetStatus.php | 12 ++++- .../src/Models/AssetType.php | 6 ++- .../src/Models/MaintenanceActivity.php | 8 ++-- .../src/Models/MaintenanceProvider.php | 2 + .../src/Models/ServiceRequestStatus.php | 1 - 15 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php create mode 100644 app-modules/inventory-management/src/Models/AssetExchange.php diff --git a/app-modules/inventory-management/database/migrations/2023_12_26_181818_create_asset_types_table.php b/app-modules/inventory-management/database/migrations/2023_12_26_181818_create_asset_types_table.php index c2d2c62e99..64a6b5b6f8 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_26_181818_create_asset_types_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_26_181818_create_asset_types_table.php @@ -45,6 +45,7 @@ public function up(): void $table->uuid('id')->primary(); $table->string('name'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_26_181828_create_asset_statuses_table.php b/app-modules/inventory-management/database/migrations/2023_12_26_181828_create_asset_statuses_table.php index c50e496550..01fe18f9cc 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_26_181828_create_asset_statuses_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_26_181828_create_asset_statuses_table.php @@ -43,8 +43,10 @@ public function up(): void { Schema::create('asset_statuses', function (Blueprint $table) { $table->uuid('id')->primary(); + $table->string('classification'); $table->string('name'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_26_181837_create_asset_locations_table.php b/app-modules/inventory-management/database/migrations/2023_12_26_181837_create_asset_locations_table.php index f3264d6e79..6409f01e97 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_26_181837_create_asset_locations_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_26_181837_create_asset_locations_table.php @@ -45,6 +45,7 @@ public function up(): void $table->uuid('id')->primary(); $table->string('name'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_26_181855_create_assets_table.php b/app-modules/inventory-management/database/migrations/2023_12_26_181855_create_assets_table.php index 57de8650b8..46ee693db6 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_26_181855_create_assets_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_26_181855_create_assets_table.php @@ -51,6 +51,7 @@ public function up(): void $table->foreignUuid('location_id')->constrained('asset_locations'); $table->timestamp('purchase_date'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_27_175502_create_maintenance_providers_table.php b/app-modules/inventory-management/database/migrations/2023_12_27_175502_create_maintenance_providers_table.php index c3ca71714d..f12366afe3 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_27_175502_create_maintenance_providers_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_27_175502_create_maintenance_providers_table.php @@ -45,6 +45,7 @@ public function up(): void $table->uuid('id')->primary(); $table->string('name'); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_27_175512_create_maintenance_activities_table.php b/app-modules/inventory-management/database/migrations/2023_12_27_175512_create_maintenance_activities_table.php index 3caa469ecd..b78014de87 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_27_175512_create_maintenance_activities_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_27_175512_create_maintenance_activities_table.php @@ -55,6 +55,7 @@ public function up(): void $table->string('status')->default(MaintenanceActivityStatus::Scheduled); $table->longText('notes')->nullable(); $table->timestamps(); + $table->softDeletes(); }); } }; diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php new file mode 100644 index 0000000000..d474c186f1 --- /dev/null +++ b/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php @@ -0,0 +1,22 @@ +uuid('id')->primary(); + $table->foreignUuid('asset_id')->constrained('assets'); + $table->string('type'); + $table->string('performed_by_type')->nullable(); + $table->string('performed_by_id')->nullable(); + $table->string('for_type'); + $table->string('for_id'); + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index 0c47192b9e..02c7dd281f 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -36,11 +36,13 @@ namespace AdvisingApp\InventoryManagement\Models; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\AssetExchangeType; use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; -use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; /** * @mixin IdeHelperAsset @@ -48,6 +50,7 @@ class Asset extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'description', @@ -78,4 +81,19 @@ public function maintenanceActivities(): HasMany { return $this->hasMany(MaintenanceActivity::class, 'asset_id'); } + + public function exchanges(): HasMany + { + return $this->hasMany(AssetExchange::class, 'asset_id'); + } + + public function checkOuts(): HasMany + { + return $this->exchanges()->where('type', AssetExchangeType::CheckOut); + } + + public function checkIns(): HasMany + { + return $this->exchanges()->where('type', AssetExchangeType::CheckIn); + } } diff --git a/app-modules/inventory-management/src/Models/AssetExchange.php b/app-modules/inventory-management/src/Models/AssetExchange.php new file mode 100644 index 0000000000..41107d7e83 --- /dev/null +++ b/app-modules/inventory-management/src/Models/AssetExchange.php @@ -0,0 +1,45 @@ + AssetExchangeType::class, + ]; + + public function asset(): BelongsTo + { + return $this->belongsTo(Asset::class, 'asset_id'); + } + + public function scopeCheckIn(Builder $query): void + { + $query->where('type', AssetExchangeType::CheckIn); + } + + public function scopeCheckOut(Builder $query): void + { + $query->where('type', AssetExchangeType::CheckOut); + } +} diff --git a/app-modules/inventory-management/src/Models/AssetLocation.php b/app-modules/inventory-management/src/Models/AssetLocation.php index d310c7f8b9..35e1f96256 100644 --- a/app-modules/inventory-management/src/Models/AssetLocation.php +++ b/app-modules/inventory-management/src/Models/AssetLocation.php @@ -36,10 +36,11 @@ namespace AdvisingApp\InventoryManagement\Models; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\Relations\HasMany; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; /** * @mixin IdeHelperAssetLocation @@ -47,6 +48,7 @@ class AssetLocation extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'name', diff --git a/app-modules/inventory-management/src/Models/AssetStatus.php b/app-modules/inventory-management/src/Models/AssetStatus.php index 5214a52f50..ad32d6023a 100644 --- a/app-modules/inventory-management/src/Models/AssetStatus.php +++ b/app-modules/inventory-management/src/Models/AssetStatus.php @@ -36,10 +36,12 @@ namespace AdvisingApp\InventoryManagement\Models; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\Relations\HasMany; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; /** * @mixin IdeHelperAssetStatus @@ -47,11 +49,17 @@ class AssetStatus extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ + 'classification', 'name', ]; + protected $casts = [ + 'classification' => SystemAssetStatusClassification::class, + ]; + public function assets(): HasMany { return $this->hasMany(Asset::class, 'status_id'); diff --git a/app-modules/inventory-management/src/Models/AssetType.php b/app-modules/inventory-management/src/Models/AssetType.php index f1a9bde9f0..1a492ebdfb 100644 --- a/app-modules/inventory-management/src/Models/AssetType.php +++ b/app-modules/inventory-management/src/Models/AssetType.php @@ -36,10 +36,11 @@ namespace AdvisingApp\InventoryManagement\Models; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\Relations\HasMany; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; /** * @mixin IdeHelperAssetType @@ -47,6 +48,7 @@ class AssetType extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'name', diff --git a/app-modules/inventory-management/src/Models/MaintenanceActivity.php b/app-modules/inventory-management/src/Models/MaintenanceActivity.php index 7431ad186f..6bc1748b66 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceActivity.php +++ b/app-modules/inventory-management/src/Models/MaintenanceActivity.php @@ -36,11 +36,12 @@ namespace AdvisingApp\InventoryManagement\Models; -use App\Models\BaseModel; -use OwenIt\Auditing\Contracts\Auditable; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus; +use App\Models\BaseModel; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\SoftDeletes; +use OwenIt\Auditing\Contracts\Auditable; /** * @mixin IdeHelperMaintenanceActivity @@ -48,6 +49,7 @@ class MaintenanceActivity extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'asset_id', diff --git a/app-modules/inventory-management/src/Models/MaintenanceProvider.php b/app-modules/inventory-management/src/Models/MaintenanceProvider.php index 79c81e28e8..6acc6b5019 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceProvider.php +++ b/app-modules/inventory-management/src/Models/MaintenanceProvider.php @@ -38,6 +38,7 @@ use App\Models\BaseModel; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; @@ -47,6 +48,7 @@ class MaintenanceProvider extends BaseModel implements Auditable { use AuditableTrait; + use SoftDeletes; protected $fillable = [ 'name', diff --git a/app-modules/service-management/src/Models/ServiceRequestStatus.php b/app-modules/service-management/src/Models/ServiceRequestStatus.php index 22c8749bc9..40bd3148b5 100644 --- a/app-modules/service-management/src/Models/ServiceRequestStatus.php +++ b/app-modules/service-management/src/Models/ServiceRequestStatus.php @@ -52,7 +52,6 @@ class ServiceRequestStatus extends BaseModel implements Auditable { use SoftDeletes; - use HasUuids; use AuditableTrait; protected $fillable = [ From 77d723bc9704e548def6b64164c17016308f07d6 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Thu, 28 Dec 2023 08:33:16 -0500 Subject: [PATCH 080/152] Asset exchange type and system classification. --- .../src/Enums/AssetExchangeType.php | 50 +++++++++++++++++ .../Enums/SystemAssetStatusClassification.php | 53 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 app-modules/inventory-management/src/Enums/AssetExchangeType.php create mode 100644 app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php diff --git a/app-modules/inventory-management/src/Enums/AssetExchangeType.php b/app-modules/inventory-management/src/Enums/AssetExchangeType.php new file mode 100644 index 0000000000..9af8a53029 --- /dev/null +++ b/app-modules/inventory-management/src/Enums/AssetExchangeType.php @@ -0,0 +1,50 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Enums; + +use Filament\Support\Contracts\HasLabel; + +enum AssetExchangeType: string implements HasLabel +{ + case CheckIn = 'check_in'; + case CheckOut = 'check_out'; + + public function getLabel(): ?string + { + return $this->name; + } +} diff --git a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php new file mode 100644 index 0000000000..d1b153e600 --- /dev/null +++ b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php @@ -0,0 +1,53 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Enums; + +use Filament\Support\Contracts\HasLabel; + +enum SystemAssetStatusClassification: string implements HasLabel +{ + case Available = 'available'; + + case Unavailable = 'unavailable'; + + case Custom = 'custom'; + + public function getLabel(): ?string + { + return $this->name; + } +} From b71c071c787768563c7d44fa31c25b2ea3f07202 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Thu, 28 Dec 2023 08:42:56 -0500 Subject: [PATCH 081/152] Add policies. --- .../src/Policies/AssetExchangePolicy.php | 100 ++++++++++++++++++ .../src/Policies/AssetLocationPolicy.php | 100 ++++++++++++++++++ .../src/Policies/AssetPolicy.php | 100 ++++++++++++++++++ .../src/Policies/AssetStatusPolicy.php | 100 ++++++++++++++++++ .../src/Policies/AssetTypePolicy.php | 100 ++++++++++++++++++ .../Policies/MaintenanceActivityPolicy.php | 100 ++++++++++++++++++ .../Policies/MaintenanceProviderPolicy.php | 100 ++++++++++++++++++ 7 files changed, 700 insertions(+) create mode 100644 app-modules/inventory-management/src/Policies/AssetExchangePolicy.php create mode 100644 app-modules/inventory-management/src/Policies/AssetLocationPolicy.php create mode 100644 app-modules/inventory-management/src/Policies/AssetPolicy.php create mode 100644 app-modules/inventory-management/src/Policies/AssetStatusPolicy.php create mode 100644 app-modules/inventory-management/src/Policies/AssetTypePolicy.php create mode 100644 app-modules/inventory-management/src/Policies/MaintenanceActivityPolicy.php create mode 100644 app-modules/inventory-management/src/Policies/MaintenanceProviderPolicy.php diff --git a/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php b/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php new file mode 100644 index 0000000000..031744e4f1 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetExchange; + +class AssetExchangePolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_exchange.view-any', + denyResponse: 'You do not have permission to view asset exchanges.' + ); + } + + public function view(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.view', "asset_exchange.{$assetExchange->id}.view"], + denyResponse: 'You do not have permission to view this asset exchange.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_exchange.create', + denyResponse: 'You do not have permission to create asset exchanges.' + ); + } + + public function update(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.update', "asset_exchange.{$assetExchange->id}.update"], + denyResponse: 'You do not have permission to update this asset exchange.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.delete', "asset_exchange.{$assetExchange->id}.delete"], + denyResponse: 'You do not have permission to delete this asset exchange.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.restore', "asset_exchange.{$assetExchange->id}.restore"], + denyResponse: 'You do not have permission to restore this asset exchange.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_exchange.*.force-delete', "asset_exchange.{$assetExchange->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset exchange.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/AssetLocationPolicy.php b/app-modules/inventory-management/src/Policies/AssetLocationPolicy.php new file mode 100644 index 0000000000..f6500dc256 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetLocationPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetLocation; + +class AssetLocationPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_location.view-any', + denyResponse: 'You do not have permission to view asset locations.' + ); + } + + public function view(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.view', "asset_location.{$assetLocation->id}.view"], + denyResponse: 'You do not have permission to view this asset location.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_location.create', + denyResponse: 'You do not have permission to create asset locations.' + ); + } + + public function update(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.update', "asset_location.{$assetLocation->id}.update"], + denyResponse: 'You do not have permission to update this asset location.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.delete', "asset_location.{$assetLocation->id}.delete"], + denyResponse: 'You do not have permission to delete this asset location.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.restore', "asset_location.{$assetLocation->id}.restore"], + denyResponse: 'You do not have permission to restore this asset location.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetLocation $assetLocation): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_location.*.force-delete', "asset_location.{$assetLocation->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset location.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/AssetPolicy.php b/app-modules/inventory-management/src/Policies/AssetPolicy.php new file mode 100644 index 0000000000..ec0b8e5140 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\Asset; + +class AssetPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset.view-any', + denyResponse: 'You do not have permission to view assets.' + ); + } + + public function view(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.view', "asset.{$asset->id}.view"], + denyResponse: 'You do not have permission to view this asset.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset.create', + denyResponse: 'You do not have permission to create assets.' + ); + } + + public function update(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.update', "asset.{$asset->id}.update"], + denyResponse: 'You do not have permission to update this asset.' + ); + } + + public function delete(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.delete', "asset.{$asset->id}.delete"], + denyResponse: 'You do not have permission to delete this asset.' + ); + } + + public function restore(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.restore', "asset.{$asset->id}.restore"], + denyResponse: 'You do not have permission to restore this asset.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, Asset $asset): Response + { + return $authenticatable->canOrElse( + abilities: ['asset.*.force-delete', "asset.{$asset->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/AssetStatusPolicy.php b/app-modules/inventory-management/src/Policies/AssetStatusPolicy.php new file mode 100644 index 0000000000..1e973501b9 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetStatusPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetStatus; + +class AssetStatusPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_status.view-any', + denyResponse: 'You do not have permission to view asset statuses.' + ); + } + + public function view(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.view', "asset_status.{$assetStatus->id}.view"], + denyResponse: 'You do not have permission to view this asset status.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_status.create', + denyResponse: 'You do not have permission to create asset statuses.' + ); + } + + public function update(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.update', "asset_status.{$assetStatus->id}.update"], + denyResponse: 'You do not have permission to update this asset status.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.delete', "asset_status.{$assetStatus->id}.delete"], + denyResponse: 'You do not have permission to delete this asset status.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.restore', "asset_status.{$assetStatus->id}.restore"], + denyResponse: 'You do not have permission to restore this asset status.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetStatus $assetStatus): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_status.*.force-delete', "asset_status.{$assetStatus->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset status.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/AssetTypePolicy.php b/app-modules/inventory-management/src/Policies/AssetTypePolicy.php new file mode 100644 index 0000000000..952f9140ad --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetTypePolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetType; + +class AssetTypePolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_type.view-any', + denyResponse: 'You do not have permission to view asset types.' + ); + } + + public function view(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.view', "asset_type.{$assetType->id}.view"], + denyResponse: 'You do not have permission to view this asset type.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_type.create', + denyResponse: 'You do not have permission to create asset types.' + ); + } + + public function update(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.update', "asset_type.{$assetType->id}.update"], + denyResponse: 'You do not have permission to update this asset type.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.delete', "asset_type.{$assetType->id}.delete"], + denyResponse: 'You do not have permission to delete this asset type.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.restore', "asset_type.{$assetType->id}.restore"], + denyResponse: 'You do not have permission to restore this asset type.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetType $assetType): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_type.*.force-delete', "asset_type.{$assetType->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset type.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/MaintenanceActivityPolicy.php b/app-modules/inventory-management/src/Policies/MaintenanceActivityPolicy.php new file mode 100644 index 0000000000..fe5911d6c3 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/MaintenanceActivityPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\MaintenanceActivity; + +class MaintenanceActivityPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'maintenance_activity.view-any', + denyResponse: 'You do not have permission to view maintenance activities.' + ); + } + + public function view(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.view', "maintenance_activity.{$maintenanceActivity->id}.view"], + denyResponse: 'You do not have permission to view this maintenance activity.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'maintenance_activity.create', + denyResponse: 'You do not have permission to create maintenance activities.' + ); + } + + public function update(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.update', "maintenance_activity.{$maintenanceActivity->id}.update"], + denyResponse: 'You do not have permission to update this maintenance activity.' + ); + } + + public function delete(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.delete', "maintenance_activity.{$maintenanceActivity->id}.delete"], + denyResponse: 'You do not have permission to delete this maintenance activity.' + ); + } + + public function restore(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.restore', "maintenance_activity.{$maintenanceActivity->id}.restore"], + denyResponse: 'You do not have permission to restore this maintenance activity.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, MaintenanceActivity $maintenanceActivity): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_activity.*.force-delete', "maintenance_activity.{$maintenanceActivity->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this maintenance activity.' + ); + } +} diff --git a/app-modules/inventory-management/src/Policies/MaintenanceProviderPolicy.php b/app-modules/inventory-management/src/Policies/MaintenanceProviderPolicy.php new file mode 100644 index 0000000000..fab3fb32a0 --- /dev/null +++ b/app-modules/inventory-management/src/Policies/MaintenanceProviderPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\MaintenanceProvider; + +class MaintenanceProviderPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'maintenance_provider.view-any', + denyResponse: 'You do not have permission to view maintenance providers.' + ); + } + + public function view(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.view', "maintenance_provider.{$maintenanceProvider->id}.view"], + denyResponse: 'You do not have permission to view this maintenance provider.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'maintenance_provider.create', + denyResponse: 'You do not have permission to create maintenance providers.' + ); + } + + public function update(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.update', "maintenance_provider.{$maintenanceProvider->id}.update"], + denyResponse: 'You do not have permission to update this maintenance provider.' + ); + } + + public function delete(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.delete', "maintenance_provider.{$maintenanceProvider->id}.delete"], + denyResponse: 'You do not have permission to delete this maintenance provider.' + ); + } + + public function restore(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.restore', "maintenance_provider.{$maintenanceProvider->id}.restore"], + denyResponse: 'You do not have permission to restore this maintenance provider.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, MaintenanceProvider $maintenanceProvider): Response + { + return $authenticatable->canOrElse( + abilities: ['maintenance_provider.*.force-delete', "maintenance_provider.{$maintenanceProvider->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this maintenance provider.' + ); + } +} From d6e7cca8a31daa17715f45653f9ed1db637e5948 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Tue, 2 Jan 2024 13:45:43 -0500 Subject: [PATCH 082/152] Utilize two model system. --- .../factories/AssetCheckInFactory.php | 45 ++++++++++++++ .../factories/AssetCheckOutFactory.php | 53 ++++++++++++++++ .../database/factories/AssetStatusFactory.php | 2 + ...8_174428_create_asset_check_ins_table.php} | 13 ++-- ...8_174437_create_asset_check_outs_table.php | 25 ++++++++ .../database/seeders/AssetSeeder.php | 11 +++- .../database/seeders/AssetStatusSeeder.php | 8 ++- .../src/Enums/AssetExchangeType.php | 50 --------------- .../inventory-management/src/Models/Asset.php | 22 +++---- .../src/Models/AssetCheckIn.php | 59 ++++++++++++++++++ .../src/Models/AssetCheckOut.php | 61 +++++++++++++++++++ .../src/Models/AssetExchange.php | 45 -------------- .../src/Models/AssetStatus.php | 8 +-- .../InventoryManagementServiceProvider.php | 4 ++ 14 files changed, 285 insertions(+), 121 deletions(-) create mode 100644 app-modules/inventory-management/database/factories/AssetCheckInFactory.php create mode 100644 app-modules/inventory-management/database/factories/AssetCheckOutFactory.php rename app-modules/inventory-management/database/migrations/{2023_12_28_131317_create_asset_exchanges_table.php => 2023_12_28_174428_create_asset_check_ins_table.php} (52%) create mode 100644 app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php delete mode 100644 app-modules/inventory-management/src/Enums/AssetExchangeType.php create mode 100644 app-modules/inventory-management/src/Models/AssetCheckIn.php create mode 100644 app-modules/inventory-management/src/Models/AssetCheckOut.php delete mode 100644 app-modules/inventory-management/src/Models/AssetExchange.php diff --git a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php new file mode 100644 index 0000000000..793d21673d --- /dev/null +++ b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php @@ -0,0 +1,45 @@ + + */ +class AssetCheckInFactory extends Factory +{ + public function definition(): array + { + $checkedOutBy = User::factory()->create(); + + return [ + 'asset_id' => Asset::factory(), + 'checked_in_by_type' => $checkedOutBy->getMorphClass(), + 'checked_in_by_id' => $checkedOutBy->getKey(), + 'checked_in_from_type' => fake()->randomElement([ + (new Student())->getMorphClass(), + (new Prospect())->getMorphClass(), + ]), + 'checked_in_from_id' => function (array $attributes) { + $checkedInFromClass = Relation::getMorphedModel($attributes['checked_in_from_type']); + + /** @var Student|Prospect $senderModel */ + $checkedInFromModel = new $checkedInFromClass(); + + $checkedInFromModel = $checkedInFromClass === Student::class + ? Student::inRandomOrder()->first() ?? Student::factory()->create() + : $checkedInFromModel::factory()->create(); + + return $checkedInFromModel->getKey(); + }, + 'checked_in_at' => fake()->dateTimeBetween('-1 year', 'now'), + 'notes' => fake()->paragraph(), + ]; + } +} diff --git a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php new file mode 100644 index 0000000000..f4e1d061c3 --- /dev/null +++ b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php @@ -0,0 +1,53 @@ + + */ +class AssetCheckOutFactory extends Factory +{ + public function definition(): array + { + $checkedOutBy = User::factory()->create(); + + return [ + 'asset_id' => Asset::factory(), + // TODO Add variance to this column so that some check outs do not have corresponding check ins + 'asset_check_in_id' => null, + 'checked_out_by_type' => $checkedOutBy->getMorphClass(), + 'checked_out_by_id' => $checkedOutBy->getKey(), + 'checked_out_to_type' => fake()->randomElement([ + (new Student())->getMorphClass(), + (new Prospect())->getMorphClass(), + ]), + 'checked_out_to_id' => function (array $attributes) { + $checkedOutToClass = Relation::getMorphedModel($attributes['checked_out_to_type']); + + /** @var Student|Prospect $senderModel */ + $checkedOutToModel = new $checkedOutToClass(); + + $checkedOutToModel = $checkedOutToClass === Student::class + ? Student::inRandomOrder()->first() ?? Student::factory()->create() + : $checkedOutToModel::factory()->create(); + + return $checkedOutToModel->getKey(); + }, + 'checked_out_at' => fake()->dateTimeBetween('-1 year', 'now'), + 'expected_check_in_at' => function (array $attributes) { + $checkedOutAt = Carbon::parse($attributes['checked_out_at']); + + return fake()->dateTimeBetween($checkedOutAt->addDays(1), $checkedOutAt->addDays(50)); + }, + 'notes' => fake()->paragraph(), + ]; + } +} diff --git a/app-modules/inventory-management/database/factories/AssetStatusFactory.php b/app-modules/inventory-management/database/factories/AssetStatusFactory.php index 75ea75e646..412da2f51c 100644 --- a/app-modules/inventory-management/database/factories/AssetStatusFactory.php +++ b/app-modules/inventory-management/database/factories/AssetStatusFactory.php @@ -37,6 +37,7 @@ namespace AdvisingApp\InventoryManagement\Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\AdvisingApp\InventoryManagement\Models\AssetStatus> @@ -46,6 +47,7 @@ class AssetStatusFactory extends Factory public function definition(): array { return [ + 'classification' => SystemAssetStatusClassification::Unavailable, 'name' => fake()->word(), ]; } diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php similarity index 52% rename from app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php rename to app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php index d474c186f1..08c435f4bb 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_28_131317_create_asset_exchanges_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php @@ -7,14 +7,15 @@ return new class () extends Migration { public function up(): void { - Schema::create('asset_exchanges', function (Blueprint $table) { + Schema::create('asset_check_ins', function (Blueprint $table) { $table->uuid('id')->primary(); $table->foreignUuid('asset_id')->constrained('assets'); - $table->string('type'); - $table->string('performed_by_type')->nullable(); - $table->string('performed_by_id')->nullable(); - $table->string('for_type'); - $table->string('for_id'); + $table->string('checked_in_by_type')->nullable(); + $table->string('checked_in_by_id')->nullable(); + $table->string('checked_in_from_type'); + $table->string('checked_in_from_id'); + $table->timestamp('checked_in_at'); + $table->longText('notes')->nullable(); $table->timestamps(); $table->softDeletes(); }); diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php new file mode 100644 index 0000000000..a37094dcd4 --- /dev/null +++ b/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php @@ -0,0 +1,25 @@ +uuid('id')->primary(); + $table->foreignUuid('asset_id')->constrained('assets'); + $table->foreignUuid('asset_check_in_id')->nullable()->constrained('asset_check_ins'); + $table->string('checked_out_by_type')->nullable(); + $table->string('checked_out_by_id')->nullable(); + $table->string('checked_out_to_type'); + $table->string('checked_out_to_id'); + $table->timestamp('checked_out_at'); + $table->timestamp('expected_check_in_at')->nullable(); + $table->longText('notes')->nullable(); + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/inventory-management/database/seeders/AssetSeeder.php b/app-modules/inventory-management/database/seeders/AssetSeeder.php index d5638da918..4baa6c6f61 100644 --- a/app-modules/inventory-management/database/seeders/AssetSeeder.php +++ b/app-modules/inventory-management/database/seeders/AssetSeeder.php @@ -38,6 +38,8 @@ use Illuminate\Database\Seeder; use AdvisingApp\InventoryManagement\Models\Asset; +use AdvisingApp\InventoryManagement\Models\AssetCheckIn; +use AdvisingApp\InventoryManagement\Models\AssetCheckOut; use AdvisingApp\InventoryManagement\Models\MaintenanceActivity; class AssetSeeder extends Seeder @@ -48,13 +50,18 @@ public function run(): void ->count(10) ->create() ->each(function (Asset $asset) { - $maintenanceActivitiesCount = rand(0, 10); + $entityCount = rand(0, 10); - for ($i = 0; $i < $maintenanceActivitiesCount; $i++) { + for ($i = 0; $i < $entityCount; $i++) { MaintenanceActivity::factory() ->randomizeState() ->for($asset, 'asset') ->create(); + + AssetCheckOut::factory() + ->has(AssetCheckIn::factory(), 'checkIn') + ->for($asset, 'asset') + ->create(); } }); } diff --git a/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php b/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php index 5ae922356b..16ddff9f5e 100644 --- a/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php +++ b/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php @@ -38,6 +38,7 @@ use Illuminate\Database\Seeder; use AdvisingApp\InventoryManagement\Models\AssetStatus; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; class AssetStatusSeeder extends Seeder { @@ -46,16 +47,17 @@ public function run(): void AssetStatus::factory() ->createMany( [ + [ + 'name' => 'Available', + 'classification' => SystemAssetStatusClassification::Available, + ], ['name' => 'In Use'], - ['name' => 'Available'], ['name' => 'Under Maintenance'], ['name' => 'Out of Service'], ['name' => 'Reserved'], - ['name' => 'On Loan'], ['name' => 'Awaiting Repair'], ['name' => 'Lost'], ['name' => 'Damaged'], - ['name' => 'New'], ] ); } diff --git a/app-modules/inventory-management/src/Enums/AssetExchangeType.php b/app-modules/inventory-management/src/Enums/AssetExchangeType.php deleted file mode 100644 index 9af8a53029..0000000000 --- a/app-modules/inventory-management/src/Enums/AssetExchangeType.php +++ /dev/null @@ -1,50 +0,0 @@ - - - Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. - - Advising App™ is licensed under the Elastic License 2.0. For more details, - see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. - - Notice: - - - You may not provide the software to third parties as a hosted or managed - service, where the service provides users with access to any substantial set of - the features or functionality of the software. - - You may not move, change, disable, or circumvent the license key functionality - in the software, and you may not remove or obscure any functionality in the - software that is protected by the license key. - - You may not alter, remove, or obscure any licensing, copyright, or other notices - of the licensor in the software. Any use of the licensor’s trademarks is subject - to applicable law. - - Canyon GBS LLC respects the intellectual property rights of others and expects the - same in return. Canyon GBS™ and Advising App™ are registered trademarks of - Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks - vigorously. - - The software solution, including services, infrastructure, and code, is offered as a - Software as a Service (SaaS) by Canyon GBS LLC. - - Use of this software implies agreement to the license terms and conditions as stated - in the Elastic License 2.0. - - For more information or inquiries please visit our website at - https://www.canyongbs.com or contact us via email at legal@canyongbs.com. - - -*/ - -namespace AdvisingApp\InventoryManagement\Enums; - -use Filament\Support\Contracts\HasLabel; - -enum AssetExchangeType: string implements HasLabel -{ - case CheckIn = 'check_in'; - case CheckOut = 'check_out'; - - public function getLabel(): ?string - { - return $this->name; - } -} diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index 02c7dd281f..ec2629e1b3 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -36,13 +36,13 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; -use AdvisingApp\InventoryManagement\Enums\AssetExchangeType; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; /** * @mixin IdeHelperAsset @@ -82,18 +82,18 @@ public function maintenanceActivities(): HasMany return $this->hasMany(MaintenanceActivity::class, 'asset_id'); } - public function exchanges(): HasMany + public function checkOuts(): HasMany { - return $this->hasMany(AssetExchange::class, 'asset_id'); + return $this->hasMany(AssetCheckOut::class, 'asset_id'); } - public function checkOuts(): HasMany + public function checkIns(): HasMany { - return $this->exchanges()->where('type', AssetExchangeType::CheckOut); + return $this->hasMany(AssetCheckIn::class, 'asset_id'); } - public function checkIns(): HasMany + public function isAvailable(): bool { - return $this->exchanges()->where('type', AssetExchangeType::CheckIn); + return $this->status->classification === SystemAssetStatusClassification::Available; } } diff --git a/app-modules/inventory-management/src/Models/AssetCheckIn.php b/app-modules/inventory-management/src/Models/AssetCheckIn.php new file mode 100644 index 0000000000..edd1f6dca2 --- /dev/null +++ b/app-modules/inventory-management/src/Models/AssetCheckIn.php @@ -0,0 +1,59 @@ + 'datetime', + ]; + + public function asset(): BelongsTo + { + return $this->belongsTo(Asset::class, 'asset_id'); + } + + public function checkedInBy(): MorphTo + { + return $this->morphTo( + name: 'checked_in_by', + type: 'checked_in_by_type', + id: 'checked_in_by_id', + ); + } + + public function checkedInFrom(): MorphTo + { + return $this->morphTo( + name: 'checked_in_from', + type: 'checked_in_from_type', + id: 'checked_in_from_id', + ); + } + + public function checkOut(): HasOne + { + return $this->hasOne(AssetCheckOut::class); + } +} diff --git a/app-modules/inventory-management/src/Models/AssetCheckOut.php b/app-modules/inventory-management/src/Models/AssetCheckOut.php new file mode 100644 index 0000000000..dad253e8c2 --- /dev/null +++ b/app-modules/inventory-management/src/Models/AssetCheckOut.php @@ -0,0 +1,61 @@ + 'datetime', + 'expected_check_in_at' => 'datetime', + ]; + + public function asset(): BelongsTo + { + return $this->belongsTo(Asset::class, 'asset_id'); + } + + public function checkedOutBy(): MorphTo + { + return $this->morphTo( + name: 'checked_out_by', + type: 'checked_out_by_type', + id: 'checked_out_by_id', + ); + } + + public function checkedOutTo(): MorphTo + { + return $this->morphTo( + name: 'checked_out_to', + type: 'checked_out_to_type', + id: 'checked_out_to_id', + ); + } + + public function checkIn(): BelongsTo + { + return $this->belongsTo(AssetCheckIn::class); + } +} diff --git a/app-modules/inventory-management/src/Models/AssetExchange.php b/app-modules/inventory-management/src/Models/AssetExchange.php deleted file mode 100644 index 41107d7e83..0000000000 --- a/app-modules/inventory-management/src/Models/AssetExchange.php +++ /dev/null @@ -1,45 +0,0 @@ - AssetExchangeType::class, - ]; - - public function asset(): BelongsTo - { - return $this->belongsTo(Asset::class, 'asset_id'); - } - - public function scopeCheckIn(Builder $query): void - { - $query->where('type', AssetExchangeType::CheckIn); - } - - public function scopeCheckOut(Builder $query): void - { - $query->where('type', AssetExchangeType::CheckOut); - } -} diff --git a/app-modules/inventory-management/src/Models/AssetStatus.php b/app-modules/inventory-management/src/Models/AssetStatus.php index ad32d6023a..524f5372c9 100644 --- a/app-modules/inventory-management/src/Models/AssetStatus.php +++ b/app-modules/inventory-management/src/Models/AssetStatus.php @@ -36,12 +36,12 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; -use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasMany; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; /** * @mixin IdeHelperAssetStatus diff --git a/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php b/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php index ee84ace5b0..52739c94ec 100644 --- a/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php +++ b/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php @@ -43,6 +43,8 @@ use AdvisingApp\InventoryManagement\Models\AssetType; use AdvisingApp\InventoryManagement\Models\AssetStatus; use AdvisingApp\Authorization\AuthorizationRoleRegistry; +use AdvisingApp\InventoryManagement\Models\AssetCheckIn; +use AdvisingApp\InventoryManagement\Models\AssetCheckOut; use AdvisingApp\InventoryManagement\Models\AssetLocation; use AdvisingApp\Authorization\AuthorizationPermissionRegistry; use AdvisingApp\InventoryManagement\InventoryManagementPlugin; @@ -59,6 +61,8 @@ public function register() public function boot() { Relation::morphMap([ + 'asset_check_in' => AssetCheckIn::class, + 'asset_check_out' => AssetCheckOut::class, 'asset_location' => AssetLocation::class, 'asset_status' => AssetStatus::class, 'asset_type' => AssetType::class, From 3f330427176b4784d76514126d6cdfc83f2ee773 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 07:39:00 -0500 Subject: [PATCH 083/152] Add check out action. --- .../database/seeders/AssetStatusSeeder.php | 5 +- .../Enums/SystemAssetStatusClassification.php | 8 +- .../Actions/CheckOutAssetHeaderAction.php | 95 +++++++++++++++++++ .../AssetResource/Pages/ViewAsset.php | 9 ++ .../inventory-management/src/Models/Asset.php | 16 +++- 5 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php diff --git a/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php b/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php index 16ddff9f5e..e722caff2b 100644 --- a/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php +++ b/app-modules/inventory-management/database/seeders/AssetStatusSeeder.php @@ -51,7 +51,10 @@ public function run(): void 'name' => 'Available', 'classification' => SystemAssetStatusClassification::Available, ], - ['name' => 'In Use'], + [ + 'name' => 'In Use', + 'classification' => SystemAssetStatusClassification::CheckedOut, + ], ['name' => 'Under Maintenance'], ['name' => 'Out of Service'], ['name' => 'Reserved'], diff --git a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php index d1b153e600..7d4447615d 100644 --- a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php +++ b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php @@ -42,12 +42,18 @@ enum SystemAssetStatusClassification: string implements HasLabel { case Available = 'available'; + // TODO Implement a rule that only one asset status can be classified as this + case CheckedOut = 'checked_out'; + case Unavailable = 'unavailable'; case Custom = 'custom'; public function getLabel(): ?string { - return $this->name; + return match ($this) { + self::CheckedOut => 'Checked Out', + default => $this->name + }; } } diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php new file mode 100644 index 0000000000..b65d222e75 --- /dev/null +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -0,0 +1,95 @@ +button(); + + $this->label(__('Check Out')); + + /** @var Asset $asset */ + $asset = $this->getRecord(); + + $this->modalHeading(__("Check out {$asset->name}")); + + $this->modalSubmitActionLabel(__('Done')); + + $this->successNotificationTitle(__("Successfully checked out {$asset->name}")); + + $this->form([ + Radio::make('checked_out_to_type') + ->label('Check out to') + ->options([ + Student::class => 'Student', + Prospect::class => 'Prospect', + ]) + ->default(Student::class) + ->required() + ->live(), + Select::make('checked_out_to_id') + ->label(fn (Get $get): string => match ($get('checked_out_to_type')) { + Student::class => 'Select Student', + Prospect::class => 'Select Prospect', + }) + ->visible(fn (Get $get): bool => filled($get('checked_out_to_type'))) + ->getSearchResultsUsing(function (string $search, Get $get) { + return match ($get('checked_out_to_type')) { + Student::class => Student::where('full_name', 'like', "%{$search}%")->pluck('full_name', 'sisid')->toArray(), + Prospect::class => Prospect::where('full_name', 'like', "%{$search}%")->pluck('full_name', 'id')->toArray(), + }; + }) + ->searchable() + ->required(), + Textarea::make('notes') + ->autofocus() + ->required(), + DateTimePicker::make('expected_check_in_at') + ->label('Expected Return Date'), + ]); + + $this->action(function (array $data): void { + /** @var Asset $asset */ + $asset = $this->getRecord(); + + if (! $asset->isAvailable()) { + $this->failure(); + } + + $asset->checkOuts()->create([ + 'checked_out_by_type' => auth()->user()?->getMorphClass(), + 'checked_out_by_id' => auth()->user()?->id, + 'checked_out_to_type' => (new $data['checked_out_to_type']())->getMorphClass(), + 'checked_out_to_id' => $data['checked_out_to_id'], + 'notes' => $data['notes'], + 'checked_out_at' => now(), + 'expected_check_in_at' => $data['expected_check_in_at'], + ]); + + // TODO We may want to move this to an observer in order to clean up... + $checkedOutStatus = AssetStatus::where('classification', SystemAssetStatusClassification::CheckedOut)->first(); + + $asset->update([ + 'status_id' => $checkedOutStatus->id, + ]); + + $this->success(); + }); + } +} diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php b/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php index aaaa2de57b..deedb2c68d 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php @@ -41,7 +41,9 @@ use Filament\Resources\Pages\ViewRecord; use Filament\Infolists\Components\Section; use Filament\Infolists\Components\TextEntry; +use AdvisingApp\InventoryManagement\Models\Asset; use AdvisingApp\InventoryManagement\Filament\Resources\AssetResource; +use AdvisingApp\InventoryManagement\Filament\Actions\CheckOutAssetHeaderAction; class ViewAsset extends ViewRecord { @@ -71,6 +73,13 @@ protected function getHeaderActions(): array { return [ EditAction::make(), + CheckOutAssetHeaderAction::make('check-out') + ->visible(function () { + /** @var Asset $asset */ + $asset = $this->getRecord(); + + return $asset->isAvailable(); + }), ]; } } diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index ec2629e1b3..a3d240dfd1 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -39,6 +39,7 @@ use App\Models\BaseModel; use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; @@ -87,6 +88,18 @@ public function checkOuts(): HasMany return $this->hasMany(AssetCheckOut::class, 'asset_id'); } + public function latestCheckOut(): HasOne + { + return $this->hasOne(AssetCheckOut::class, 'asset_id') + ->oldest('checked_out_at'); + } + + public function latestCheckIn(): HasOne + { + return $this->hasOne(AssetCheckIn::class, 'asset_id') + ->latest('checked_in_at'); + } + public function checkIns(): HasMany { return $this->hasMany(AssetCheckIn::class, 'asset_id'); @@ -94,6 +107,7 @@ public function checkIns(): HasMany public function isAvailable(): bool { - return $this->status->classification === SystemAssetStatusClassification::Available; + return $this->status->classification === SystemAssetStatusClassification::Available + && is_null($this->latestCheckOut->asset_check_in_id); } } From fa3bff3cfd4d365e5a84b76b3b6c0dae8b94ed26 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:06:33 -0500 Subject: [PATCH 084/152] Add check in action. --- .../Providers/EngagementServiceProvider.php | 4 +- .../Enums/SystemAssetStatusClassification.php | 1 + .../Actions/CheckInAssetHeaderAction.php | 64 +++++++++++++++++++ .../AssetResource/Pages/ViewAsset.php | 8 +++ .../inventory-management/src/Models/Asset.php | 13 +++- .../src/Observers/AssetCheckInObserver.php | 52 +++++++++++++++ .../InventoryManagementServiceProvider.php | 8 +++ 7 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php create mode 100644 app-modules/inventory-management/src/Observers/AssetCheckInObserver.php diff --git a/app-modules/engagement/src/Providers/EngagementServiceProvider.php b/app-modules/engagement/src/Providers/EngagementServiceProvider.php index c37579c893..5f9f784093 100644 --- a/app-modules/engagement/src/Providers/EngagementServiceProvider.php +++ b/app-modules/engagement/src/Providers/EngagementServiceProvider.php @@ -84,9 +84,9 @@ public function boot(): void ->withoutOverlapping(); }); - $this->registerRolesAndPermissions(); - $this->registerObservers(); + + $this->registerRolesAndPermissions(); } public function registerObservers(): void diff --git a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php index 7d4447615d..ba9704cb95 100644 --- a/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php +++ b/app-modules/inventory-management/src/Enums/SystemAssetStatusClassification.php @@ -40,6 +40,7 @@ enum SystemAssetStatusClassification: string implements HasLabel { + // TODO Implement a rule that only one asset status can be classified as this case Available = 'available'; // TODO Implement a rule that only one asset status can be classified as this diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php new file mode 100644 index 0000000000..e14ef6b132 --- /dev/null +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -0,0 +1,64 @@ +button(); + + $this->label(__('Check In')); + + /** @var Asset $asset */ + $asset = $this->getRecord(); + + $this->modalHeading(__("Check in {$asset->name}")); + + $this->modalSubmitActionLabel(__('Done')); + + $this->successNotificationTitle(__("Successfully checked in {$asset->name}")); + + $this->form([ + Textarea::make('notes') + ->autofocus() + ->required(), + ]); + + $this->action(function (array $data): void { + /** @var Asset $asset */ + $asset = $this->getRecord(); + + if (! $asset->isAvailable()) { + $this->failure(); + } + + $asset->checkIns()->create([ + 'checked_in_by_type' => auth()->user()?->getMorphClass(), + 'checked_in_by_id' => auth()->user()?->id, + // TODO Should we still have this be configurable? Or should the expectation be that this information is the same as the latest check out? + 'checked_in_from_type' => $asset->latestCheckOut->checked_out_to_type, + 'checked_in_from_id' => $asset->latestCheckOut->checked_out_to_id, + 'notes' => $data['notes'], + 'checked_in_at' => now(), + ]); + + // TODO We may want to move this to an observer in order to clean up... + $checkedInStatus = AssetStatus::where('classification', SystemAssetStatusClassification::Available)->first(); + + $asset->update([ + 'status_id' => $checkedInStatus->id, + ]); + + $this->success(); + }); + } +} diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php b/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php index deedb2c68d..db278be7fb 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetResource/Pages/ViewAsset.php @@ -43,6 +43,7 @@ use Filament\Infolists\Components\TextEntry; use AdvisingApp\InventoryManagement\Models\Asset; use AdvisingApp\InventoryManagement\Filament\Resources\AssetResource; +use AdvisingApp\InventoryManagement\Filament\Actions\CheckInAssetHeaderAction; use AdvisingApp\InventoryManagement\Filament\Actions\CheckOutAssetHeaderAction; class ViewAsset extends ViewRecord @@ -80,6 +81,13 @@ protected function getHeaderActions(): array return $asset->isAvailable(); }), + CheckInAssetHeaderAction::make('check-in') + ->visible(function () { + /** @var Asset $asset */ + $asset = $this->getRecord(); + + return $asset->isCheckedOut(); + }), ]; } } diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index a3d240dfd1..80e673b408 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -108,6 +108,17 @@ public function checkIns(): HasMany public function isAvailable(): bool { return $this->status->classification === SystemAssetStatusClassification::Available - && is_null($this->latestCheckOut->asset_check_in_id); + && ! is_null($this->latestCheckOut?->asset_check_in_id); + } + + public function isNotAvailable(): bool + { + return ! $this->isAvailable(); + } + + public function isCheckedOut(): bool + { + return $this->status->classification === SystemAssetStatusClassification::CheckedOut + && is_null($this->latestCheckOut?->asset_check_in_id); } } diff --git a/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php b/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php new file mode 100644 index 0000000000..54d9e4fa18 --- /dev/null +++ b/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php @@ -0,0 +1,52 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Observers; + +use AdvisingApp\InventoryManagement\Models\AssetCheckIn; + +class AssetCheckInObserver +{ + public function created(AssetCheckIn $checkIn): void + { + ray('AssetCheckInObserver::created()'); + ray($checkIn->asset->latestCheckOut); + + $checkIn->asset->latestCheckOut->update([ + 'asset_check_in_id' => $checkIn->id, + ]); + } +} diff --git a/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php b/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php index 52739c94ec..bed4974244 100644 --- a/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php +++ b/app-modules/inventory-management/src/Providers/InventoryManagementServiceProvider.php @@ -50,6 +50,7 @@ use AdvisingApp\InventoryManagement\InventoryManagementPlugin; use AdvisingApp\InventoryManagement\Models\MaintenanceActivity; use AdvisingApp\InventoryManagement\Models\MaintenanceProvider; +use AdvisingApp\InventoryManagement\Observers\AssetCheckInObserver; class InventoryManagementServiceProvider extends ServiceProvider { @@ -71,9 +72,16 @@ public function boot() 'maintenance_provider' => MaintenanceProvider::class, ]); + $this->registerObservers(); + $this->registerRolesAndPermissions(); } + public function registerObservers(): void + { + AssetCheckIn::observe(AssetCheckInObserver::class); + } + protected function registerRolesAndPermissions() { $permissionRegistry = app(AuthorizationPermissionRegistry::class); From 8175cf1185ae27bc6dc4dc4a06b6afc06899e54a Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:15:54 -0500 Subject: [PATCH 085/152] Make status configurable on check in. --- .../Actions/CheckInAssetHeaderAction.php | 18 +++++++++++++----- .../Actions/CheckOutAssetHeaderAction.php | 3 +-- .../src/Models/AssetStatus.php | 10 ++++++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php index e14ef6b132..4b7161533f 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -3,10 +3,11 @@ namespace AdvisingApp\InventoryManagement\Filament\Actions; use Filament\Actions\Action; +use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\DateTimePicker; use AdvisingApp\InventoryManagement\Models\Asset; use AdvisingApp\InventoryManagement\Models\AssetStatus; -use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; class CheckInAssetHeaderAction extends Action { @@ -31,6 +32,16 @@ protected function setUp(): void Textarea::make('notes') ->autofocus() ->required(), + Select::make('status_id') + ->relationship('status', 'name') + ->preload() + ->label('Status') + ->default(AssetStatus::available()->first()->id) + ->required() + ->exists((new AssetStatus())->getTable(), 'id'), + DateTimePicker::make('checked_in_at') + ->label('Checked in at') + ->default(now()), ]); $this->action(function (array $data): void { @@ -51,11 +62,8 @@ protected function setUp(): void 'checked_in_at' => now(), ]); - // TODO We may want to move this to an observer in order to clean up... - $checkedInStatus = AssetStatus::where('classification', SystemAssetStatusClassification::Available)->first(); - $asset->update([ - 'status_id' => $checkedInStatus->id, + 'status_id' => $data['status_id'], ]); $this->success(); diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php index b65d222e75..9bb252cdd5 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -12,7 +12,6 @@ use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\InventoryManagement\Models\Asset; use AdvisingApp\InventoryManagement\Models\AssetStatus; -use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; class CheckOutAssetHeaderAction extends Action { @@ -83,7 +82,7 @@ protected function setUp(): void ]); // TODO We may want to move this to an observer in order to clean up... - $checkedOutStatus = AssetStatus::where('classification', SystemAssetStatusClassification::CheckedOut)->first(); + $checkedOutStatus = AssetStatus::checkedOut()->first(); $asset->update([ 'status_id' => $checkedOutStatus->id, diff --git a/app-modules/inventory-management/src/Models/AssetStatus.php b/app-modules/inventory-management/src/Models/AssetStatus.php index 524f5372c9..85e04ca8ce 100644 --- a/app-modules/inventory-management/src/Models/AssetStatus.php +++ b/app-modules/inventory-management/src/Models/AssetStatus.php @@ -64,4 +64,14 @@ public function assets(): HasMany { return $this->hasMany(Asset::class, 'status_id'); } + + public function scopeAvailable(): void + { + $this->where('classification', SystemAssetStatusClassification::Available); + } + + public function scopeCheckedOut(): void + { + $this->where('classification', SystemAssetStatusClassification::CheckedOut); + } } From 0b7db9ee758ad7690f621829ffe0ed2cf325dfdf Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:24:17 -0500 Subject: [PATCH 086/152] Clean up action validation. --- .../inventory-management/database/seeders/AssetSeeder.php | 7 ------- .../src/Filament/Actions/CheckInAssetHeaderAction.php | 5 ++--- .../src/Filament/Actions/CheckOutAssetHeaderAction.php | 3 +-- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/app-modules/inventory-management/database/seeders/AssetSeeder.php b/app-modules/inventory-management/database/seeders/AssetSeeder.php index 4baa6c6f61..9dc2eab33c 100644 --- a/app-modules/inventory-management/database/seeders/AssetSeeder.php +++ b/app-modules/inventory-management/database/seeders/AssetSeeder.php @@ -38,8 +38,6 @@ use Illuminate\Database\Seeder; use AdvisingApp\InventoryManagement\Models\Asset; -use AdvisingApp\InventoryManagement\Models\AssetCheckIn; -use AdvisingApp\InventoryManagement\Models\AssetCheckOut; use AdvisingApp\InventoryManagement\Models\MaintenanceActivity; class AssetSeeder extends Seeder @@ -57,11 +55,6 @@ public function run(): void ->randomizeState() ->for($asset, 'asset') ->create(); - - AssetCheckOut::factory() - ->has(AssetCheckIn::factory(), 'checkIn') - ->for($asset, 'asset') - ->create(); } }); } diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php index 4b7161533f..2c2b3da131 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -30,8 +30,7 @@ protected function setUp(): void $this->form([ Textarea::make('notes') - ->autofocus() - ->required(), + ->autofocus(), Select::make('status_id') ->relationship('status', 'name') ->preload() @@ -59,7 +58,7 @@ protected function setUp(): void 'checked_in_from_type' => $asset->latestCheckOut->checked_out_to_type, 'checked_in_from_id' => $asset->latestCheckOut->checked_out_to_id, 'notes' => $data['notes'], - 'checked_in_at' => now(), + 'checked_in_at' => $data['checked_in_at'] ?? now(), ]); $asset->update([ diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php index 9bb252cdd5..59d59532a7 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -57,8 +57,7 @@ protected function setUp(): void ->searchable() ->required(), Textarea::make('notes') - ->autofocus() - ->required(), + ->autofocus(), DateTimePicker::make('expected_check_in_at') ->label('Expected Return Date'), ]); From 1f07cfb3be72de94b99384a878006cf8b4c2ceba Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:29:11 -0500 Subject: [PATCH 087/152] Update policies, roles. --- .../config/roles/api/inventory_management.php | 6 ++ .../config/roles/web/inventory_management.php | 6 ++ ...hangePolicy.php => AssetCheckInPolicy.php} | 42 ++++---- .../src/Policies/AssetCheckOutPolicy.php | 100 ++++++++++++++++++ 4 files changed, 133 insertions(+), 21 deletions(-) rename app-modules/inventory-management/src/Policies/{AssetExchangePolicy.php => AssetCheckInPolicy.php} (75%) create mode 100644 app-modules/inventory-management/src/Policies/AssetCheckOutPolicy.php diff --git a/app-modules/inventory-management/config/roles/api/inventory_management.php b/app-modules/inventory-management/config/roles/api/inventory_management.php index 268edc7499..d7c70b0afb 100644 --- a/app-modules/inventory-management/config/roles/api/inventory_management.php +++ b/app-modules/inventory-management/config/roles/api/inventory_management.php @@ -48,6 +48,12 @@ 'asset_type' => [ '*', ], + 'asset_check_in' => [ + '*', + ], + 'asset_check_out' => [ + '*', + ], 'maintenance_activity' => [ '*', ], diff --git a/app-modules/inventory-management/config/roles/web/inventory_management.php b/app-modules/inventory-management/config/roles/web/inventory_management.php index 268edc7499..d7c70b0afb 100644 --- a/app-modules/inventory-management/config/roles/web/inventory_management.php +++ b/app-modules/inventory-management/config/roles/web/inventory_management.php @@ -48,6 +48,12 @@ 'asset_type' => [ '*', ], + 'asset_check_in' => [ + '*', + ], + 'asset_check_out' => [ + '*', + ], 'maintenance_activity' => [ '*', ], diff --git a/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php b/app-modules/inventory-management/src/Policies/AssetCheckInPolicy.php similarity index 75% rename from app-modules/inventory-management/src/Policies/AssetExchangePolicy.php rename to app-modules/inventory-management/src/Policies/AssetCheckInPolicy.php index 031744e4f1..9e57d18e83 100644 --- a/app-modules/inventory-management/src/Policies/AssetExchangePolicy.php +++ b/app-modules/inventory-management/src/Policies/AssetCheckInPolicy.php @@ -38,63 +38,63 @@ use App\Models\Authenticatable; use Illuminate\Auth\Access\Response; -use AdvisingApp\InventoryManagement\Models\AssetExchange; +use AdvisingApp\InventoryManagement\Models\AssetCheckIn; -class AssetExchangePolicy +class AssetCheckInPolicy { public function viewAny(Authenticatable $authenticatable): Response { return $authenticatable->canOrElse( - abilities: 'asset_exchange.view-any', - denyResponse: 'You do not have permission to view asset exchanges.' + abilities: 'asset_check_in.view-any', + denyResponse: 'You do not have permission to view asset check ins.' ); } - public function view(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function view(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.view', "asset_exchange.{$assetExchange->id}.view"], - denyResponse: 'You do not have permission to view this asset exchange.' + abilities: ['asset_check_in.*.view', "asset_check_in.{$assetCheckIn->id}.view"], + denyResponse: 'You do not have permission to view this asset check in.' ); } public function create(Authenticatable $authenticatable): Response { return $authenticatable->canOrElse( - abilities: 'asset_exchange.create', - denyResponse: 'You do not have permission to create asset exchanges.' + abilities: 'asset_check_in.create', + denyResponse: 'You do not have permission to create asset check ins.' ); } - public function update(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function update(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.update', "asset_exchange.{$assetExchange->id}.update"], - denyResponse: 'You do not have permission to update this asset exchange.' + abilities: ['asset_check_in.*.update', "asset_check_in.{$assetCheckIn->id}.update"], + denyResponse: 'You do not have permission to update this asset check in.' ); } - public function delete(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function delete(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.delete', "asset_exchange.{$assetExchange->id}.delete"], - denyResponse: 'You do not have permission to delete this asset exchange.' + abilities: ['asset_check_in.*.delete', "asset_check_in.{$assetCheckIn->id}.delete"], + denyResponse: 'You do not have permission to delete this asset check in.' ); } - public function restore(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function restore(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.restore', "asset_exchange.{$assetExchange->id}.restore"], - denyResponse: 'You do not have permission to restore this asset exchange.' + abilities: ['asset_check_in.*.restore', "asset_check_in.{$assetCheckIn->id}.restore"], + denyResponse: 'You do not have permission to restore this asset check in.' ); } - public function forceDelete(Authenticatable $authenticatable, AssetExchange $assetExchange): Response + public function forceDelete(Authenticatable $authenticatable, AssetCheckIn $assetCheckIn): Response { return $authenticatable->canOrElse( - abilities: ['asset_exchange.*.force-delete', "asset_exchange.{$assetExchange->id}.force-delete"], - denyResponse: 'You do not have permission to permanently delete this asset exchange.' + abilities: ['asset_check_in.*.force-delete', "asset_check_in.{$assetCheckIn->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset check in.' ); } } diff --git a/app-modules/inventory-management/src/Policies/AssetCheckOutPolicy.php b/app-modules/inventory-management/src/Policies/AssetCheckOutPolicy.php new file mode 100644 index 0000000000..cd227de8ca --- /dev/null +++ b/app-modules/inventory-management/src/Policies/AssetCheckOutPolicy.php @@ -0,0 +1,100 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\InventoryManagement\Policies; + +use App\Models\Authenticatable; +use Illuminate\Auth\Access\Response; +use AdvisingApp\InventoryManagement\Models\AssetCheckOut; + +class AssetCheckOutPolicy +{ + public function viewAny(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_check_out.view-any', + denyResponse: 'You do not have permission to view asset check outs.' + ); + } + + public function view(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.view', "asset_check_out.{$assetCheckOut->id}.view"], + denyResponse: 'You do not have permission to view this asset check out.' + ); + } + + public function create(Authenticatable $authenticatable): Response + { + return $authenticatable->canOrElse( + abilities: 'asset_check_out.create', + denyResponse: 'You do not have permission to create asset check outs.' + ); + } + + public function update(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.update', "asset_check_out.{$assetCheckOut->id}.update"], + denyResponse: 'You do not have permission to update this asset check out.' + ); + } + + public function delete(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.delete', "asset_check_out.{$assetCheckOut->id}.delete"], + denyResponse: 'You do not have permission to delete this asset check out.' + ); + } + + public function restore(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.restore', "asset_check_out.{$assetCheckOut->id}.restore"], + denyResponse: 'You do not have permission to restore this asset check out.' + ); + } + + public function forceDelete(Authenticatable $authenticatable, AssetCheckOut $assetCheckOut): Response + { + return $authenticatable->canOrElse( + abilities: ['asset_check_out.*.force-delete', "asset_check_out.{$assetCheckOut->id}.force-delete"], + denyResponse: 'You do not have permission to permanently delete this asset check out.' + ); + } +} From 54e7d5167733ea5174203721e59f4c19f01bcbee Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:46:22 -0500 Subject: [PATCH 088/152] Add classification controls to asset status resource. --- .../database/factories/AssetCheckInFactory.php | 6 +++--- .../database/factories/AssetCheckOutFactory.php | 1 - .../AssetStatusResource/Pages/CreateAssetStatus.php | 6 ++++++ .../AssetStatusResource/Pages/ListAssetStatuses.php | 3 +++ .../Resources/AssetStatusResource/Pages/ViewAssetStatus.php | 1 + 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php index 793d21673d..ec6cf59f3e 100644 --- a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php +++ b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php @@ -16,12 +16,12 @@ class AssetCheckInFactory extends Factory { public function definition(): array { - $checkedOutBy = User::factory()->create(); + $checkedInBy = User::factory()->create(); return [ 'asset_id' => Asset::factory(), - 'checked_in_by_type' => $checkedOutBy->getMorphClass(), - 'checked_in_by_id' => $checkedOutBy->getKey(), + 'checked_in_by_type' => $checkedInBy->getMorphClass(), + 'checked_in_by_id' => $checkedInBy->getKey(), 'checked_in_from_type' => fake()->randomElement([ (new Student())->getMorphClass(), (new Prospect())->getMorphClass(), diff --git a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php index f4e1d061c3..f1509098b2 100644 --- a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php +++ b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php @@ -21,7 +21,6 @@ public function definition(): array return [ 'asset_id' => Asset::factory(), - // TODO Add variance to this column so that some check outs do not have corresponding check ins 'asset_check_in_id' => null, 'checked_out_by_type' => $checkedOutBy->getMorphClass(), 'checked_out_by_id' => $checkedOutBy->getKey(), diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/CreateAssetStatus.php b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/CreateAssetStatus.php index 8e2facb1c2..62e4601954 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/CreateAssetStatus.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/CreateAssetStatus.php @@ -37,8 +37,10 @@ namespace AdvisingApp\InventoryManagement\Filament\Resources\AssetStatusResource\Pages; use Filament\Forms\Form; +use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\CreateRecord; +use AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification; use AdvisingApp\InventoryManagement\Filament\Resources\AssetStatusResource; class CreateAssetStatus extends CreateRecord @@ -51,6 +53,10 @@ public function form(Form $form): Form ->schema([ TextInput::make('name') ->required(), + Select::make('classification') + ->options(SystemAssetStatusClassification::class) + ->enum(SystemAssetStatusClassification::class) + ->required(), ]); } } diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ListAssetStatuses.php b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ListAssetStatuses.php index a67d22af3f..123fa8d625 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ListAssetStatuses.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ListAssetStatuses.php @@ -57,6 +57,9 @@ public function table(Table $table): Table TextColumn::make('name') ->searchable() ->sortable(), + TextColumn::make('classification') + ->searchable() + ->sortable(), ]) ->filters([ ]) diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ViewAssetStatus.php b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ViewAssetStatus.php index ed06f374c8..7eb133e489 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ViewAssetStatus.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource/Pages/ViewAssetStatus.php @@ -54,6 +54,7 @@ public function infolist(Infolist $infolist): Infolist Section::make() ->schema([ TextEntry::make('name'), + TextEntry::make('classification'), ]), ]); } From 627f2d51c6140d3aa723f7da48bbf9f8da49f331 Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 08:59:10 -0500 Subject: [PATCH 089/152] Clean up. --- .../src/Filament/Actions/CheckInAssetHeaderAction.php | 5 +++-- .../src/Filament/Actions/CheckOutAssetHeaderAction.php | 5 +---- app-modules/inventory-management/src/Models/Asset.php | 10 +++++----- .../src/Observers/AssetCheckInObserver.php | 3 --- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php index 2c2b3da131..773cc1a23f 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -47,14 +47,15 @@ protected function setUp(): void /** @var Asset $asset */ $asset = $this->getRecord(); - if (! $asset->isAvailable()) { + if (! $asset->isCheckedOut()) { $this->failure(); } $asset->checkIns()->create([ 'checked_in_by_type' => auth()->user()?->getMorphClass(), 'checked_in_by_id' => auth()->user()?->id, - // TODO Should we still have this be configurable? Or should the expectation be that this information is the same as the latest check out? + // TODO Should this always simply be the latest check out, or do we want to support + // The possibility that the person checking in is different than whoever checked out? 'checked_in_from_type' => $asset->latestCheckOut->checked_out_to_type, 'checked_in_from_id' => $asset->latestCheckOut->checked_out_to_id, 'notes' => $data['notes'], diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php index 59d59532a7..fe64c51ed2 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -80,11 +80,8 @@ protected function setUp(): void 'expected_check_in_at' => $data['expected_check_in_at'], ]); - // TODO We may want to move this to an observer in order to clean up... - $checkedOutStatus = AssetStatus::checkedOut()->first(); - $asset->update([ - 'status_id' => $checkedOutStatus->id, + 'status_id' => AssetStatus::checkedOut()->first()->id, ]); $this->success(); diff --git a/app-modules/inventory-management/src/Models/Asset.php b/app-modules/inventory-management/src/Models/Asset.php index 80e673b408..d2723972ea 100644 --- a/app-modules/inventory-management/src/Models/Asset.php +++ b/app-modules/inventory-management/src/Models/Asset.php @@ -88,6 +88,11 @@ public function checkOuts(): HasMany return $this->hasMany(AssetCheckOut::class, 'asset_id'); } + public function checkIns(): HasMany + { + return $this->hasMany(AssetCheckIn::class, 'asset_id'); + } + public function latestCheckOut(): HasOne { return $this->hasOne(AssetCheckOut::class, 'asset_id') @@ -100,11 +105,6 @@ public function latestCheckIn(): HasOne ->latest('checked_in_at'); } - public function checkIns(): HasMany - { - return $this->hasMany(AssetCheckIn::class, 'asset_id'); - } - public function isAvailable(): bool { return $this->status->classification === SystemAssetStatusClassification::Available diff --git a/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php b/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php index 54d9e4fa18..6909116d0b 100644 --- a/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php +++ b/app-modules/inventory-management/src/Observers/AssetCheckInObserver.php @@ -42,9 +42,6 @@ class AssetCheckInObserver { public function created(AssetCheckIn $checkIn): void { - ray('AssetCheckInObserver::created()'); - ray($checkIn->asset->latestCheckOut); - $checkIn->asset->latestCheckOut->update([ 'asset_check_in_id' => $checkIn->id, ]); From 8772bb412eaaf0f88885464cf8d88103602d4570 Mon Sep 17 00:00:00 2001 From: dgoetzit Date: Wed, 3 Jan 2024 14:02:35 +0000 Subject: [PATCH 090/152] chore: fix enforcement of copyright on all files --- .../factories/AssetCheckInFactory.php | 34 +++++++++++++++++++ .../factories/AssetCheckOutFactory.php | 34 +++++++++++++++++++ ...28_174428_create_asset_check_ins_table.php | 34 +++++++++++++++++++ ...8_174437_create_asset_check_outs_table.php | 34 +++++++++++++++++++ .../Actions/CheckInAssetHeaderAction.php | 34 +++++++++++++++++++ .../Actions/CheckOutAssetHeaderAction.php | 34 +++++++++++++++++++ .../src/Models/AssetCheckIn.php | 34 +++++++++++++++++++ .../src/Models/AssetCheckOut.php | 34 +++++++++++++++++++ 8 files changed, 272 insertions(+) diff --git a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php index ec6cf59f3e..aec0066bd4 100644 --- a/app-modules/inventory-management/database/factories/AssetCheckInFactory.php +++ b/app-modules/inventory-management/database/factories/AssetCheckInFactory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Database\Factories; use App\Models\User; diff --git a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php index f1509098b2..908cc3623d 100644 --- a/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php +++ b/app-modules/inventory-management/database/factories/AssetCheckOutFactory.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Database\Factories; use Carbon\Carbon; diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php index 08c435f4bb..f837c2993a 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_28_174428_create_asset_check_ins_table.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; diff --git a/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php b/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php index a37094dcd4..4dd77f8ed2 100644 --- a/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php +++ b/app-modules/inventory-management/database/migrations/2023_12_28_174437_create_asset_check_outs_table.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php index 773cc1a23f..9419287ff7 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckInAssetHeaderAction.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Filament\Actions; use Filament\Actions\Action; diff --git a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php index fe64c51ed2..f417c58289 100644 --- a/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php +++ b/app-modules/inventory-management/src/Filament/Actions/CheckOutAssetHeaderAction.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Filament\Actions; use Filament\Forms\Get; diff --git a/app-modules/inventory-management/src/Models/AssetCheckIn.php b/app-modules/inventory-management/src/Models/AssetCheckIn.php index edd1f6dca2..cef99b06aa 100644 --- a/app-modules/inventory-management/src/Models/AssetCheckIn.php +++ b/app-modules/inventory-management/src/Models/AssetCheckIn.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Models; use App\Models\BaseModel; diff --git a/app-modules/inventory-management/src/Models/AssetCheckOut.php b/app-modules/inventory-management/src/Models/AssetCheckOut.php index dad253e8c2..121c9de71b 100644 --- a/app-modules/inventory-management/src/Models/AssetCheckOut.php +++ b/app-modules/inventory-management/src/Models/AssetCheckOut.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\InventoryManagement\Models; use App\Models\BaseModel; From fb54dbe7f508ca92cb933f4e5f6284c9be950403 Mon Sep 17 00:00:00 2001 From: joelicatajr Date: Wed, 3 Jan 2024 14:06:00 +0000 Subject: [PATCH 091/152] chore: fix code style --- .../inventory-management/src/Models/AssetLocation.php | 6 +++--- app-modules/inventory-management/src/Models/AssetType.php | 6 +++--- .../src/Models/MaintenanceActivity.php | 8 ++++---- .../src/Models/ServiceRequestStatus.php | 1 - 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app-modules/inventory-management/src/Models/AssetLocation.php b/app-modules/inventory-management/src/Models/AssetLocation.php index 35e1f96256..871c929e26 100644 --- a/app-modules/inventory-management/src/Models/AssetLocation.php +++ b/app-modules/inventory-management/src/Models/AssetLocation.php @@ -36,11 +36,11 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasMany; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; /** * @mixin IdeHelperAssetLocation diff --git a/app-modules/inventory-management/src/Models/AssetType.php b/app-modules/inventory-management/src/Models/AssetType.php index 1a492ebdfb..692f0dabdc 100644 --- a/app-modules/inventory-management/src/Models/AssetType.php +++ b/app-modules/inventory-management/src/Models/AssetType.php @@ -36,11 +36,11 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\HasMany; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; /** * @mixin IdeHelperAssetType diff --git a/app-modules/inventory-management/src/Models/MaintenanceActivity.php b/app-modules/inventory-management/src/Models/MaintenanceActivity.php index 6bc1748b66..1e5ec8ce5c 100644 --- a/app-modules/inventory-management/src/Models/MaintenanceActivity.php +++ b/app-modules/inventory-management/src/Models/MaintenanceActivity.php @@ -36,12 +36,12 @@ namespace AdvisingApp\InventoryManagement\Models; -use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; -use AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus; use App\Models\BaseModel; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\SoftDeletes; use OwenIt\Auditing\Contracts\Auditable; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\InventoryManagement\Enums\MaintenanceActivityStatus; /** * @mixin IdeHelperMaintenanceActivity diff --git a/app-modules/service-management/src/Models/ServiceRequestStatus.php b/app-modules/service-management/src/Models/ServiceRequestStatus.php index 40bd3148b5..5250ece7c4 100644 --- a/app-modules/service-management/src/Models/ServiceRequestStatus.php +++ b/app-modules/service-management/src/Models/ServiceRequestStatus.php @@ -40,7 +40,6 @@ use App\Models\BaseModel; use OwenIt\Auditing\Contracts\Auditable; use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Relations\HasMany; use AdvisingApp\ServiceManagement\Enums\ColumnColorOptions; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; From 60230e4b538edcac12085a36033419e4ae8e110f Mon Sep 17 00:00:00 2001 From: Derek Goetz Date: Wed, 3 Jan 2024 10:14:25 -0500 Subject: [PATCH 092/152] Remove open search fields and indexing from prospects. --- .../ProspectResource/Pages/ListProspects.php | 14 +++----- app-modules/prospect/src/Models/Prospect.php | 35 ------------------- 2 files changed, 5 insertions(+), 44 deletions(-) diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ListProspects.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ListProspects.php index cc455741c8..a5cc897835 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ListProspects.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ListProspects.php @@ -56,7 +56,6 @@ use Filament\Resources\Pages\ListRecords; use Filament\Tables\Filters\SelectFilter; use Illuminate\Database\Eloquent\Builder; -use App\Concerns\FilterTableWithOpenSearch; use Filament\Tables\Actions\BulkActionGroup; use Illuminate\Database\Eloquent\Collection; use Filament\Tables\Actions\DeleteBulkAction; @@ -71,14 +70,11 @@ use AdvisingApp\CareTeam\Filament\Actions\ToggleCareTeamBulkAction; use AdvisingApp\Notification\Filament\Actions\SubscribeTableAction; use AdvisingApp\CaseloadManagement\Actions\TranslateCaseloadFilters; -use App\Filament\Columns\OpenSearch\TextColumn as OpenSearchTextColumn; -use App\Filament\Filters\OpenSearch\SelectFilter as OpenSearchSelectFilter; use AdvisingApp\Engagement\Filament\Actions\Contracts\HasBulkEngagementAction; use AdvisingApp\Engagement\Filament\Actions\Concerns\ImplementsHasBulkEngagementAction; class ListProspects extends ListRecords implements HasBulkEngagementAction { - use FilterTableWithOpenSearch; use ImplementsHasBulkEngagementAction; protected static string $resource = ProspectResource::class; @@ -88,16 +84,16 @@ public function table(Table $table): Table return $table ->columns([ IdColumn::make(), - OpenSearchTextColumn::make(Prospect::displayNameKey()) + TextColumn::make(Prospect::displayNameKey()) ->label('Name') ->searchable() ->sortable(), - OpenSearchTextColumn::make('email') + TextColumn::make('email') ->label('Email') ->translateLabel() ->searchable() ->sortable(), - OpenSearchTextColumn::make('mobile') + TextColumn::make('mobile') ->label('Mobile') ->translateLabel() ->searchable() @@ -147,11 +143,11 @@ public function table(Table $table): Table ->searchable() ->optionsLimit(20) ->query(fn (Builder $query, array $data) => $this->caseloadFilter($query, $data)), - OpenSearchSelectFilter::make('status_id') + SelectFilter::make('status_id') ->relationship('status', 'name') ->multiple() ->preload(), - OpenSearchSelectFilter::make('source_id') + SelectFilter::make('source_id') ->relationship('source', 'name') ->multiple() ->preload(), diff --git a/app-modules/prospect/src/Models/Prospect.php b/app-modules/prospect/src/Models/Prospect.php index 00baff3249..d0aa1a0f80 100644 --- a/app-modules/prospect/src/Models/Prospect.php +++ b/app-modules/prospect/src/Models/Prospect.php @@ -45,7 +45,6 @@ use Illuminate\Notifications\Notifiable; use OwenIt\Auditing\Contracts\Auditable; use AdvisingApp\CareTeam\Models\CareTeam; -use OpenSearch\ScoutDriverPlus\Searchable; use AdvisingApp\Form\Models\FormSubmission; use Illuminate\Database\Eloquent\SoftDeletes; use AdvisingApp\Engagement\Models\EngagementFile; @@ -84,7 +83,6 @@ class Prospect extends BaseModel implements Auditable, Subscribable, Educatable, use HasManyMorphedEngagementResponses; use HasManyMorphedInteractions; use HasSubscriptions; - use Searchable; use NotifiableViaSms; protected $fillable = [ @@ -115,39 +113,6 @@ class Prospect extends BaseModel implements Auditable, Subscribable, Educatable, 'birthdate' => 'date', ]; - public function searchableAs(): string - { - return config('scout.prefix') . 'prospects'; - } - - public function toSearchableArray(): array - { - return [ - 'id' => (int) $this->getScoutKey(), - 'status_id' => $this->status_id, - 'source_id' => $this->source_id, - 'first_name' => $this->first_name, - 'last_name' => $this->last_name, - 'full_name' => $this->full_name, - 'preferred' => $this->preferred, - 'description' => $this->description, - 'email' => $this->email, - 'email_2' => $this->email_2, - 'mobile' => $this->mobile, - 'sms_opt_out' => $this->sms_opt_out, - 'email_bounce' => $this->email_bounce, - 'phone' => $this->phone, - 'address' => $this->address, - 'address_2' => $this->address_2, - 'birthdate' => $this->birthdate, - 'hsgrad' => (int) $this->hsgrad, - 'assigned_to_id' => $this->assigned_to_id, - 'created_by_id' => $this->created_by_id, - 'created_at' => $this->created_at->format('Y-m-d H:i:s'), - 'updated_at' => $this->updated_at->format('Y-m-d H:i:s'), - ]; - } - public function identifier(): string { return $this->id; From 0630c2f3446698ce7cdd049c6ffafa66fba19da6 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 17:51:41 -0500 Subject: [PATCH 093/152] Init event registration Signed-off-by: Kevin Ullyott --- .../src/Models/SubmissibleAuthentication.php | 2 +- ..._create_event_registration_forms_table.php | 60 ++++ ...27_194216_create_event_attendees_table.php | 56 ++++ ...7_create_event_attendee_entities_table.php | 52 ++++ ...te_event_registration_form_steps_table.php | 55 ++++ ...e_event_registration_form_fields_table.php | 58 ++++ ...egistration_form_authentications_table.php | 54 ++++ ...nt_registration_form_submissions_table.php | 59 ++++ ...0_create_survey_field_submission_table.php | 54 ++++ .../src/Enums/EventAttendeeStatus.php | 22 ++ .../EventRegistrationWidgetController.php | 263 ++++++++++++++++++ .../src/Models/EventAttendee.php | 61 ++++ .../src/Models/EventRegistrationForm.php | 89 ++++++ .../EventRegistrationFormAuthentication.php | 61 ++++ .../src/Models/EventRegistrationFormField.php | 71 +++++ .../src/Models/EventRegistrationFormStep.php | 71 +++++ .../EventRegistrationFormSubmission.php | 130 +++++++++ ...icateEventRegistrationFormNotification.php | 70 +++++ .../MeetingCenterServiceProvider.php | 12 + ...survey_roles.php => survey_management.php} | 0 20 files changed, 1299 insertions(+), 1 deletion(-) create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194215_create_event_registration_forms_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194216_create_event_attendees_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194217_create_event_attendee_entities_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194226_create_event_registration_form_steps_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194227_create_event_registration_form_fields_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194228_create_event_registration_form_authentications_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php create mode 100644 app-modules/meeting-center/database/migrations/2023_12_27_194230_create_survey_field_submission_table.php create mode 100644 app-modules/meeting-center/src/Enums/EventAttendeeStatus.php create mode 100644 app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php create mode 100644 app-modules/meeting-center/src/Models/EventAttendee.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationForm.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationFormAuthentication.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationFormField.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationFormStep.php create mode 100644 app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php create mode 100644 app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php rename app-modules/survey/config/roles/web/{survey_roles.php => survey_management.php} (100%) diff --git a/app-modules/form/src/Models/SubmissibleAuthentication.php b/app-modules/form/src/Models/SubmissibleAuthentication.php index 9e6c8d5523..b5a0360f6f 100644 --- a/app-modules/form/src/Models/SubmissibleAuthentication.php +++ b/app-modules/form/src/Models/SubmissibleAuthentication.php @@ -66,7 +66,7 @@ public function prunable(): Builder ->where('created_at', '<', now()->subMonth()); } - public function author(): MorphTo + public function author(): MorphTo|BelongsTo { return $this->morphTo(); } diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194215_create_event_registration_forms_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194215_create_event_registration_forms_table.php new file mode 100644 index 0000000000..8571656d00 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194215_create_event_registration_forms_table.php @@ -0,0 +1,60 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_forms', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); + $table->boolean('embed_enabled')->default(false); + $table->json('allowed_domains')->nullable(); + $table->string('primary_color')->nullable(); + $table->string('rounding')->nullable(); + $table->boolean('is_wizard')->default(false); + $table->boolean('recaptcha_enabled')->default(false); + $table->json('content')->nullable(); + + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194216_create_event_attendees_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194216_create_event_attendees_table.php new file mode 100644 index 0000000000..2bcee55835 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194216_create_event_attendees_table.php @@ -0,0 +1,56 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_attendees', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->string('status'); + $table->string('email'); + $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); + + $table->timestamps(); + + $table->unique(['email', 'event_id']); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194217_create_event_attendee_entities_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194217_create_event_attendee_entities_table.php new file mode 100644 index 0000000000..45532122f7 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194217_create_event_attendee_entities_table.php @@ -0,0 +1,52 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_attendees_entities', function (Blueprint $table) { + $table->string('entity_id'); + $table->string('entity_type'); + $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); + + $table->unique(['entity_id', 'entity_type', 'event_attendee_id']); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194226_create_event_registration_form_steps_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194226_create_event_registration_form_steps_table.php new file mode 100644 index 0000000000..bae9ad05b1 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194226_create_event_registration_form_steps_table.php @@ -0,0 +1,55 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_steps', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->text('label'); + $table->json('content')->nullable(); + $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); + $table->integer('sort'); + + $table->timestamps(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194227_create_event_registration_form_fields_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194227_create_event_registration_form_fields_table.php new file mode 100644 index 0000000000..4b8f20c26a --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194227_create_event_registration_form_fields_table.php @@ -0,0 +1,58 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_fields', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->text('label'); + $table->text('type'); + $table->boolean('is_required'); + $table->json('config'); + + $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); + $table->foreignUuid('step_id')->nullable()->constrained('event_registration_form_steps')->cascadeOnDelete(); + + $table->timestamps(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194228_create_event_registration_form_authentications_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194228_create_event_registration_form_authentications_table.php new file mode 100644 index 0000000000..31216c9ba4 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194228_create_event_registration_form_authentications_table.php @@ -0,0 +1,54 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_authentications', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); + $table->string('code')->nullable(); + $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); + + $table->timestamps(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php new file mode 100644 index 0000000000..0165143dbd --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php @@ -0,0 +1,59 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_submissions', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); + $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); + $table->timestamp('submitted_at')->nullable(); + $table->timestamp('canceled_at')->nullable(); + $table->string('request_method')->nullable(); + $table->text('request_note')->nullable(); + $table->foreignUuid('requester_id')->nullable()->constrained('users')->nullOnDelete(); + + $table->timestamps(); + $table->softDeletes(); + }); + } +}; diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194230_create_survey_field_submission_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194230_create_survey_field_submission_table.php new file mode 100644 index 0000000000..d5b0f6c326 --- /dev/null +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194230_create_survey_field_submission_table.php @@ -0,0 +1,54 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +return new class () extends Migration { + public function up(): void + { + Schema::create('event_registration_form_field_submission', function (Blueprint $table) { + $table->uuid('id')->primary(); + + $table->longText('response'); + $table->foreignUuid('field_id')->constrained('event_registration_form_fields')->cascadeOnDelete(); + $table->foreignUuid('submission_id')->constrained('event_registration_form_submissions')->cascadeOnDelete(); + + $table->timestamps(); + }); + } +}; diff --git a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php new file mode 100644 index 0000000000..f84db2a022 --- /dev/null +++ b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php @@ -0,0 +1,22 @@ + 'Not Attending', + default => $this->name, + }; + } +} diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php new file mode 100644 index 0000000000..39dd56722f --- /dev/null +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -0,0 +1,263 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Http\Controllers; + +use Closure; +use Illuminate\Support\Str; +use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use Filament\Support\Colors\Color; +use Illuminate\Support\Facades\URL; +use App\Http\Controllers\Controller; +use Illuminate\Support\Facades\Hash; +use AdvisingApp\Survey\Models\Survey; +use Illuminate\Support\Facades\Validator; +use Illuminate\Support\Facades\Notification; +use Symfony\Component\HttpFoundation\Response; +use AdvisingApp\Survey\Models\SurveySubmission; +use AdvisingApp\Form\Actions\GenerateFormKitSchema; +use AdvisingApp\MeetingCenter\Models\EventAttendee; +use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; +use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; +use AdvisingApp\Application\Models\ApplicationAuthentication; +use AdvisingApp\Form\Actions\ResolveSubmissionAuthorFromEmail; +use AdvisingApp\Form\Filament\Blocks\EducatableEmailFormFieldBlock; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; +use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; +use AdvisingApp\Form\Notifications\AuthenticateEventRegistrationFormNotification; + +class EventRegistrationWidgetController extends Controller +{ + public function view(GenerateFormKitSchema $generateSchema, EventRegistrationForm $form): JsonResponse + { + return response()->json( + [ + 'name' => $form->event->title, + 'description' => $form->event->description, + // TODO: Maybe get rid of this? It would never not be authenticated. + 'is_authenticated' => true, + 'authentication_url' => URL::signedRoute('event-registration.request-authentication', ['form' => $form]), + 'recaptcha_enabled' => $form->recaptcha_enabled, + ...($form->recaptcha_enabled ? [ + 'recaptcha_site_key' => app(GoogleRecaptchaSettings::class)->site_key, + ] : []), + 'schema' => $generateSchema($form), + 'primary_color' => Color::all()[$form->primary_color ?? 'blue'], + 'rounding' => $form->rounding, + ], + ); + } + + public function requestAuthentication(Request $request, EventRegistrationForm $form): JsonResponse + { + $data = $request->validate([ + 'email' => ['required', 'email'], + ]); + + $attendee = EventAttendee::firstOrNew( + [ + 'email' => $data['email'], + 'event_id' => $form->event_id, + ], + ); + + if (empty($attendee->status)) { + $attendee->status = EventAttendeeStatus::Pending; + } + + // TODO: When an EventAttendee is created, we should try and match it to an entity, perhaps in an observer. + $attendee->save(); + + $code = random_int(100000, 999999); + + $authentication = new EventRegistrationFormAuthentication(); + $authentication->author()->associate($attendee); + $authentication->submissible()->associate($form); + $authentication->code = Hash::make($code); + $authentication->save(); + + Notification::route('mail', $attendee->email)->notify(new AuthenticateEventRegistrationFormNotification($authentication, $code)); + + return response()->json([ + 'message' => "We've sent an authentication code to {$attendee->email}.", + 'authentication_url' => URL::signedRoute('event-registration.authenticate', [ + 'form' => $form, + 'authentication' => $authentication, + ]), + ]); + } + + public function authenticate(Request $request, Survey $survey, ApplicationAuthentication $authentication): JsonResponse + { + if ($authentication->isExpired()) { + return response()->json([ + 'is_expired' => true, + ]); + } + + $request->validate([ + 'code' => ['required', 'integer', 'digits:6', function (string $attribute, int $value, Closure $fail) use ($authentication) { + if (Hash::check($value, $authentication->code)) { + return; + } + + $fail('The provided code is invalid.'); + }], + ]); + + return response()->json([ + 'submission_url' => URL::signedRoute('surveys.submit', [ + 'survey' => $authentication, + 'application' => $authentication->submissible, + ]), + ]); + } + + public function store( + Request $request, + GenerateSubmissibleValidation $generateValidation, + ResolveSubmissionAuthorFromEmail $resolveSubmissionAuthorFromEmail, + Survey $survey, + ): JsonResponse { + $authentication = $request->query('authentication'); + + if (filled($authentication)) { + $authentication = ApplicationAuthentication::findOrFail($authentication); + } + + if ( + $survey->is_authenticated && + ($authentication?->isExpired() ?? true) + ) { + abort(Response::HTTP_UNAUTHORIZED); + } + + $validator = Validator::make( + $request->all(), + $generateValidation($survey) + ); + + if ($validator->fails()) { + return response()->json( + [ + 'errors' => (object) $validator->errors(), + ], + Response::HTTP_UNPROCESSABLE_ENTITY + ); + } + + /** @var SurveySubmission $submission */ + $submission = $survey->submissions()->make(); + + if ($authentication) { + $submission->author()->associate($authentication->author); + + $authentication->delete(); + } + + $submission->submitted_at = now(); + + $submission->save(); + + $data = $validator->validated(); + + unset($data['recaptcha-token']); + + if ($survey->is_wizard) { + foreach ($survey->steps as $step) { + $stepFields = $step->fields()->pluck('type', 'id')->all(); + + foreach ($data[$step->label] as $fieldId => $response) { + $submission->fields()->attach( + $fieldId, + ['id' => Str::orderedUuid(), 'response' => $response], + ); + + if ($submission->author) { + continue; + } + + if ($stepFields[$fieldId] !== EducatableEmailFormFieldBlock::type()) { + continue; + } + + $author = $resolveSubmissionAuthorFromEmail($response); + + if (! $author) { + continue; + } + + $submission->author()->associate($author); + } + } + } else { + $surveyFields = $survey->fields()->pluck('type', 'id')->all(); + + foreach ($data as $fieldId => $response) { + $submission->fields()->attach( + $fieldId, + ['id' => Str::orderedUuid(), 'response' => $response], + ); + + if ($submission->author) { + continue; + } + + if ($surveyFields[$fieldId] !== EducatableEmailFormFieldBlock::type()) { + continue; + } + + $author = $resolveSubmissionAuthorFromEmail($response); + + if (! $author) { + continue; + } + + $submission->author()->associate($author); + } + } + + $submission->save(); + + return response()->json( + [ + 'message' => 'Survey submitted successfully.', + ] + ); + } +} diff --git a/app-modules/meeting-center/src/Models/EventAttendee.php b/app-modules/meeting-center/src/Models/EventAttendee.php new file mode 100644 index 0000000000..fab1a5c640 --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventAttendee.php @@ -0,0 +1,61 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use App\Models\BaseModel; +use App\Models\Attributes\NoPermissions; +use Illuminate\Notifications\Notifiable; +use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; + +#[NoPermissions] +/** + * @mixin IdeHelperEventAttendee + */ +class EventAttendee extends BaseModel +{ + use Notifiable; + + protected $fillable = [ + 'status', + 'email', + 'event_id', + ]; + + protected $casts = [ + 'status' => EventAttendeeStatus::class, + ]; +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationForm.php b/app-modules/meeting-center/src/Models/EventRegistrationForm.php new file mode 100644 index 0000000000..672883ea58 --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationForm.php @@ -0,0 +1,89 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use AdvisingApp\Form\Enums\Rounding; +use AdvisingApp\Form\Models\Submissible; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; + +/** + * @mixin IdeHelperEventRegistrationForm + */ +class EventRegistrationForm extends Submissible +{ + protected $fillable = [ + 'form_id', + 'embed_enabled', + 'allowed_domains', + 'is_wizard', + 'recaptcha_enabled', + 'primary_color', + 'rounding', + 'content', + ]; + + protected $casts = [ + 'content' => 'array', + 'embed_enabled' => 'boolean', + 'allowed_domains' => 'array', + 'is_wizard' => 'boolean', + 'recaptcha_enabled' => 'boolean', + 'rounding' => Rounding::class, + ]; + + public function event(): BelongsTo + { + return $this + ->belongsTo(Event::class, 'event_id'); + } + + public function fields(): HasMany + { + return $this->hasMany(EventRegistrationFormField::class); + } + + public function steps(): HasMany + { + return $this->hasMany(EventRegistrationFormStep::class); + } + + public function submissions(): HasMany + { + return $this->hasMany(EventRegistrationFormSubmission::class); + } +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormAuthentication.php b/app-modules/meeting-center/src/Models/EventRegistrationFormAuthentication.php new file mode 100644 index 0000000000..d312ed5e03 --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormAuthentication.php @@ -0,0 +1,61 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use App\Models\Attributes\NoPermissions; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\Form\Models\SubmissibleAuthentication; + +#[NoPermissions] +/** + * @property-read EventRegistrationForm $submissible + * + * @mixin IdeHelperEventRegistrationFormAuthentication + */ +class EventRegistrationFormAuthentication extends SubmissibleAuthentication +{ + public function submissible(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationForm::class, 'form_id'); + } + + public function author(): BelongsTo + { + return $this->belongsTo(EventAttendee::class, 'event_attendee_id'); + } +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormField.php b/app-modules/meeting-center/src/Models/EventRegistrationFormField.php new file mode 100644 index 0000000000..7d1867c5c6 --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormField.php @@ -0,0 +1,71 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use AdvisingApp\Form\Models\SubmissibleField; +use Illuminate\Database\Eloquent\Relations\BelongsTo; + +/** + * @mixin IdeHelperEventRegistrationFormField + */ +class EventRegistrationFormField extends SubmissibleField +{ + protected $fillable = [ + 'config', + 'label', + 'type', + 'is_required', + 'form_id', + ]; + + protected $casts = [ + 'config' => 'array', + 'is_required' => 'bool', + ]; + + public function submissible(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationForm::class, 'form_id'); + } + + public function step(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationFormStep::class, 'step_id'); + } +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormStep.php b/app-modules/meeting-center/src/Models/EventRegistrationFormStep.php new file mode 100644 index 0000000000..89ed913a0f --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormStep.php @@ -0,0 +1,71 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use App\Models\Attributes\NoPermissions; +use AdvisingApp\Form\Models\SubmissibleStep; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; + +#[NoPermissions] +/** + * @mixin IdeHelperEventRegistrationFormStep + */ +class EventRegistrationFormStep extends SubmissibleStep +{ + protected $fillable = [ + 'label', + 'content', + 'sort', + ]; + + protected $casts = [ + 'content' => 'array', + 'sort' => 'integer', + ]; + + public function submissible(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationForm::class, 'form_id'); + } + + public function fields(): HasMany + { + return $this->hasMany(EventRegistrationFormField::class, 'step_id'); + } +} diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php new file mode 100644 index 0000000000..4a1392f1ae --- /dev/null +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php @@ -0,0 +1,130 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Models; + +use App\Models\User; +use AdvisingApp\Form\Models\Submission; +use Illuminate\Database\Eloquent\Builder; +use AdvisingApp\Form\Enums\FormSubmissionStatus; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use AdvisingApp\Form\Enums\FormSubmissionRequestDeliveryMethod; + +/** + * @mixin IdeHelperEventRegistrationFormSubmission + */ +class EventRegistrationFormSubmission extends Submission +{ + protected $fillable = [ + 'canceled_at', + 'form_id', + 'request_method', + 'request_note', + 'submitted_at', + ]; + + protected $casts = [ + 'submitted_at' => 'immutable_datetime', + 'canceled_at' => 'immutable_datetime', + 'request_method' => FormSubmissionRequestDeliveryMethod::class, + ]; + + public function submissible(): BelongsTo + { + return $this + ->belongsTo(EventRegistrationForm::class, 'form_id'); + } + + public function requester(): BelongsTo + { + return $this->belongsTo(User::class, 'requester_id'); + } + + public function fields(): BelongsToMany + { + return $this->belongsToMany( + EventRegistrationFormField::class, + 'event_registration_form_field_submission', + 'submission_id', + 'field_id', + ) + ->withPivot(['id', 'response']); + } + + public function deliverRequest(): void + { + $this->request_method->deliver($this); + } + + public function scopeRequested(Builder $query): Builder + { + return $query->notSubmitted()->notCanceled(); + } + + public function scopeSubmitted(Builder $query): Builder + { + return $query->whereNotNull('submitted_at'); + } + + public function scopeCanceled(Builder $query): Builder + { + return $query->notSubmitted()->whereNotNull('canceled_at'); + } + + public function scopeNotSubmitted(Builder $query): Builder + { + return $query->whereNull('submitted_at'); + } + + public function scopeNotCanceled(Builder $query): Builder + { + return $query->whereNull('canceled_at'); + } + + public function getStatus(): FormSubmissionStatus + { + if ($this->submitted_at) { + return FormSubmissionStatus::Submitted; + } + + if ($this->canceled_at) { + return FormSubmissionStatus::Canceled; + } + + return FormSubmissionStatus::Requested; + } +} diff --git a/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php b/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php new file mode 100644 index 0000000000..6719016200 --- /dev/null +++ b/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php @@ -0,0 +1,70 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Form\Notifications; + +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Notification; +use Illuminate\Notifications\AnonymousNotifiable; +use AdvisingApp\Notification\Notifications\Messages\MailMessage; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; + +class AuthenticateEventRegistrationFormNotification extends Notification +{ + use Queueable; + + public function __construct( + public EventRegistrationFormAuthentication $authentication, + public int $code, + ) {} + + /** + * @return array + */ + public function via(object $notifiable): array + { + return ['mail']; + } + + public function toMail(AnonymousNotifiable $notifiable): MailMessage + { + return MailMessage::make() + ->subject("Your authentication code for {$this->authentication->submissible->event->title} registration") + ->line("Your code is: {$this->code}.") + ->line('You should type this code into the form to authenticate yourself.') + ->line('For security reasons, the code will expire in 24 hours, but you can always request another.'); + } +} diff --git a/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php b/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php index 4da3cd67f1..bc5e36b29c 100644 --- a/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php +++ b/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php @@ -44,10 +44,16 @@ use AdvisingApp\MeetingCenter\Jobs\SyncCalendars; use AdvisingApp\MeetingCenter\MeetingCenterPlugin; use AdvisingApp\MeetingCenter\Models\CalendarEvent; +use AdvisingApp\MeetingCenter\Models\EventAttendee; use Illuminate\Database\Eloquent\Relations\Relation; use AdvisingApp\Authorization\AuthorizationRoleRegistry; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; use AdvisingApp\Authorization\AuthorizationPermissionRegistry; use AdvisingApp\MeetingCenter\Observers\CalendarEventObserver; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; class MeetingCenterServiceProvider extends ServiceProvider { @@ -62,6 +68,12 @@ public function boot(): void 'calendar' => Calendar::class, 'calendar_event' => CalendarEvent::class, 'event' => Event::class, + 'event_attendee' => EventAttendee::class, + 'event_registration_form' => EventRegistrationForm::class, + 'event_registration_form_authentication' => EventRegistrationFormAuthentication::class, + 'event_registration_form_field' => EventRegistrationFormField::class, + 'event_registration_form_step' => EventRegistrationFormStep::class, + 'event_registration_form_submission' => EventRegistrationFormSubmission::class, ]); $this->callAfterResolving(Schedule::class, function (Schedule $schedule) { diff --git a/app-modules/survey/config/roles/web/survey_roles.php b/app-modules/survey/config/roles/web/survey_management.php similarity index 100% rename from app-modules/survey/config/roles/web/survey_roles.php rename to app-modules/survey/config/roles/web/survey_management.php From 22399e10809b6ac54faa2ccce46e091c32cb6945 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 17:57:07 -0500 Subject: [PATCH 094/152] Fix survey widget auth Signed-off-by: Kevin Ullyott --- .../src/Http/Controllers/SurveyWidgetController.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app-modules/survey/src/Http/Controllers/SurveyWidgetController.php b/app-modules/survey/src/Http/Controllers/SurveyWidgetController.php index 5c8a72a9ef..8a1c815907 100644 --- a/app-modules/survey/src/Http/Controllers/SurveyWidgetController.php +++ b/app-modules/survey/src/Http/Controllers/SurveyWidgetController.php @@ -53,7 +53,6 @@ use AdvisingApp\Form\Actions\GenerateFormKitSchema; use AdvisingApp\Survey\Models\SurveyAuthentication; use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; -use AdvisingApp\Application\Models\ApplicationAuthentication; use AdvisingApp\Form\Actions\ResolveSubmissionAuthorFromEmail; use AdvisingApp\Form\Notifications\AuthenticateFormNotification; use AdvisingApp\Form\Filament\Blocks\EducatableEmailFormFieldBlock; @@ -119,7 +118,7 @@ public function requestAuthentication(Request $request, ResolveSubmissionAuthorF ]); } - public function authenticate(Request $request, Survey $survey, ApplicationAuthentication $authentication): JsonResponse + public function authenticate(Request $request, Survey $survey, SurveyAuthentication $authentication): JsonResponse { if ($authentication->isExpired()) { return response()->json([ @@ -139,8 +138,8 @@ public function authenticate(Request $request, Survey $survey, ApplicationAuthen return response()->json([ 'submission_url' => URL::signedRoute('surveys.submit', [ - 'survey' => $authentication, - 'application' => $authentication->submissible, + 'authentication' => $authentication, + 'survey' => $authentication->submissible, ]), ]); } @@ -154,7 +153,7 @@ public function store( $authentication = $request->query('authentication'); if (filled($authentication)) { - $authentication = ApplicationAuthentication::findOrFail($authentication); + $authentication = SurveyAuthentication::findOrFail($authentication); } if ( From e9f66c41e0ccaf722765b9dc83f319b0550d4105 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 18:07:51 -0500 Subject: [PATCH 095/152] Clear out all non-related code from Event Reg Widget Controller Signed-off-by: Kevin Ullyott --- .../EventRegistrationWidgetController.php | 74 +++++-------------- 1 file changed, 17 insertions(+), 57 deletions(-) diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index 39dd56722f..3bd79a987d 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -44,19 +44,16 @@ use Illuminate\Support\Facades\URL; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; -use AdvisingApp\Survey\Models\Survey; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Notification; use Symfony\Component\HttpFoundation\Response; -use AdvisingApp\Survey\Models\SurveySubmission; use AdvisingApp\Form\Actions\GenerateFormKitSchema; use AdvisingApp\MeetingCenter\Models\EventAttendee; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; -use AdvisingApp\Application\Models\ApplicationAuthentication; use AdvisingApp\Form\Actions\ResolveSubmissionAuthorFromEmail; -use AdvisingApp\Form\Filament\Blocks\EducatableEmailFormFieldBlock; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; use AdvisingApp\Form\Notifications\AuthenticateEventRegistrationFormNotification; @@ -122,7 +119,7 @@ public function requestAuthentication(Request $request, EventRegistrationForm $f ]); } - public function authenticate(Request $request, Survey $survey, ApplicationAuthentication $authentication): JsonResponse + public function authenticate(Request $request, EventRegistrationForm $form, EventRegistrationFormAuthentication $authentication): JsonResponse { if ($authentication->isExpired()) { return response()->json([ @@ -141,9 +138,9 @@ public function authenticate(Request $request, Survey $survey, ApplicationAuthen ]); return response()->json([ - 'submission_url' => URL::signedRoute('surveys.submit', [ - 'survey' => $authentication, - 'application' => $authentication->submissible, + 'submission_url' => URL::signedRoute('event-registration.submit', [ + 'authentication' => $authentication, + 'form' => $authentication->submissible, ]), ]); } @@ -152,16 +149,15 @@ public function store( Request $request, GenerateSubmissibleValidation $generateValidation, ResolveSubmissionAuthorFromEmail $resolveSubmissionAuthorFromEmail, - Survey $survey, + EventRegistrationForm $form, ): JsonResponse { $authentication = $request->query('authentication'); if (filled($authentication)) { - $authentication = ApplicationAuthentication::findOrFail($authentication); + $authentication = EventRegistrationFormAuthentication::findOrFail($authentication); } if ( - $survey->is_authenticated && ($authentication?->isExpired() ?? true) ) { abort(Response::HTTP_UNAUTHORIZED); @@ -169,7 +165,7 @@ public function store( $validator = Validator::make( $request->all(), - $generateValidation($survey) + $generateValidation($form) ); if ($validator->fails()) { @@ -181,74 +177,38 @@ public function store( ); } - /** @var SurveySubmission $submission */ - $submission = $survey->submissions()->make(); + /** @var EventRegistrationFormSubmission $submission */ + $submission = $form->submissions()->make(); - if ($authentication) { - $submission->author()->associate($authentication->author); + $submission->author()->associate($authentication->author); - $authentication->delete(); - } + $authentication->delete(); $submission->submitted_at = now(); + // TODO: Adjust the status of the EventAttendee to Attending or Not Attending based on the form submission. + $submission->save(); $data = $validator->validated(); unset($data['recaptcha-token']); - if ($survey->is_wizard) { - foreach ($survey->steps as $step) { - $stepFields = $step->fields()->pluck('type', 'id')->all(); - + if ($form->is_wizard) { + foreach ($form->steps as $step) { foreach ($data[$step->label] as $fieldId => $response) { $submission->fields()->attach( $fieldId, ['id' => Str::orderedUuid(), 'response' => $response], ); - - if ($submission->author) { - continue; - } - - if ($stepFields[$fieldId] !== EducatableEmailFormFieldBlock::type()) { - continue; - } - - $author = $resolveSubmissionAuthorFromEmail($response); - - if (! $author) { - continue; - } - - $submission->author()->associate($author); } } } else { - $surveyFields = $survey->fields()->pluck('type', 'id')->all(); - foreach ($data as $fieldId => $response) { $submission->fields()->attach( $fieldId, ['id' => Str::orderedUuid(), 'response' => $response], ); - - if ($submission->author) { - continue; - } - - if ($surveyFields[$fieldId] !== EducatableEmailFormFieldBlock::type()) { - continue; - } - - $author = $resolveSubmissionAuthorFromEmail($response); - - if (! $author) { - continue; - } - - $submission->author()->associate($author); } } @@ -256,7 +216,7 @@ public function store( return response()->json( [ - 'message' => 'Survey submitted successfully.', + 'message' => 'Event registration submitted successfully.', ] ); } From a308bb3fcd456bc4031f635b7120aab9cbcd69de Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 18:27:41 -0500 Subject: [PATCH 096/152] Setup EventRegistrationForm Controller and relations Signed-off-by: Kevin Ullyott --- .../Actions/GenerateSubmissibleEmbedCode.php | 10 +++ .../render-event-registration-form.blade.php | 42 +++++++++++++ app-modules/meeting-center/routes/api.php | 62 +++++++++++++++++++ app-modules/meeting-center/routes/web.php | 9 +++ .../Livewire/RenderEventRegistrationForm.php | 60 ++++++++++++++++++ 5 files changed, 183 insertions(+) create mode 100644 app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php create mode 100644 app-modules/meeting-center/routes/api.php create mode 100644 app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php diff --git a/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php b/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php index 41140906d9..ea28b94f01 100644 --- a/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php +++ b/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php @@ -42,6 +42,7 @@ use AdvisingApp\Survey\Models\Survey; use AdvisingApp\Form\Models\Submissible; use AdvisingApp\Application\Models\Application; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; class GenerateSubmissibleEmbedCode { @@ -75,6 +76,15 @@ public function handle(Submissible $submissible): string EOD; })(), + EventRegistrationForm::class => (function () use ($submissible) { + $scriptUrl = url('js/widgets/events/advising-app-event-registration-form-widget.js?'); + $formDefinitionUrl = URL::signedRoute('event-registration.define', ['form' => $submissible]); + + return << + + EOD; + })(), default => throw new Exception('Unsupported submissible type.'), }; } diff --git a/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php b/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php new file mode 100644 index 0000000000..26a5435918 --- /dev/null +++ b/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php @@ -0,0 +1,42 @@ +{{-- + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +--}} +@php + use AdvisingApp\Form\Actions\GenerateSubmissibleEmbedCode; +@endphp + +
+
+ {!! resolve(GenerateSubmissibleEmbedCode::class)->handle($this->eventRegistrationForm) !!} +
+
diff --git a/app-modules/meeting-center/routes/api.php b/app-modules/meeting-center/routes/api.php new file mode 100644 index 0000000000..13aa9a6000 --- /dev/null +++ b/app-modules/meeting-center/routes/api.php @@ -0,0 +1,62 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +use AdvisingApp\Form\Http\Middleware\EnsureSubmissibleIsEmbeddableAndAuthorized; +use AdvisingApp\MeetingCenter\Http\Controllers\EventRegistrationWidgetController; + +Route::prefix('api') + ->middleware([ + 'api', + EnsureSubmissibleIsEmbeddableAndAuthorized::class . ':form', + ]) + ->group(function () { + Route::prefix('event-registration') + ->name('event-registration.') + ->group(function () { + Route::get('/{form}', [EventRegistrationWidgetController::class, 'view']) + ->middleware(['signed']) + ->name('define'); + Route::post('/{form}/authenticate/request', [EventRegistrationWidgetController::class, 'requestAuthentication']) + ->middleware(['signed']) + ->name('request-authentication'); + Route::post('/{form}/authenticate/{authentication}', [EventRegistrationWidgetController::class, 'authenticate']) + ->middleware(['signed']) + ->name('authenticate'); + Route::post('/{form}/submit', [EventRegistrationWidgetController::class, 'store']) + ->middleware(['signed']) + ->name('submit'); + }); + }); diff --git a/app-modules/meeting-center/routes/web.php b/app-modules/meeting-center/routes/web.php index 796a4317ab..a55eb2e6f2 100644 --- a/app-modules/meeting-center/routes/web.php +++ b/app-modules/meeting-center/routes/web.php @@ -35,6 +35,7 @@ */ use AdvisingApp\MeetingCenter\Enums\CalendarProvider; +use AdvisingApp\Survey\Livewire\RenderEventRegistrationForm; use AdvisingApp\MeetingCenter\Http\Controllers\GoogleCalendarController; use AdvisingApp\MeetingCenter\Http\Controllers\OutlookCalendarController; @@ -45,3 +46,11 @@ provider_routes(CalendarProvider::Google, GoogleCalendarController::class); provider_routes(CalendarProvider::Outlook, OutlookCalendarController::class); }); + +Route::middleware('web') + ->prefix('event-registration') + ->name('event-registration.') + ->group(function () { + Route::get('/{eventRegistrationForm}/respond', RenderEventRegistrationForm::class) + ->name('show'); + }); diff --git a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php new file mode 100644 index 0000000000..fbb4552603 --- /dev/null +++ b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php @@ -0,0 +1,60 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Survey\Livewire; + +use Livewire\Component; +use Illuminate\Contracts\View\View; +use Filament\Forms\Contracts\HasForms; +use Filament\Forms\Concerns\InteractsWithForms; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; + +class RenderEventRegistrationForm extends Component implements HasForms +{ + use InteractsWithForms; + + public bool $show = true; + + public EventRegistrationForm $eventRegistrationForm; + + public ?array $data = []; + + public function render(): View + { + return view('meeting-center::livewire.render-event-registration-form') + ->title("{$this->eventRegistrationForm->event->title} Registration"); + } +} From 99d0c79d2ef5d0ad23420986512112f885e61321 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 18:37:26 -0500 Subject: [PATCH 097/152] Setup the event registration widget Signed-off-by: Kevin Ullyott --- package.json | 3 +- widgets/event-registration/postcss.config.js | 42 ++ widgets/event-registration/src/App.vue | 358 ++++++++++++++++++ .../event-registration/src/formkit.config.js | 47 +++ widgets/event-registration/src/widget.css | 38 ++ widgets/event-registration/src/widget.js | 62 +++ widgets/event-registration/tailwind.config.js | 39 ++ .../tailwind.config.preset.js | 69 ++++ widgets/event-registration/vite.config.js | 58 +++ 9 files changed, 715 insertions(+), 1 deletion(-) create mode 100644 widgets/event-registration/postcss.config.js create mode 100644 widgets/event-registration/src/App.vue create mode 100644 widgets/event-registration/src/formkit.config.js create mode 100644 widgets/event-registration/src/widget.css create mode 100644 widgets/event-registration/src/widget.js create mode 100644 widgets/event-registration/tailwind.config.js create mode 100644 widgets/event-registration/tailwind.config.preset.js create mode 100644 widgets/event-registration/vite.config.js diff --git a/package.json b/package.json index a189c50282..3b3beb6502 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,11 @@ "build:js-compile": "node ./bin/build.js", "build:filament": "php artisan filament:assets", "build:vite": "vite build", - "build": "npm run build:js-compile && npm run build:vite && npm run build:filament && npm run build:application && npm run build:form && npm run build:survey", "build:application": "(cd widgets/application && vite build)", "build:form": "(cd widgets/form && vite build)", "build:survey": "(cd widgets/survey && vite build)", + "build:event-registration": "(cd widgets/event-registration && vite build)", + "build": "npm run build:js-compile && npm run build:vite && npm run build:filament && npm run build:application && npm run build:form && npm run build:survey && npm run build:event-registration", "api-docs:generate": "export NODE_OPTIONS=--max_old_space_size=4096 && env-cmd spectaql spectaql.yml" }, "devDependencies": { diff --git a/widgets/event-registration/postcss.config.js b/widgets/event-registration/postcss.config.js new file mode 100644 index 0000000000..2f7f96d2ff --- /dev/null +++ b/widgets/event-registration/postcss.config.js @@ -0,0 +1,42 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +export default { + plugins: { + 'tailwindcss/nesting': {}, + tailwindcss: { + config: './tailwind.config.js', + }, + autoprefixer: {}, + }, +} diff --git a/widgets/event-registration/src/App.vue b/widgets/event-registration/src/App.vue new file mode 100644 index 0000000000..78579b05e8 --- /dev/null +++ b/widgets/event-registration/src/App.vue @@ -0,0 +1,358 @@ + + + + diff --git a/widgets/event-registration/src/formkit.config.js b/widgets/event-registration/src/formkit.config.js new file mode 100644 index 0000000000..26e2877b28 --- /dev/null +++ b/widgets/event-registration/src/formkit.config.js @@ -0,0 +1,47 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import { generateClasses } from '@formkit/themes'; +import { genesisIcons } from '@formkit/icons'; +import theme from '../../form/src/FormKit/theme'; +import inputs from '../../form/src/FormKit/Inputs/index'; + +export default { + icons: { + ...genesisIcons, + }, + inputs, + config: { + classes: generateClasses(theme), + }, +}; diff --git a/widgets/event-registration/src/widget.css b/widgets/event-registration/src/widget.css new file mode 100644 index 0000000000..e896335f42 --- /dev/null +++ b/widgets/event-registration/src/widget.css @@ -0,0 +1,38 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +@import '../../form/src/FormKit/index.css'; + +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/widgets/event-registration/src/widget.js b/widgets/event-registration/src/widget.js new file mode 100644 index 0000000000..53f8f4e47d --- /dev/null +++ b/widgets/event-registration/src/widget.js @@ -0,0 +1,62 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import { createApp, defineCustomElement, getCurrentInstance, h } from "vue"; +import "./widget.css"; +import App from "./App.vue"; +import { defaultConfig, plugin } from "@formkit/vue"; +import config from "./formkit.config.js"; +import VueSignaturePad from "vue-signature-pad"; + +customElements.define( + 'event-registration-embed', + defineCustomElement({ + setup(props) { + const app = createApp(); + + // install plugins + app.use(plugin, defaultConfig(config)); + + app.use(VueSignaturePad); + + app.config.devtools = true; + + const inst = getCurrentInstance(); + Object.assign(inst.appContext, app._context); + Object.assign(inst.provides, app._context.provides); + + return () => h(App, props); + }, + props: ['url'], + }), +); diff --git a/widgets/event-registration/tailwind.config.js b/widgets/event-registration/tailwind.config.js new file mode 100644 index 0000000000..9ab2129136 --- /dev/null +++ b/widgets/event-registration/tailwind.config.js @@ -0,0 +1,39 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import preset from './tailwind.config.preset.js'; + +export default { + presets: [preset], + content: ['./src/**/*.vue', './src/FormKit/theme.js'], +}; diff --git a/widgets/event-registration/tailwind.config.preset.js b/widgets/event-registration/tailwind.config.preset.js new file mode 100644 index 0000000000..f65aaf5496 --- /dev/null +++ b/widgets/event-registration/tailwind.config.preset.js @@ -0,0 +1,69 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import forms from '@tailwindcss/forms'; +import typography from '@tailwindcss/typography'; +import FormKitVariants from '@formkit/themes/tailwindcss'; + +export default { + theme: { + extend: { + colors: { + primary: { + 50: 'rgba(var(--primary-50), )', + 100: 'rgba(var(--primary-100), )', + 200: 'rgba(var(--primary-200), )', + 300: 'rgba(var(--primary-300), )', + 400: 'rgba(var(--primary-400), )', + 500: 'rgba(var(--primary-500), )', + 600: 'rgba(var(--primary-600), )', + 700: 'rgba(var(--primary-700), )', + 800: 'rgba(var(--primary-800), )', + 900: 'rgba(var(--primary-900), )', + 950: 'rgba(var(--primary-950), )', + }, + }, + borderRadius: { + sm: 'var(--rounding-sm)', + DEFAULT: 'var(--rounding)', + md: 'var(--rounding-md)', + lg: 'var(--rounding-lg)', + full: 'var(--rounding-sm)', + }, + fontFamily: { + signature: ['Satisfy', 'cursive'], + }, + }, + }, + plugins: [forms, typography, FormKitVariants], +} diff --git a/widgets/event-registration/vite.config.js b/widgets/event-registration/vite.config.js new file mode 100644 index 0000000000..72ee5f9760 --- /dev/null +++ b/widgets/event-registration/vite.config.js @@ -0,0 +1,58 @@ +/* + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ +import { resolve } from "path"; +import { defineConfig } from "vite"; +import vue from "@vitejs/plugin-vue"; + +export default defineConfig({ + plugins: [vue()], + build: { + manifest: true, + lib: { + entry: resolve(__dirname, 'src/widget.js'), + name: 'AdvisingAppEventRegistrationFormWidget', + fileName: 'advising-app-event-registration-form-widget', + formats: ['es'], + }, + outDir: resolve(__dirname, '../../public/js/widgets/events'), + emptyOutDir: true, + sourcemap: true, + }, + resolve: { + alias: { + '@': resolve(__dirname, 'src'), + }, + }, + define: { 'process.env.NODE_ENV': '"production"' }, +}); From b9d0e76c031dac3cf5479bce812d40b957fa9c9b Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 19:01:41 -0500 Subject: [PATCH 098/152] Fix namespace Signed-off-by: Kevin Ullyott --- app-modules/meeting-center/routes/web.php | 2 +- .../meeting-center/src/Livewire/RenderEventRegistrationForm.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app-modules/meeting-center/routes/web.php b/app-modules/meeting-center/routes/web.php index a55eb2e6f2..d1b6d06442 100644 --- a/app-modules/meeting-center/routes/web.php +++ b/app-modules/meeting-center/routes/web.php @@ -35,7 +35,7 @@ */ use AdvisingApp\MeetingCenter\Enums\CalendarProvider; -use AdvisingApp\Survey\Livewire\RenderEventRegistrationForm; +use AdvisingApp\MeetingCenter\Livewire\RenderEventRegistrationForm; use AdvisingApp\MeetingCenter\Http\Controllers\GoogleCalendarController; use AdvisingApp\MeetingCenter\Http\Controllers\OutlookCalendarController; diff --git a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php index fbb4552603..60dc4d9cdf 100644 --- a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php +++ b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php @@ -34,7 +34,7 @@ */ -namespace AdvisingApp\Survey\Livewire; +namespace AdvisingApp\MeetingCenter\Livewire; use Livewire\Component; use Illuminate\Contracts\View\View; From a5fe53ba9daa581e1ca3ad9f152958fd18b0316b Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 19:44:35 -0500 Subject: [PATCH 099/152] Start adding the ability to add a Form to the Event edit page Signed-off-by: Kevin Ullyott --- .../EventResource/Pages/EditEvent.php | 186 +++++++++++ .../meeting-center/src/Models/Event.php | 6 + .../src/Models/EventRegistrationForm.php | 6 +- composer.json | 2 +- composer.lock | 288 ++++++++---------- 5 files changed, 323 insertions(+), 165 deletions(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index 7a1ac857ca..cda81e3d39 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -37,14 +37,33 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; use App\Models\User; +use Filament\Forms\Get; use Filament\Forms\Form; use Filament\Actions\ViewAction; use Filament\Actions\DeleteAction; +use Filament\Forms\Components\Grid; +use AdvisingApp\Form\Enums\Rounding; +use AdvisingApp\Form\Rules\IsDomain; +use App\Forms\Components\ColorSelect; +use Filament\Forms\Components\Select; +use Filament\Forms\Components\Toggle; +use Filament\Forms\Components\Section; +use FilamentTiptapEditor\TiptapEditor; +use Filament\Forms\Components\Fieldset; +use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TagsInput; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; +use AdvisingApp\MeetingCenter\Models\Event; +use FilamentTiptapEditor\Enums\TiptapOutput; use Filament\Forms\Components\DateTimePicker; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; +use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; +use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; +use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; class EditEvent extends EditRecord { @@ -75,9 +94,176 @@ public function form(Form $form): Form DateTimePicker::make('ends_at') ->timezone($user->timezone) ->required(), + Fieldset::make('Registration Form') + ->relationship('eventRegistrationForm') + ->schema([ + Grid::make() + ->schema([ + Toggle::make('embed_enabled') + ->label('Embed Enabled') + ->live() + ->helperText('If enabled, this form can be embedded on other websites.'), + TagsInput::make('allowed_domains') + ->label('Allowed Domains') + ->helperText('Only these domains will be allowed to embed this form.') + ->placeholder('example.com') + ->hidden(fn (Get $get) => ! $get('embed_enabled')) + ->disabled(fn (Get $get) => ! $get('embed_enabled')) + ->nestedRecursiveRules( + [ + 'string', + new IsDomain(), + ] + ), + ]) + ->columnSpanFull(), + Toggle::make('is_wizard') + ->label('Multi-step form') + ->live() + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), + Section::make('Fields') + ->schema([ + $this->fieldBuilder(), + ]) + ->hidden(fn (Get $get) => $get('is_wizard')) + ->disabled(fn (?EventRegistrationForm $record) => $record->submissions()->exists()), + Repeater::make('steps') + ->schema([ + TextInput::make('label') + ->required() + ->string() + ->maxLength(255) + ->autocomplete(false) + ->columnSpanFull() + ->lazy(), + $this->fieldBuilder(), + ]) + ->addActionLabel('New step') + ->itemLabel(fn (array $state): ?string => $state['label'] ?? null) + ->visible(fn (Get $get) => $get('is_wizard')) + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()) + ->relationship() + ->reorderable() + ->columnSpanFull(), + Section::make('Appearance') + ->schema([ + ColorSelect::make('primary_color'), + Select::make('rounding') + ->options(Rounding::class), + ]) + ->columns(), + ]), ]); } + public function fieldBuilder(): TiptapEditor + { + return TiptapEditor::make('content') + ->output(TiptapOutput::Json) + ->blocks(FormFieldBlockRegistry::get()) + ->tools(['bold', 'italic', 'small', '|', 'heading', 'bullet-list', 'ordered-list', 'hr', '|', 'link', 'grid', 'blocks']) + ->placeholder('Drag blocks here to build your form') + ->hiddenLabel() + ->saveRelationshipsUsing(function (TiptapEditor $component, EventRegistrationForm | EventRegistrationFormStep $record) { + if ($component->isDisabled()) { + return; + } + + $form = $record instanceof EventRegistrationForm ? $record : $record->submissible; + $formStep = $record instanceof EventRegistrationFormStep ? $record : null; + + EventRegistrationFormStep::query() + ->whereBelongsTo($form, 'submissible') + ->when($formStep, fn (EloquentBuilder $query) => $query->whereBelongsTo($formStep, 'step')) + ->delete(); + + $content = $component->decodeBlocksBeforeSave($component->getJSON(decoded: true)); + $content['content'] = $this->saveFieldsFromComponents( + $form, + $content['content'] ?? [], + $formStep, + ); + + $record->content = $content; + $record->save(); + }) + ->dehydrated(false) + ->columnSpanFull() + ->extraInputAttributes(['style' => 'min-height: 12rem;']); + } + + public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array + { + foreach ($components as $componentKey => $component) { + if (array_key_exists('content', $component)) { + $components[$componentKey]['content'] = $this->saveFieldsFromComponents($form, $component['content'], $eventRegistrationFormStep); + + continue; + } + + if ($component['type'] !== 'tiptapBlock') { + continue; + } + + $componentAttributes = $component['attrs'] ?? []; + + if (array_key_exists('id', $componentAttributes)) { + $id = $componentAttributes['id'] ?? null; + unset($componentAttributes['id']); + } + + if (array_key_exists('label', $componentAttributes['data'])) { + $label = $componentAttributes['data']['label'] ?? null; + unset($componentAttributes['data']['label']); + } + + if (array_key_exists('isRequired', $componentAttributes['data'])) { + $isRequired = $componentAttributes['data']['isRequired'] ?? null; + unset($componentAttributes['data']['isRequired']); + } + + /** @var EventRegistrationFormField $field */ + $field = $form->fields()->findOrNew($id ?? null); + $field->step()->associate($eventRegistrationFormStep); + $field->label = $label ?? $componentAttributes['type']; + $field->is_required = $isRequired ?? false; + $field->type = $componentAttributes['type']; + $field->config = $componentAttributes['data']; + $field->save(); + + $components[$componentKey]['attrs']['id'] = $field->id; + } + + return $components; + } + + protected function afterCreate(): void + { + $this->clearFormContentForWizard(); + } + + protected function afterSave(): void + { + $this->clearFormContentForWizard(); + } + + protected function clearFormContentForWizard(): void + { + /** @var Event $event */ + $event = $this->record; + + $form = $event->eventRegistrationForm; + + if ($form->is_wizard) { + $form->content = null; + $form->save(); + + return; + } + + $form->steps()->delete(); + } + protected function getHeaderActions(): array { return [ diff --git a/app-modules/meeting-center/src/Models/Event.php b/app-modules/meeting-center/src/Models/Event.php index 6484c5341e..e19a7706e9 100644 --- a/app-modules/meeting-center/src/Models/Event.php +++ b/app-modules/meeting-center/src/Models/Event.php @@ -37,6 +37,7 @@ namespace AdvisingApp\MeetingCenter\Models; use App\Models\BaseModel; +use Illuminate\Database\Eloquent\Relations\HasOne; /** * @mixin IdeHelperEvent @@ -56,4 +57,9 @@ class Event extends BaseModel 'starts_at' => 'datetime', 'ends_at' => 'datetime', ]; + + public function eventRegistrationForm(): HasOne + { + return $this->hasOne(EventRegistrationForm::class, 'event_id'); + } } diff --git a/app-modules/meeting-center/src/Models/EventRegistrationForm.php b/app-modules/meeting-center/src/Models/EventRegistrationForm.php index 672883ea58..e8ed9f9aa2 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationForm.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationForm.php @@ -74,16 +74,16 @@ public function event(): BelongsTo public function fields(): HasMany { - return $this->hasMany(EventRegistrationFormField::class); + return $this->hasMany(EventRegistrationFormField::class, 'form_id'); } public function steps(): HasMany { - return $this->hasMany(EventRegistrationFormStep::class); + return $this->hasMany(EventRegistrationFormStep::class, 'form_id'); } public function submissions(): HasMany { - return $this->hasMany(EventRegistrationFormSubmission::class); + return $this->hasMany(EventRegistrationFormSubmission::class, 'form_id'); } } diff --git a/composer.json b/composer.json index 9ac9e26dce..97e808d8fb 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "php": "8.2.*", "ext-gd": "*", "ext-pdo": "*", - "awcodes/filament-tiptap-editor": "^3.2.14", + "awcodes/filament-tiptap-editor": "^3.2.17", "aws/aws-php-sns-message-validator": "^1.8.0", "aws/aws-sdk-php": "^3.293", "barryvdh/laravel-debugbar": "^3.9", diff --git a/composer.lock b/composer.lock index 7f43c3aa26..2377067c69 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4135a59df44c5333303e7a1b6f1ff947", + "content-hash": "a7c988d45a8bf04ea377069a6dd7b23a", "packages": [ { "name": "amphp/amp", @@ -559,16 +559,16 @@ }, { "name": "awcodes/filament-tiptap-editor", - "version": "v3.2.18", + "version": "v3.2.17", "source": { "type": "git", "url": "https://github.com/awcodes/filament-tiptap-editor.git", - "reference": "7de016e723ba62908f979a39204955e1801b0967" + "reference": "0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/7de016e723ba62908f979a39204955e1801b0967", - "reference": "7de016e723ba62908f979a39204955e1801b0967", + "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f", + "reference": "0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f", "shasum": "" }, "require": { @@ -630,7 +630,7 @@ ], "support": { "issues": "https://github.com/awcodes/filament-tiptap-editor/issues", - "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.18" + "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.17" }, "funding": [ { @@ -638,7 +638,7 @@ "type": "github" } ], - "time": "2023-12-28T20:05:06+00:00" + "time": "2023-12-27T19:10:56+00:00" }, { "name": "aws/aws-crt-php", @@ -755,16 +755,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.295.3", + "version": "3.294.5", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "3346f60c6c5075453f90f703693f764dad76a3a8" + "reference": "2e34d45e970c77775e4c298e08732d64b647c41c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3346f60c6c5075453f90f703693f764dad76a3a8", - "reference": "3346f60c6c5075453f90f703693f764dad76a3a8", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2e34d45e970c77775e4c298e08732d64b647c41c", + "reference": "2e34d45e970c77775e4c298e08732d64b647c41c", "shasum": "" }, "require": { @@ -844,9 +844,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.295.3" + "source": "https://github.com/aws/aws-sdk-php/tree/3.294.5" }, - "time": "2023-12-28T19:32:33+00:00" + "time": "2023-12-21T19:10:21+00:00" }, { "name": "barryvdh/laravel-debugbar", @@ -2379,41 +2379,6 @@ "relative": true } }, - { - "name": "canyon-gbs/inventory-management", - "version": "1.0", - "dist": { - "type": "path", - "url": "app-modules/inventory-management", - "reference": "16210c789f3a6d5a4b14ce0db3a17f5cdc4f6e48" - }, - "require": { - "filament/filament": "^3.0.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "AdvisingApp\\InventoryManagement\\Providers\\InventoryManagementServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "AdvisingApp\\InventoryManagement\\": "src/", - "AdvisingApp\\InventoryManagement\\Tests\\": "tests/", - "AdvisingApp\\InventoryManagement\\Database\\Factories\\": "database/factories/", - "AdvisingApp\\InventoryManagement\\Database\\Seeders\\": "database/seeders/" - } - }, - "license": [ - "proprietary" - ], - "transport-options": { - "symlink": true, - "relative": true - } - }, { "name": "carbonphp/carbon-doctrine-types", "version": "2.1.0", @@ -4106,16 +4071,16 @@ }, { "name": "filament/actions", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203" + "reference": "be3a8c110aa69f3f4856816eefd477b600bc06e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/8f2a3df7c607a24c2433a3a71cb27b20a8dea203", - "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/be3a8c110aa69f3f4856816eefd477b600bc06e2", + "reference": "be3a8c110aa69f3f4856816eefd477b600bc06e2", "shasum": "" }, "require": { @@ -4153,20 +4118,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:29+00:00" + "time": "2023-12-21T12:38:03+00:00" }, { "name": "filament/filament", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "ae12dc49094560188a4289778a54773045880e44" + "reference": "e1aa070483c2eaa5bb92ce8d959779a9558fe022" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/ae12dc49094560188a4289778a54773045880e44", - "reference": "ae12dc49094560188a4289778a54773045880e44", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/e1aa070483c2eaa5bb92ce8d959779a9558fe022", + "reference": "e1aa070483c2eaa5bb92ce8d959779a9558fe022", "shasum": "" }, "require": { @@ -4218,20 +4183,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:35+00:00" + "time": "2023-12-22T14:36:15+00:00" }, { "name": "filament/forms", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506" + "reference": "673689bd958797b05127fe9956eafeed555b91bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/26e177a4b3a8ef7b8326d992bb5073f02220a506", - "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/673689bd958797b05127fe9956eafeed555b91bd", + "reference": "673689bd958797b05127fe9956eafeed555b91bd", "shasum": "" }, "require": { @@ -4274,20 +4239,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:30+00:00" + "time": "2023-12-22T14:36:00+00:00" }, { "name": "filament/infolists", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", - "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3" + "reference": "9207c2b83ba9c8dcbcac9a930e93ce87f381d780" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/infolists/zipball/66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", - "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", + "url": "https://api.github.com/repos/filamentphp/infolists/zipball/9207c2b83ba9c8dcbcac9a930e93ce87f381d780", + "reference": "9207c2b83ba9c8dcbcac9a930e93ce87f381d780", "shasum": "" }, "require": { @@ -4325,20 +4290,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-26T22:39:20+00:00" + "time": "2023-12-22T14:36:00+00:00" }, { "name": "filament/notifications", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", - "reference": "4f5634f9df312050efa3a035c543add6cec0e3a2" + "reference": "5b9255c0793751534461cace12febdc0d4cc05bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/notifications/zipball/4f5634f9df312050efa3a035c543add6cec0e3a2", - "reference": "4f5634f9df312050efa3a035c543add6cec0e3a2", + "url": "https://api.github.com/repos/filamentphp/notifications/zipball/5b9255c0793751534461cace12febdc0d4cc05bb", + "reference": "5b9255c0793751534461cace12febdc0d4cc05bb", "shasum": "" }, "require": { @@ -4377,11 +4342,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:27+00:00" + "time": "2023-12-17T22:25:42+00:00" }, { "name": "filament/spatie-laravel-media-library-plugin", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-media-library-plugin.git", @@ -4418,16 +4383,16 @@ }, { "name": "filament/spatie-laravel-settings-plugin", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-settings-plugin.git", - "reference": "d26f397a845934462d511432ba88363f63a7e203" + "reference": "7119f3f714dfa0ce098cd90aa2a741147a5508f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/spatie-laravel-settings-plugin/zipball/d26f397a845934462d511432ba88363f63a7e203", - "reference": "d26f397a845934462d511432ba88363f63a7e203", + "url": "https://api.github.com/repos/filamentphp/spatie-laravel-settings-plugin/zipball/7119f3f714dfa0ce098cd90aa2a741147a5508f6", + "reference": "7119f3f714dfa0ce098cd90aa2a741147a5508f6", "shasum": "" }, "require": { @@ -4461,20 +4426,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-26T22:39:37+00:00" + "time": "2023-12-19T13:24:28+00:00" }, { "name": "filament/support", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "97792dad038a87b7a6bfe465c4f1913252c99017" + "reference": "f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/97792dad038a87b7a6bfe465c4f1913252c99017", - "reference": "97792dad038a87b7a6bfe465c4f1913252c99017", + "url": "https://api.github.com/repos/filamentphp/support/zipball/f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd", + "reference": "f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd", "shasum": "" }, "require": { @@ -4518,20 +4483,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-24T21:16:58+00:00" + "time": "2023-12-22T14:36:21+00:00" }, { "name": "filament/tables", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118" + "reference": "3391bd1015bdde8e454d0a6391952dc131fb8dad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/e0701467097f6a82b235ad9f31e3c30ae1035118", - "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/3391bd1015bdde8e454d0a6391952dc131fb8dad", + "reference": "3391bd1015bdde8e454d0a6391952dc131fb8dad", "shasum": "" }, "require": { @@ -4571,20 +4536,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T17:31:59+00:00" + "time": "2023-12-22T14:36:23+00:00" }, { "name": "filament/widgets", - "version": "v3.1.31", + "version": "v3.1.27", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd" + "reference": "290184b9dfb99436df94a9a0b8511b21811d9e64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", - "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/290184b9dfb99436df94a9a0b8511b21811d9e64", + "reference": "290184b9dfb99436df94a9a0b8511b21811d9e64", "shasum": "" }, "require": { @@ -4615,7 +4580,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T17:31:57+00:00" + "time": "2023-12-17T22:26:03+00:00" }, { "name": "firebase/php-jwt", @@ -5189,16 +5154,16 @@ }, { "name": "google/apiclient-services", - "version": "v0.329.0", + "version": "v0.328.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "3216fd1b6ba33c5f6658c3581e9723ff21d9acb7" + "reference": "211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/3216fd1b6ba33c5f6658c3581e9723ff21d9acb7", - "reference": "3216fd1b6ba33c5f6658c3581e9723ff21d9acb7", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d", + "reference": "211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d", "shasum": "" }, "require": { @@ -5227,9 +5192,9 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.329.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.328.0" }, - "time": "2023-12-24T01:02:15+00:00" + "time": "2023-12-18T01:00:18+00:00" }, { "name": "google/auth", @@ -6217,16 +6182,16 @@ }, { "name": "laravel/framework", - "version": "v10.39.0", + "version": "v10.38.2", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "114926b07bfb5fbf2545c03aa2ce5c8c37be650c" + "reference": "43da808391da3540d44a8dfeb4e46da4ad8f5723" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/114926b07bfb5fbf2545c03aa2ce5c8c37be650c", - "reference": "114926b07bfb5fbf2545c03aa2ce5c8c37be650c", + "url": "https://api.github.com/repos/laravel/framework/zipball/43da808391da3540d44a8dfeb4e46da4ad8f5723", + "reference": "43da808391da3540d44a8dfeb4e46da4ad8f5723", "shasum": "" }, "require": { @@ -6329,7 +6294,7 @@ "league/flysystem-sftp-v3": "^3.0", "mockery/mockery": "^1.5.1", "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^8.18", + "orchestra/testbench-core": "^8.15.1", "pda/pheanstalk": "^4.0", "phpstan/phpstan": "^1.4.7", "phpunit/phpunit": "^10.0.7", @@ -6418,20 +6383,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-12-27T14:26:28+00:00" + "time": "2023-12-22T14:39:10+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.14", + "version": "v0.1.13", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "2219fa9c4b944add1e825c3bdb8ecae8bc503bc6" + "reference": "e1379d8ead15edd6cc4369c22274345982edc95a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/2219fa9c4b944add1e825c3bdb8ecae8bc503bc6", - "reference": "2219fa9c4b944add1e825c3bdb8ecae8bc503bc6", + "url": "https://api.github.com/repos/laravel/prompts/zipball/e1379d8ead15edd6cc4369c22274345982edc95a", + "reference": "e1379d8ead15edd6cc4369c22274345982edc95a", "shasum": "" }, "require": { @@ -6447,7 +6412,7 @@ "require-dev": { "mockery/mockery": "^1.5", "pestphp/pest": "^2.3", - "phpstan/phpstan": "^1.11", + "phpstan/phpstan": "^1.10", "phpstan/phpstan-mockery": "^1.1" }, "suggest": { @@ -6473,22 +6438,22 @@ ], "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.14" + "source": "https://github.com/laravel/prompts/tree/v0.1.13" }, - "time": "2023-12-27T04:18:09+00:00" + "time": "2023-10-27T13:53:59+00:00" }, { "name": "laravel/sanctum", - "version": "v3.3.3", + "version": "v3.3.2", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5" + "reference": "e1a272893bec13cf135627f7e156030b3afe1e60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/8c104366459739f3ada0e994bcd3e6fd681ce3d5", - "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/e1a272893bec13cf135627f7e156030b3afe1e60", + "reference": "e1a272893bec13cf135627f7e156030b3afe1e60", "shasum": "" }, "require": { @@ -6541,7 +6506,7 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2023-12-19T18:44:48+00:00" + "time": "2023-11-03T13:42:14+00:00" }, { "name": "laravel/scout", @@ -12949,16 +12914,16 @@ }, { "name": "spatie/temporary-directory", - "version": "2.2.1", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/spatie/temporary-directory.git", - "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a" + "reference": "efc258c9f4da28f0c7661765b8393e4ccee3d19c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", - "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/efc258c9f4da28f0c7661765b8393e4ccee3d19c", + "reference": "efc258c9f4da28f0c7661765b8393e4ccee3d19c", "shasum": "" }, "require": { @@ -12994,7 +12959,7 @@ ], "support": { "issues": "https://github.com/spatie/temporary-directory/issues", - "source": "https://github.com/spatie/temporary-directory/tree/2.2.1" + "source": "https://github.com/spatie/temporary-directory/tree/2.2.0" }, "funding": [ { @@ -13006,7 +12971,7 @@ "type": "github" } ], - "time": "2023-12-25T11:46:58+00:00" + "time": "2023-09-25T07:13:36+00:00" }, { "name": "sqids/sqids", @@ -15521,21 +15486,21 @@ }, { "name": "symfony/service-contracts", - "version": "v3.4.1", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "psr/container": "^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -15583,7 +15548,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" }, "funding": [ { @@ -15599,7 +15564,7 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2023-07-30T20:28:31+00:00" }, { "name": "symfony/string", @@ -15784,16 +15749,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v3.4.1", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "06450585bf65e978026bda220cdebca3f867fde7" + "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", - "reference": "06450585bf65e978026bda220cdebca3f867fde7", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", "shasum": "" }, "require": { @@ -15842,7 +15807,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" }, "funding": [ { @@ -15858,7 +15823,7 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2023-07-25T15:08:44+00:00" }, { "name": "symfony/uid", @@ -17183,16 +17148,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.43.0", + "version": "v3.41.1", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "39b5632c39ca9deb4eb7e670ba96fcf5c3a72e3c" + "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/39b5632c39ca9deb4eb7e670ba96fcf5c3a72e3c", - "reference": "39b5632c39ca9deb4eb7e670ba96fcf5c3a72e3c", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8b6ae8dcbaf23f09680643ab832a4a3a260265f6", + "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6", "shasum": "" }, "require": { @@ -17222,7 +17187,8 @@ "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", - "phpunit/phpunit": "^9.6 || ^10.5.5", + "phpunit/phpunit": "^9.6", + "symfony/phpunit-bridge": "^6.3.8 || ^7.0", "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { @@ -17261,7 +17227,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.43.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.41.1" }, "funding": [ { @@ -17269,7 +17235,7 @@ "type": "github" } ], - "time": "2023-12-28T17:36:39+00:00" + "time": "2023-12-10T19:59:27+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -17787,36 +17753,36 @@ }, { "name": "pestphp/pest", - "version": "v2.30.0", + "version": "v2.28.1", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "97dc32f9d24b84dd071d9e89438a19e43c833f6f" + "reference": "9ee41910201ef8fc5f5b6d1390e5ec4558222927" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/97dc32f9d24b84dd071d9e89438a19e43c833f6f", - "reference": "97dc32f9d24b84dd071d9e89438a19e43c833f6f", + "url": "https://api.github.com/repos/pestphp/pest/zipball/9ee41910201ef8fc5f5b6d1390e5ec4558222927", + "reference": "9ee41910201ef8fc5f5b6d1390e5ec4558222927", "shasum": "" }, "require": { "brianium/paratest": "^7.3.1", - "nunomaduro/collision": "^7.10.0|^8.0.1", + "nunomaduro/collision": "^7.10.0|^8.0.0", "nunomaduro/termwind": "^1.15.1|^2.0.0", "pestphp/pest-plugin": "^2.1.1", "pestphp/pest-plugin-arch": "^2.5.0", "php": "^8.1.0", - "phpunit/phpunit": "^10.5.5" + "phpunit/phpunit": "^10.5.3" }, "conflict": { - "phpunit/phpunit": ">10.5.5", + "phpunit/phpunit": ">10.5.3", "sebastian/exporter": "<5.1.0", "webmozart/assert": "<1.11.0" }, "require-dev": { "pestphp/pest-dev-tools": "^2.16.0", - "pestphp/pest-plugin-type-coverage": "^2.6.0", - "symfony/process": "^6.4.0|^7.0.0" + "pestphp/pest-plugin-type-coverage": "^2.5.0", + "symfony/process": "^6.4.0|^7.0.1" }, "bin": [ "bin/pest" @@ -17879,7 +17845,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v2.30.0" + "source": "https://github.com/pestphp/pest/tree/v2.28.1" }, "funding": [ { @@ -17891,7 +17857,7 @@ "type": "github" } ], - "time": "2023-12-28T10:36:40+00:00" + "time": "2023-12-15T11:42:34+00:00" }, { "name": "pestphp/pest-plugin", @@ -18874,16 +18840,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.5", + "version": "10.5.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856" + "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ed21115d505b4b4f7dc7b5651464e19a2c7f7856", - "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6fce887c71076a73f32fd3e0774a6833fc5c7f19", + "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19", "shasum": "" }, "require": { @@ -18955,7 +18921,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.3" }, "funding": [ { @@ -18971,7 +18937,7 @@ "type": "tidelift" } ], - "time": "2023-12-27T15:13:52+00:00" + "time": "2023-12-13T07:25:23+00:00" }, { "name": "pimple/pimple", From e268d4f22699eecd63ad1ad1517c0432a2ec68d4 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 20:19:33 -0500 Subject: [PATCH 100/152] Make null safe Signed-off-by: Kevin Ullyott --- .../src/Filament/Resources/EventResource/Pages/EditEvent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index cda81e3d39..11ca44ef15 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -126,7 +126,7 @@ public function form(Form $form): Form $this->fieldBuilder(), ]) ->hidden(fn (Get $get) => $get('is_wizard')) - ->disabled(fn (?EventRegistrationForm $record) => $record->submissions()->exists()), + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), Repeater::make('steps') ->schema([ TextInput::make('label') From dc668f8b145a1dfa7242d3ef20f86cfd9f290f36 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 20:25:48 -0500 Subject: [PATCH 101/152] Fix double hydration issue Signed-off-by: Kevin Ullyott --- .../EventResource/Pages/EditEvent.php | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index 11ca44ef15..f0c0e8a8f9 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -69,6 +69,8 @@ class EditEvent extends EditRecord { protected static string $resource = EventResource::class; + protected bool $contentHydrated = false; + public function form(Form $form): Form { /** @var User $user */ @@ -189,7 +191,26 @@ public function fieldBuilder(): TiptapEditor }) ->dehydrated(false) ->columnSpanFull() - ->extraInputAttributes(['style' => 'min-height: 12rem;']); + ->extraInputAttributes(['style' => 'min-height: 12rem;']) + ->afterStateHydrated(function (TiptapEditor $component, string | array | null $state): void { + // TODO: This is a temporary fix until we can figure out whey this gets hydrated twice. + + if (! $state || $this->contentHydrated) { + return; + } + + if (! is_array($state)) { + $state = tiptap_converter()->asJSON($state, decoded: true); + } + + ray('here2'); + + $state = $component->renderBlockPreviews($state, $component); + + $component->state($state); + + $this->contentHydrated = true; + }); } public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array From 6ef9777e700663690c6e10034707f5547ce0a087 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 27 Dec 2023 22:48:40 -0500 Subject: [PATCH 102/152] FIx some bugs with submissions Signed-off-by: Kevin Ullyott --- .../Actions/GenerateSubmissibleEmbedCode.php | 3 +- app-modules/form/src/Models/Submission.php | 2 +- .../render-event-registration-form.blade.php | 2 +- app-modules/meeting-center/routes/api.php | 12 +-- app-modules/meeting-center/routes/web.php | 2 +- .../EventResource/Pages/ViewEvent.php | 6 ++ .../EventRegistrationWidgetController.php | 30 +++++--- ...istrationFormIsEmbeddableAndAuthorized.php | 75 +++++++++++++++++++ .../Livewire/RenderEventRegistrationForm.php | 6 +- .../EventRegistrationFormSubmission.php | 5 ++ ...icateEventRegistrationFormNotification.php | 2 +- app/Http/Middleware/VerifyCsrfToken.php | 1 + 12 files changed, 121 insertions(+), 25 deletions(-) create mode 100644 app-modules/meeting-center/src/Http/Middleware/EnsureEventRegistrationFormIsEmbeddableAndAuthorized.php diff --git a/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php b/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php index ea28b94f01..339d06623d 100644 --- a/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php +++ b/app-modules/form/src/Actions/GenerateSubmissibleEmbedCode.php @@ -77,8 +77,9 @@ public function handle(Submissible $submissible): string EOD; })(), EventRegistrationForm::class => (function () use ($submissible) { + /** @var EventRegistrationForm $submissible */ $scriptUrl = url('js/widgets/events/advising-app-event-registration-form-widget.js?'); - $formDefinitionUrl = URL::signedRoute('event-registration.define', ['form' => $submissible]); + $formDefinitionUrl = URL::signedRoute('event-registration.define', ['event' => $submissible->event]); return << diff --git a/app-modules/form/src/Models/Submission.php b/app-modules/form/src/Models/Submission.php index aa948d8ca1..0816268c2e 100644 --- a/app-modules/form/src/Models/Submission.php +++ b/app-modules/form/src/Models/Submission.php @@ -55,7 +55,7 @@ abstract public function submissible(): BelongsTo; abstract public function fields(): BelongsToMany; - public function author(): MorphTo + public function author(): MorphTo|BelongsTo { return $this ->morphTo('author'); diff --git a/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php b/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php index 26a5435918..e6e327ca9d 100644 --- a/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php +++ b/app-modules/meeting-center/resources/views/livewire/render-event-registration-form.blade.php @@ -37,6 +37,6 @@
- {!! resolve(GenerateSubmissibleEmbedCode::class)->handle($this->eventRegistrationForm) !!} + {!! resolve(GenerateSubmissibleEmbedCode::class)->handle($this->event->eventRegistrationForm) !!}
diff --git a/app-modules/meeting-center/routes/api.php b/app-modules/meeting-center/routes/api.php index 13aa9a6000..1bb564f34d 100644 --- a/app-modules/meeting-center/routes/api.php +++ b/app-modules/meeting-center/routes/api.php @@ -34,28 +34,28 @@ */ -use AdvisingApp\Form\Http\Middleware\EnsureSubmissibleIsEmbeddableAndAuthorized; use AdvisingApp\MeetingCenter\Http\Controllers\EventRegistrationWidgetController; +use AdvisingApp\MeetingCenter\Http\Middleware\EnsureEventRegistrationFormIsEmbeddableAndAuthorized; Route::prefix('api') ->middleware([ 'api', - EnsureSubmissibleIsEmbeddableAndAuthorized::class . ':form', + EnsureEventRegistrationFormIsEmbeddableAndAuthorized::class . ':event', ]) ->group(function () { Route::prefix('event-registration') ->name('event-registration.') ->group(function () { - Route::get('/{form}', [EventRegistrationWidgetController::class, 'view']) + Route::get('/{event}', [EventRegistrationWidgetController::class, 'view']) ->middleware(['signed']) ->name('define'); - Route::post('/{form}/authenticate/request', [EventRegistrationWidgetController::class, 'requestAuthentication']) + Route::post('/{event}/authenticate/request', [EventRegistrationWidgetController::class, 'requestAuthentication']) ->middleware(['signed']) ->name('request-authentication'); - Route::post('/{form}/authenticate/{authentication}', [EventRegistrationWidgetController::class, 'authenticate']) + Route::post('/{event}/authenticate/{authentication}', [EventRegistrationWidgetController::class, 'authenticate']) ->middleware(['signed']) ->name('authenticate'); - Route::post('/{form}/submit', [EventRegistrationWidgetController::class, 'store']) + Route::post('/{event}/submit', [EventRegistrationWidgetController::class, 'store']) ->middleware(['signed']) ->name('submit'); }); diff --git a/app-modules/meeting-center/routes/web.php b/app-modules/meeting-center/routes/web.php index d1b6d06442..b5951e3f04 100644 --- a/app-modules/meeting-center/routes/web.php +++ b/app-modules/meeting-center/routes/web.php @@ -51,6 +51,6 @@ ->prefix('event-registration') ->name('event-registration.') ->group(function () { - Route::get('/{eventRegistrationForm}/respond', RenderEventRegistrationForm::class) + Route::get('/{event}/respond', RenderEventRegistrationForm::class) ->name('show'); }); diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ViewEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ViewEvent.php index 06d58a2b7f..be813c72a9 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ViewEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ViewEvent.php @@ -36,11 +36,13 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; +use Filament\Actions\Action; use Filament\Actions\EditAction; use Filament\Infolists\Infolist; use Filament\Actions\DeleteAction; use Filament\Resources\Pages\ViewRecord; use Filament\Infolists\Components\Section; +use AdvisingApp\MeetingCenter\Models\Event; use Filament\Infolists\Components\TextEntry; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; @@ -68,6 +70,10 @@ public function infolist(Infolist $infolist): Infolist protected function getHeaderActions(): array { return [ + Action::make('view') + ->url(fn (Event $event) => route('event-registration.show', ['event' => $event])) + ->icon('heroicon-m-arrow-top-right-on-square') + ->openUrlInNewTab(), EditAction::make(), DeleteAction::make(), ]; diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index 3bd79a987d..d542a26ad2 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -45,30 +45,33 @@ use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; +use AdvisingApp\MeetingCenter\Models\Event; use Illuminate\Support\Facades\Notification; use Symfony\Component\HttpFoundation\Response; use AdvisingApp\Form\Actions\GenerateFormKitSchema; use AdvisingApp\MeetingCenter\Models\EventAttendee; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; -use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; -use AdvisingApp\Form\Actions\ResolveSubmissionAuthorFromEmail; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; -use AdvisingApp\Form\Notifications\AuthenticateEventRegistrationFormNotification; +use AdvisingApp\MeetingCenter\Notifications\AuthenticateEventRegistrationFormNotification; class EventRegistrationWidgetController extends Controller { - public function view(GenerateFormKitSchema $generateSchema, EventRegistrationForm $form): JsonResponse + public function view(GenerateFormKitSchema $generateSchema, Event $event): JsonResponse { + $form = $event->eventRegistrationForm; + + ray($event, $form); + return response()->json( [ 'name' => $form->event->title, 'description' => $form->event->description, // TODO: Maybe get rid of this? It would never not be authenticated. 'is_authenticated' => true, - 'authentication_url' => URL::signedRoute('event-registration.request-authentication', ['form' => $form]), + 'authentication_url' => URL::signedRoute('event-registration.request-authentication', ['event' => $event]), 'recaptcha_enabled' => $form->recaptcha_enabled, ...($form->recaptcha_enabled ? [ 'recaptcha_site_key' => app(GoogleRecaptchaSettings::class)->site_key, @@ -80,8 +83,10 @@ public function view(GenerateFormKitSchema $generateSchema, EventRegistrationFor ); } - public function requestAuthentication(Request $request, EventRegistrationForm $form): JsonResponse + public function requestAuthentication(Request $request, Event $event): JsonResponse { + $form = $event->eventRegistrationForm; + $data = $request->validate([ 'email' => ['required', 'email'], ]); @@ -113,13 +118,13 @@ public function requestAuthentication(Request $request, EventRegistrationForm $f return response()->json([ 'message' => "We've sent an authentication code to {$attendee->email}.", 'authentication_url' => URL::signedRoute('event-registration.authenticate', [ - 'form' => $form, + 'event' => $event, 'authentication' => $authentication, ]), ]); } - public function authenticate(Request $request, EventRegistrationForm $form, EventRegistrationFormAuthentication $authentication): JsonResponse + public function authenticate(Request $request, Event $event, EventRegistrationFormAuthentication $authentication): JsonResponse { if ($authentication->isExpired()) { return response()->json([ @@ -140,7 +145,7 @@ public function authenticate(Request $request, EventRegistrationForm $form, Even return response()->json([ 'submission_url' => URL::signedRoute('event-registration.submit', [ 'authentication' => $authentication, - 'form' => $authentication->submissible, + 'event' => $authentication->submissible->event, ]), ]); } @@ -148,9 +153,10 @@ public function authenticate(Request $request, EventRegistrationForm $form, Even public function store( Request $request, GenerateSubmissibleValidation $generateValidation, - ResolveSubmissionAuthorFromEmail $resolveSubmissionAuthorFromEmail, - EventRegistrationForm $form, + Event $event, ): JsonResponse { + $form = $event->eventRegistrationForm; + $authentication = $request->query('authentication'); if (filled($authentication)) { @@ -168,6 +174,8 @@ public function store( $generateValidation($form) ); + ray($validator->errors()); + if ($validator->fails()) { return response()->json( [ diff --git a/app-modules/meeting-center/src/Http/Middleware/EnsureEventRegistrationFormIsEmbeddableAndAuthorized.php b/app-modules/meeting-center/src/Http/Middleware/EnsureEventRegistrationFormIsEmbeddableAndAuthorized.php new file mode 100644 index 0000000000..5d041e18ae --- /dev/null +++ b/app-modules/meeting-center/src/Http/Middleware/EnsureEventRegistrationFormIsEmbeddableAndAuthorized.php @@ -0,0 +1,75 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Http\Middleware; + +use Closure; +use Illuminate\Http\Request; +use AdvisingApp\MeetingCenter\Models\Event; +use Symfony\Component\HttpFoundation\Response; + +class EnsureEventRegistrationFormIsEmbeddableAndAuthorized +{ + public function handle(Request $request, Closure $next, string $binding): Response + { + /** @var Event $event */ + $event = $request->route($binding); + + $submissible = $event->eventRegistrationForm; + + $referer = $request->headers->get('referer'); + + if (! $referer) { + return response()->json(['error' => 'Missing referer header.'], 400); + } + + $referer = parse_url($referer)['host']; + + if ($referer != parse_url(config('app.url'))['host']) { + if (! $submissible->embed_enabled) { + return response()->json(['error' => 'Embedding is not enabled for this form.'], 403); + } + + $allowedDomains = collect($submissible->allowed_domains ?? []); + + if (! $allowedDomains->contains($referer)) { + return response()->json(['error' => 'Referer not allowed. Domain must be added to allowed domains list'], 403); + } + } + + return $next($request); + } +} diff --git a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php index 60dc4d9cdf..5a77647953 100644 --- a/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php +++ b/app-modules/meeting-center/src/Livewire/RenderEventRegistrationForm.php @@ -39,8 +39,8 @@ use Livewire\Component; use Illuminate\Contracts\View\View; use Filament\Forms\Contracts\HasForms; +use AdvisingApp\MeetingCenter\Models\Event; use Filament\Forms\Concerns\InteractsWithForms; -use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; class RenderEventRegistrationForm extends Component implements HasForms { @@ -48,13 +48,13 @@ class RenderEventRegistrationForm extends Component implements HasForms public bool $show = true; - public EventRegistrationForm $eventRegistrationForm; + public Event $event; public ?array $data = []; public function render(): View { return view('meeting-center::livewire.render-event-registration-form') - ->title("{$this->eventRegistrationForm->event->title} Registration"); + ->title("{$this->event->title} Registration"); } } diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php index 4a1392f1ae..35fdd58213 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php @@ -85,6 +85,11 @@ public function fields(): BelongsToMany ->withPivot(['id', 'response']); } + public function author(): BelongsTo + { + return $this->belongsTo(EventAttendee::class, 'event_attendee_id'); + } + public function deliverRequest(): void { $this->request_method->deliver($this); diff --git a/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php b/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php index 6719016200..09efa9ae1b 100644 --- a/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php +++ b/app-modules/meeting-center/src/Notifications/AuthenticateEventRegistrationFormNotification.php @@ -34,7 +34,7 @@ */ -namespace AdvisingApp\Form\Notifications; +namespace AdvisingApp\MeetingCenter\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 88dddf1747..660c731b42 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -49,6 +49,7 @@ class VerifyCsrfToken extends Middleware '/api/forms/*', '/api/applications/*', '/api/surveys/*', + '/api/event-registration/*', '/graphql/*', ]; } From 08b83cf4d478993dec70dec94d740dbc3c9ccdaf Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 09:45:12 -0500 Subject: [PATCH 103/152] Fix relationship saving Signed-off-by: Kevin Ullyott --- .../EventResource/Pages/EditEvent.php | 26 ++++++++++++++++--- .../src/Models/EventRegistrationForm.php | 3 +++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index f0c0e8a8f9..72eda35866 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -52,6 +52,7 @@ use Filament\Forms\Components\Fieldset; use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\Component; use Filament\Forms\Components\TagsInput; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; @@ -64,6 +65,7 @@ use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; +use Filament\Forms\Components\Contracts\CanEntangleWithSingularRelationships; class EditEvent extends EditRecord { @@ -98,6 +100,24 @@ public function form(Form $form): Form ->required(), Fieldset::make('Registration Form') ->relationship('eventRegistrationForm') + ->saveRelationshipsBeforeChildrenUsing(static function (Component | CanEntangleWithSingularRelationships $component): void { + $component->getCachedExistingRecord()?->delete(); + + $relationship = $component->getRelationship(); + + $data = $component->getChildComponentContainer()->getState(shouldCallHooksBefore: false); + $data = $component->mutateRelationshipDataBeforeCreate($data); + + $relatedModel = $component->getRelatedModel(); + + $record = new $relatedModel(); + $record->fill($data); + + $relationship->save($record); + + $component->cachedExistingRecord($record); + }) + ->saveRelationshipsUsing(null) ->schema([ Grid::make() ->schema([ @@ -203,8 +223,6 @@ public function fieldBuilder(): TiptapEditor $state = tiptap_converter()->asJSON($state, decoded: true); } - ray('here2'); - $state = $component->renderBlockPreviews($state, $component); $component->state($state); @@ -275,14 +293,14 @@ protected function clearFormContentForWizard(): void $form = $event->eventRegistrationForm; - if ($form->is_wizard) { + if ($form?->is_wizard) { $form->content = null; $form->save(); return; } - $form->steps()->delete(); + $form?->steps()->delete(); } protected function getHeaderActions(): array diff --git a/app-modules/meeting-center/src/Models/EventRegistrationForm.php b/app-modules/meeting-center/src/Models/EventRegistrationForm.php index e8ed9f9aa2..66dda93cad 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationForm.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationForm.php @@ -38,6 +38,7 @@ use AdvisingApp\Form\Enums\Rounding; use AdvisingApp\Form\Models\Submissible; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -46,6 +47,8 @@ */ class EventRegistrationForm extends Submissible { + use SoftDeletes; + protected $fillable = [ 'form_id', 'embed_enabled', From 01fc3389e8352410c77184cbdebda95456a715cd Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 10:58:26 -0500 Subject: [PATCH 104/152] Upgrade filament and remove hydration fix Signed-off-by: Kevin Ullyott --- .../EventResource/Pages/EditEvent.php | 21 +- composer.lock | 237 +++++++++--------- 2 files changed, 119 insertions(+), 139 deletions(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index 72eda35866..aa11585866 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -71,8 +71,6 @@ class EditEvent extends EditRecord { protected static string $resource = EventResource::class; - protected bool $contentHydrated = false; - public function form(Form $form): Form { /** @var User $user */ @@ -211,24 +209,7 @@ public function fieldBuilder(): TiptapEditor }) ->dehydrated(false) ->columnSpanFull() - ->extraInputAttributes(['style' => 'min-height: 12rem;']) - ->afterStateHydrated(function (TiptapEditor $component, string | array | null $state): void { - // TODO: This is a temporary fix until we can figure out whey this gets hydrated twice. - - if (! $state || $this->contentHydrated) { - return; - } - - if (! is_array($state)) { - $state = tiptap_converter()->asJSON($state, decoded: true); - } - - $state = $component->renderBlockPreviews($state, $component); - - $component->state($state); - - $this->contentHydrated = true; - }); + ->extraInputAttributes(['style' => 'min-height: 12rem;']); } public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array diff --git a/composer.lock b/composer.lock index 2377067c69..029ba3e12f 100644 --- a/composer.lock +++ b/composer.lock @@ -755,16 +755,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.294.5", + "version": "3.295.2", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "2e34d45e970c77775e4c298e08732d64b647c41c" + "reference": "7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2e34d45e970c77775e4c298e08732d64b647c41c", - "reference": "2e34d45e970c77775e4c298e08732d64b647c41c", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73", + "reference": "7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73", "shasum": "" }, "require": { @@ -844,9 +844,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.294.5" + "source": "https://github.com/aws/aws-sdk-php/tree/3.295.2" }, - "time": "2023-12-21T19:10:21+00:00" + "time": "2023-12-27T19:06:10+00:00" }, { "name": "barryvdh/laravel-debugbar", @@ -4071,16 +4071,16 @@ }, { "name": "filament/actions", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "be3a8c110aa69f3f4856816eefd477b600bc06e2" + "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/be3a8c110aa69f3f4856816eefd477b600bc06e2", - "reference": "be3a8c110aa69f3f4856816eefd477b600bc06e2", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/8f2a3df7c607a24c2433a3a71cb27b20a8dea203", + "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203", "shasum": "" }, "require": { @@ -4118,20 +4118,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-21T12:38:03+00:00" + "time": "2023-12-28T15:54:29+00:00" }, { "name": "filament/filament", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "e1aa070483c2eaa5bb92ce8d959779a9558fe022" + "reference": "ae12dc49094560188a4289778a54773045880e44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/e1aa070483c2eaa5bb92ce8d959779a9558fe022", - "reference": "e1aa070483c2eaa5bb92ce8d959779a9558fe022", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/ae12dc49094560188a4289778a54773045880e44", + "reference": "ae12dc49094560188a4289778a54773045880e44", "shasum": "" }, "require": { @@ -4183,20 +4183,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:15+00:00" + "time": "2023-12-28T15:54:35+00:00" }, { "name": "filament/forms", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "673689bd958797b05127fe9956eafeed555b91bd" + "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/673689bd958797b05127fe9956eafeed555b91bd", - "reference": "673689bd958797b05127fe9956eafeed555b91bd", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/26e177a4b3a8ef7b8326d992bb5073f02220a506", + "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506", "shasum": "" }, "require": { @@ -4239,20 +4239,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:00+00:00" + "time": "2023-12-28T15:54:30+00:00" }, { "name": "filament/infolists", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", - "reference": "9207c2b83ba9c8dcbcac9a930e93ce87f381d780" + "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/infolists/zipball/9207c2b83ba9c8dcbcac9a930e93ce87f381d780", - "reference": "9207c2b83ba9c8dcbcac9a930e93ce87f381d780", + "url": "https://api.github.com/repos/filamentphp/infolists/zipball/66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", + "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", "shasum": "" }, "require": { @@ -4290,20 +4290,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:00+00:00" + "time": "2023-12-26T22:39:20+00:00" }, { "name": "filament/notifications", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", - "reference": "5b9255c0793751534461cace12febdc0d4cc05bb" + "reference": "4f5634f9df312050efa3a035c543add6cec0e3a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/notifications/zipball/5b9255c0793751534461cace12febdc0d4cc05bb", - "reference": "5b9255c0793751534461cace12febdc0d4cc05bb", + "url": "https://api.github.com/repos/filamentphp/notifications/zipball/4f5634f9df312050efa3a035c543add6cec0e3a2", + "reference": "4f5634f9df312050efa3a035c543add6cec0e3a2", "shasum": "" }, "require": { @@ -4342,11 +4342,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-17T22:25:42+00:00" + "time": "2023-12-28T15:54:27+00:00" }, { "name": "filament/spatie-laravel-media-library-plugin", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-media-library-plugin.git", @@ -4383,16 +4383,16 @@ }, { "name": "filament/spatie-laravel-settings-plugin", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-settings-plugin.git", - "reference": "7119f3f714dfa0ce098cd90aa2a741147a5508f6" + "reference": "d26f397a845934462d511432ba88363f63a7e203" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/spatie-laravel-settings-plugin/zipball/7119f3f714dfa0ce098cd90aa2a741147a5508f6", - "reference": "7119f3f714dfa0ce098cd90aa2a741147a5508f6", + "url": "https://api.github.com/repos/filamentphp/spatie-laravel-settings-plugin/zipball/d26f397a845934462d511432ba88363f63a7e203", + "reference": "d26f397a845934462d511432ba88363f63a7e203", "shasum": "" }, "require": { @@ -4426,20 +4426,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-19T13:24:28+00:00" + "time": "2023-12-26T22:39:37+00:00" }, { "name": "filament/support", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd" + "reference": "97792dad038a87b7a6bfe465c4f1913252c99017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd", - "reference": "f00f44dd79e8e1b3f92dea6e2ef6e1ba9e5396dd", + "url": "https://api.github.com/repos/filamentphp/support/zipball/97792dad038a87b7a6bfe465c4f1913252c99017", + "reference": "97792dad038a87b7a6bfe465c4f1913252c99017", "shasum": "" }, "require": { @@ -4483,20 +4483,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:21+00:00" + "time": "2023-12-24T21:16:58+00:00" }, { "name": "filament/tables", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "3391bd1015bdde8e454d0a6391952dc131fb8dad" + "reference": "ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/3391bd1015bdde8e454d0a6391952dc131fb8dad", - "reference": "3391bd1015bdde8e454d0a6391952dc131fb8dad", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67", + "reference": "ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67", "shasum": "" }, "require": { @@ -4536,20 +4536,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-22T14:36:23+00:00" + "time": "2023-12-28T15:54:29+00:00" }, { "name": "filament/widgets", - "version": "v3.1.27", + "version": "v3.1.30", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "290184b9dfb99436df94a9a0b8511b21811d9e64" + "reference": "7195d2fe7d12a9b9595fa445a4dbedd6d7714836" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/290184b9dfb99436df94a9a0b8511b21811d9e64", - "reference": "290184b9dfb99436df94a9a0b8511b21811d9e64", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/7195d2fe7d12a9b9595fa445a4dbedd6d7714836", + "reference": "7195d2fe7d12a9b9595fa445a4dbedd6d7714836", "shasum": "" }, "require": { @@ -4580,7 +4580,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-17T22:26:03+00:00" + "time": "2023-12-24T21:17:06+00:00" }, { "name": "firebase/php-jwt", @@ -5154,16 +5154,16 @@ }, { "name": "google/apiclient-services", - "version": "v0.328.0", + "version": "v0.329.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d" + "reference": "3216fd1b6ba33c5f6658c3581e9723ff21d9acb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d", - "reference": "211ba786d30a4ab21e012d2b7dbefc49b4fc6a3d", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/3216fd1b6ba33c5f6658c3581e9723ff21d9acb7", + "reference": "3216fd1b6ba33c5f6658c3581e9723ff21d9acb7", "shasum": "" }, "require": { @@ -5192,9 +5192,9 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.328.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.329.0" }, - "time": "2023-12-18T01:00:18+00:00" + "time": "2023-12-24T01:02:15+00:00" }, { "name": "google/auth", @@ -6182,16 +6182,16 @@ }, { "name": "laravel/framework", - "version": "v10.38.2", + "version": "v10.39.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "43da808391da3540d44a8dfeb4e46da4ad8f5723" + "reference": "114926b07bfb5fbf2545c03aa2ce5c8c37be650c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/43da808391da3540d44a8dfeb4e46da4ad8f5723", - "reference": "43da808391da3540d44a8dfeb4e46da4ad8f5723", + "url": "https://api.github.com/repos/laravel/framework/zipball/114926b07bfb5fbf2545c03aa2ce5c8c37be650c", + "reference": "114926b07bfb5fbf2545c03aa2ce5c8c37be650c", "shasum": "" }, "require": { @@ -6294,7 +6294,7 @@ "league/flysystem-sftp-v3": "^3.0", "mockery/mockery": "^1.5.1", "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^8.15.1", + "orchestra/testbench-core": "^8.18", "pda/pheanstalk": "^4.0", "phpstan/phpstan": "^1.4.7", "phpunit/phpunit": "^10.0.7", @@ -6383,20 +6383,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-12-22T14:39:10+00:00" + "time": "2023-12-27T14:26:28+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.13", + "version": "v0.1.14", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "e1379d8ead15edd6cc4369c22274345982edc95a" + "reference": "2219fa9c4b944add1e825c3bdb8ecae8bc503bc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/e1379d8ead15edd6cc4369c22274345982edc95a", - "reference": "e1379d8ead15edd6cc4369c22274345982edc95a", + "url": "https://api.github.com/repos/laravel/prompts/zipball/2219fa9c4b944add1e825c3bdb8ecae8bc503bc6", + "reference": "2219fa9c4b944add1e825c3bdb8ecae8bc503bc6", "shasum": "" }, "require": { @@ -6412,7 +6412,7 @@ "require-dev": { "mockery/mockery": "^1.5", "pestphp/pest": "^2.3", - "phpstan/phpstan": "^1.10", + "phpstan/phpstan": "^1.11", "phpstan/phpstan-mockery": "^1.1" }, "suggest": { @@ -6438,22 +6438,22 @@ ], "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.13" + "source": "https://github.com/laravel/prompts/tree/v0.1.14" }, - "time": "2023-10-27T13:53:59+00:00" + "time": "2023-12-27T04:18:09+00:00" }, { "name": "laravel/sanctum", - "version": "v3.3.2", + "version": "v3.3.3", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "e1a272893bec13cf135627f7e156030b3afe1e60" + "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/e1a272893bec13cf135627f7e156030b3afe1e60", - "reference": "e1a272893bec13cf135627f7e156030b3afe1e60", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/8c104366459739f3ada0e994bcd3e6fd681ce3d5", + "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5", "shasum": "" }, "require": { @@ -6506,7 +6506,7 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2023-11-03T13:42:14+00:00" + "time": "2023-12-19T18:44:48+00:00" }, { "name": "laravel/scout", @@ -12914,16 +12914,16 @@ }, { "name": "spatie/temporary-directory", - "version": "2.2.0", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/spatie/temporary-directory.git", - "reference": "efc258c9f4da28f0c7661765b8393e4ccee3d19c" + "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/efc258c9f4da28f0c7661765b8393e4ccee3d19c", - "reference": "efc258c9f4da28f0c7661765b8393e4ccee3d19c", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", + "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", "shasum": "" }, "require": { @@ -12959,7 +12959,7 @@ ], "support": { "issues": "https://github.com/spatie/temporary-directory/issues", - "source": "https://github.com/spatie/temporary-directory/tree/2.2.0" + "source": "https://github.com/spatie/temporary-directory/tree/2.2.1" }, "funding": [ { @@ -12971,7 +12971,7 @@ "type": "github" } ], - "time": "2023-09-25T07:13:36+00:00" + "time": "2023-12-25T11:46:58+00:00" }, { "name": "sqids/sqids", @@ -15486,21 +15486,21 @@ }, { "name": "symfony/service-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -15548,7 +15548,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -15564,7 +15564,7 @@ "type": "tidelift" } ], - "time": "2023-07-30T20:28:31+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/string", @@ -15749,16 +15749,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" + "reference": "06450585bf65e978026bda220cdebca3f867fde7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", + "reference": "06450585bf65e978026bda220cdebca3f867fde7", "shasum": "" }, "require": { @@ -15807,7 +15807,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" }, "funding": [ { @@ -15823,7 +15823,7 @@ "type": "tidelift" } ], - "time": "2023-07-25T15:08:44+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/uid", @@ -17148,16 +17148,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.41.1", + "version": "v3.42.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6" + "reference": "632ef1be3447a9b890bef06147475facee535d0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8b6ae8dcbaf23f09680643ab832a4a3a260265f6", - "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/632ef1be3447a9b890bef06147475facee535d0f", + "reference": "632ef1be3447a9b890bef06147475facee535d0f", "shasum": "" }, "require": { @@ -17188,7 +17188,6 @@ "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", "phpunit/phpunit": "^9.6", - "symfony/phpunit-bridge": "^6.3.8 || ^7.0", "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { @@ -17227,7 +17226,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.41.1" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.42.0" }, "funding": [ { @@ -17235,7 +17234,7 @@ "type": "github" } ], - "time": "2023-12-10T19:59:27+00:00" + "time": "2023-12-24T14:38:51+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -17753,36 +17752,36 @@ }, { "name": "pestphp/pest", - "version": "v2.28.1", + "version": "v2.30.0", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "9ee41910201ef8fc5f5b6d1390e5ec4558222927" + "reference": "97dc32f9d24b84dd071d9e89438a19e43c833f6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/9ee41910201ef8fc5f5b6d1390e5ec4558222927", - "reference": "9ee41910201ef8fc5f5b6d1390e5ec4558222927", + "url": "https://api.github.com/repos/pestphp/pest/zipball/97dc32f9d24b84dd071d9e89438a19e43c833f6f", + "reference": "97dc32f9d24b84dd071d9e89438a19e43c833f6f", "shasum": "" }, "require": { "brianium/paratest": "^7.3.1", - "nunomaduro/collision": "^7.10.0|^8.0.0", + "nunomaduro/collision": "^7.10.0|^8.0.1", "nunomaduro/termwind": "^1.15.1|^2.0.0", "pestphp/pest-plugin": "^2.1.1", "pestphp/pest-plugin-arch": "^2.5.0", "php": "^8.1.0", - "phpunit/phpunit": "^10.5.3" + "phpunit/phpunit": "^10.5.5" }, "conflict": { - "phpunit/phpunit": ">10.5.3", + "phpunit/phpunit": ">10.5.5", "sebastian/exporter": "<5.1.0", "webmozart/assert": "<1.11.0" }, "require-dev": { "pestphp/pest-dev-tools": "^2.16.0", - "pestphp/pest-plugin-type-coverage": "^2.5.0", - "symfony/process": "^6.4.0|^7.0.1" + "pestphp/pest-plugin-type-coverage": "^2.6.0", + "symfony/process": "^6.4.0|^7.0.0" }, "bin": [ "bin/pest" @@ -17845,7 +17844,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v2.28.1" + "source": "https://github.com/pestphp/pest/tree/v2.30.0" }, "funding": [ { @@ -17857,7 +17856,7 @@ "type": "github" } ], - "time": "2023-12-15T11:42:34+00:00" + "time": "2023-12-28T10:36:40+00:00" }, { "name": "pestphp/pest-plugin", @@ -18840,16 +18839,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.3", + "version": "10.5.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19" + "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6fce887c71076a73f32fd3e0774a6833fc5c7f19", - "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ed21115d505b4b4f7dc7b5651464e19a2c7f7856", + "reference": "ed21115d505b4b4f7dc7b5651464e19a2c7f7856", "shasum": "" }, "require": { @@ -18921,7 +18920,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.5" }, "funding": [ { @@ -18937,7 +18936,7 @@ "type": "tidelift" } ], - "time": "2023-12-13T07:25:23+00:00" + "time": "2023-12-27T15:13:52+00:00" }, { "name": "pimple/pimple", From 98f8b4fa69c33468216f2fd05ae12bc36f471077 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 12:15:40 -0500 Subject: [PATCH 105/152] Fix issue with signed urls Signed-off-by: Kevin Ullyott --- .../src/Http/Controllers/EventRegistrationWidgetController.php | 2 -- app/Providers/AppServiceProvider.php | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index d542a26ad2..eee1f4c4a1 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -63,8 +63,6 @@ public function view(GenerateFormKitSchema $generateSchema, Event $event): JsonR { $form = $event->eventRegistrationForm; - ray($event, $form); - return response()->json( [ 'name' => $form->event->title, diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index f54cc6fd41..4483cd73a2 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -64,6 +64,7 @@ public function boot(): void if (config('app.force_https')) { URL::forceScheme('https'); + $this->app['request']->server->set('HTTPS', true); } } } From c22597505c509953ee42e86800095b7eecc0b763 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 12:29:06 -0500 Subject: [PATCH 106/152] Share event configuration between create and edit Signed-off-by: Kevin Ullyott --- .../HasSharedEventFormConfiguration.php | 245 ++++++++++++++++++ .../EventResource/Pages/CreateEvent.php | 32 +-- .../EventResource/Pages/EditEvent.php | 238 +---------------- 3 files changed, 253 insertions(+), 262 deletions(-) create mode 100644 app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php new file mode 100644 index 0000000000..f3de80786e --- /dev/null +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php @@ -0,0 +1,245 @@ +user(); + + return [ + TextInput::make('title') + ->string() + ->required(), + Textarea::make('description') + ->string() + ->nullable(), + TextInput::make('location') + ->string() + ->nullable(), + TextInput::make('capacity') + ->integer() + ->minValue(1) + ->nullable(), + DateTimePicker::make('starts_at') + ->timezone($user->timezone) + ->required(), + DateTimePicker::make('ends_at') + ->timezone($user->timezone) + ->required(), + Fieldset::make('Registration Form') + ->relationship('eventRegistrationForm') + ->saveRelationshipsBeforeChildrenUsing(static function (Component | CanEntangleWithSingularRelationships $component): void { + $component->getCachedExistingRecord()?->delete(); + + $relationship = $component->getRelationship(); + + $data = $component->getChildComponentContainer()->getState(shouldCallHooksBefore: false); + $data = $component->mutateRelationshipDataBeforeCreate($data); + + $relatedModel = $component->getRelatedModel(); + + $record = new $relatedModel(); + $record->fill($data); + + $relationship->save($record); + + $component->cachedExistingRecord($record); + }) + ->saveRelationshipsUsing(null) + ->schema([ + Grid::make() + ->schema([ + Toggle::make('embed_enabled') + ->label('Embed Enabled') + ->live() + ->helperText('If enabled, this form can be embedded on other websites.'), + TagsInput::make('allowed_domains') + ->label('Allowed Domains') + ->helperText('Only these domains will be allowed to embed this form.') + ->placeholder('example.com') + ->hidden(fn (Get $get) => ! $get('embed_enabled')) + ->disabled(fn (Get $get) => ! $get('embed_enabled')) + ->nestedRecursiveRules( + [ + 'string', + new IsDomain(), + ] + ), + ]) + ->columnSpanFull(), + Toggle::make('is_wizard') + ->label('Multi-step form') + ->live() + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), + Section::make('Fields') + ->schema([ + $this->fieldBuilder(), + ]) + ->hidden(fn (Get $get) => $get('is_wizard')) + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), + Repeater::make('steps') + ->schema([ + TextInput::make('label') + ->required() + ->string() + ->maxLength(255) + ->autocomplete(false) + ->columnSpanFull() + ->lazy(), + $this->fieldBuilder(), + ]) + ->addActionLabel('New step') + ->itemLabel(fn (array $state): ?string => $state['label'] ?? null) + ->visible(fn (Get $get) => $get('is_wizard')) + ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()) + ->relationship() + ->reorderable() + ->columnSpanFull(), + Section::make('Appearance') + ->schema([ + ColorSelect::make('primary_color'), + Select::make('rounding') + ->options(Rounding::class), + ]) + ->columns(), + ]), + ]; + } + + public function fieldBuilder(): TiptapEditor + { + return TiptapEditor::make('content') + ->output(TiptapOutput::Json) + ->blocks(FormFieldBlockRegistry::get()) + ->tools(['bold', 'italic', 'small', '|', 'heading', 'bullet-list', 'ordered-list', 'hr', '|', 'link', 'grid', 'blocks']) + ->placeholder('Drag blocks here to build your form') + ->hiddenLabel() + ->saveRelationshipsUsing(function (TiptapEditor $component, EventRegistrationForm | EventRegistrationFormStep $record) { + if ($component->isDisabled()) { + return; + } + + $form = $record instanceof EventRegistrationForm ? $record : $record->submissible; + $formStep = $record instanceof EventRegistrationFormStep ? $record : null; + + EventRegistrationFormStep::query() + ->whereBelongsTo($form, 'submissible') + ->when($formStep, fn (EloquentBuilder $query) => $query->whereBelongsTo($formStep, 'step')) + ->delete(); + + $content = $component->decodeBlocksBeforeSave($component->getJSON(decoded: true)); + $content['content'] = $this->saveFieldsFromComponents( + $form, + $content['content'] ?? [], + $formStep, + ); + + $record->content = $content; + $record->save(); + }) + ->dehydrated(false) + ->columnSpanFull() + ->extraInputAttributes(['style' => 'min-height: 12rem;']); + } + + public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array + { + foreach ($components as $componentKey => $component) { + if (array_key_exists('content', $component)) { + $components[$componentKey]['content'] = $this->saveFieldsFromComponents($form, $component['content'], $eventRegistrationFormStep); + + continue; + } + + if ($component['type'] !== 'tiptapBlock') { + continue; + } + + $componentAttributes = $component['attrs'] ?? []; + + if (array_key_exists('id', $componentAttributes)) { + $id = $componentAttributes['id'] ?? null; + unset($componentAttributes['id']); + } + + if (array_key_exists('label', $componentAttributes['data'])) { + $label = $componentAttributes['data']['label'] ?? null; + unset($componentAttributes['data']['label']); + } + + if (array_key_exists('isRequired', $componentAttributes['data'])) { + $isRequired = $componentAttributes['data']['isRequired'] ?? null; + unset($componentAttributes['data']['isRequired']); + } + + /** @var EventRegistrationFormField $field */ + $field = $form->fields()->findOrNew($id ?? null); + $field->step()->associate($eventRegistrationFormStep); + $field->label = $label ?? $componentAttributes['type']; + $field->is_required = $isRequired ?? false; + $field->type = $componentAttributes['type']; + $field->config = $componentAttributes['data']; + $field->save(); + + $components[$componentKey]['attrs']['id'] = $field->id; + } + + return $components; + } + + protected function afterCreate(): void + { + $this->clearFormContentForWizard(); + } + + protected function afterSave(): void + { + $this->clearFormContentForWizard(); + } + + protected function clearFormContentForWizard(): void + { + /** @var Event $event */ + $event = $this->record; + + $form = $event->eventRegistrationForm; + + if ($form?->is_wizard) { + $form->content = null; + $form->save(); + + return; + } + + $form?->steps()->delete(); + } +} diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/CreateEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/CreateEvent.php index 5fb7b12ea2..28a87776c3 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/CreateEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/CreateEvent.php @@ -36,43 +36,19 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; -use App\Models\User; use Filament\Forms\Form; -use Filament\Forms\Components\Textarea; -use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\CreateRecord; -use Filament\Forms\Components\DateTimePicker; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; +use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\Concerns\HasSharedEventFormConfiguration; class CreateEvent extends CreateRecord { + use HasSharedEventFormConfiguration; + protected static string $resource = EventResource::class; public function form(Form $form): Form { - /** @var User $user */ - $user = auth()->user(); - - return $form->schema([ - TextInput::make('title') - ->string() - ->required(), - Textarea::make('description') - ->string() - ->nullable(), - TextInput::make('location') - ->string() - ->nullable(), - TextInput::make('capacity') - ->integer() - ->minValue(1) - ->nullable(), - DateTimePicker::make('starts_at') - ->timezone($user->timezone) - ->required(), - DateTimePicker::make('ends_at') - ->timezone($user->timezone) - ->required(), - ]); + return $form->schema($this->fields()); } } diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index aa11585866..7e8a652fdf 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -36,252 +36,22 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; -use App\Models\User; -use Filament\Forms\Get; use Filament\Forms\Form; use Filament\Actions\ViewAction; use Filament\Actions\DeleteAction; -use Filament\Forms\Components\Grid; -use AdvisingApp\Form\Enums\Rounding; -use AdvisingApp\Form\Rules\IsDomain; -use App\Forms\Components\ColorSelect; -use Filament\Forms\Components\Select; -use Filament\Forms\Components\Toggle; -use Filament\Forms\Components\Section; -use FilamentTiptapEditor\TiptapEditor; -use Filament\Forms\Components\Fieldset; -use Filament\Forms\Components\Repeater; -use Filament\Forms\Components\Textarea; -use Filament\Forms\Components\Component; -use Filament\Forms\Components\TagsInput; -use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; -use AdvisingApp\MeetingCenter\Models\Event; -use FilamentTiptapEditor\Enums\TiptapOutput; -use Filament\Forms\Components\DateTimePicker; -use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; -use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; -use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; -use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; -use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; -use Filament\Forms\Components\Contracts\CanEntangleWithSingularRelationships; +use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\Concerns\HasSharedEventFormConfiguration; class EditEvent extends EditRecord { + use HasSharedEventFormConfiguration; + protected static string $resource = EventResource::class; public function form(Form $form): Form { - /** @var User $user */ - $user = auth()->user(); - - return $form->schema([ - TextInput::make('title') - ->string() - ->required(), - Textarea::make('description') - ->string() - ->nullable(), - TextInput::make('location') - ->string() - ->nullable(), - TextInput::make('capacity') - ->integer() - ->minValue(1) - ->nullable(), - DateTimePicker::make('starts_at') - ->timezone($user->timezone) - ->required(), - DateTimePicker::make('ends_at') - ->timezone($user->timezone) - ->required(), - Fieldset::make('Registration Form') - ->relationship('eventRegistrationForm') - ->saveRelationshipsBeforeChildrenUsing(static function (Component | CanEntangleWithSingularRelationships $component): void { - $component->getCachedExistingRecord()?->delete(); - - $relationship = $component->getRelationship(); - - $data = $component->getChildComponentContainer()->getState(shouldCallHooksBefore: false); - $data = $component->mutateRelationshipDataBeforeCreate($data); - - $relatedModel = $component->getRelatedModel(); - - $record = new $relatedModel(); - $record->fill($data); - - $relationship->save($record); - - $component->cachedExistingRecord($record); - }) - ->saveRelationshipsUsing(null) - ->schema([ - Grid::make() - ->schema([ - Toggle::make('embed_enabled') - ->label('Embed Enabled') - ->live() - ->helperText('If enabled, this form can be embedded on other websites.'), - TagsInput::make('allowed_domains') - ->label('Allowed Domains') - ->helperText('Only these domains will be allowed to embed this form.') - ->placeholder('example.com') - ->hidden(fn (Get $get) => ! $get('embed_enabled')) - ->disabled(fn (Get $get) => ! $get('embed_enabled')) - ->nestedRecursiveRules( - [ - 'string', - new IsDomain(), - ] - ), - ]) - ->columnSpanFull(), - Toggle::make('is_wizard') - ->label('Multi-step form') - ->live() - ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), - Section::make('Fields') - ->schema([ - $this->fieldBuilder(), - ]) - ->hidden(fn (Get $get) => $get('is_wizard')) - ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()), - Repeater::make('steps') - ->schema([ - TextInput::make('label') - ->required() - ->string() - ->maxLength(255) - ->autocomplete(false) - ->columnSpanFull() - ->lazy(), - $this->fieldBuilder(), - ]) - ->addActionLabel('New step') - ->itemLabel(fn (array $state): ?string => $state['label'] ?? null) - ->visible(fn (Get $get) => $get('is_wizard')) - ->disabled(fn (?EventRegistrationForm $record) => $record?->submissions()->exists()) - ->relationship() - ->reorderable() - ->columnSpanFull(), - Section::make('Appearance') - ->schema([ - ColorSelect::make('primary_color'), - Select::make('rounding') - ->options(Rounding::class), - ]) - ->columns(), - ]), - ]); - } - - public function fieldBuilder(): TiptapEditor - { - return TiptapEditor::make('content') - ->output(TiptapOutput::Json) - ->blocks(FormFieldBlockRegistry::get()) - ->tools(['bold', 'italic', 'small', '|', 'heading', 'bullet-list', 'ordered-list', 'hr', '|', 'link', 'grid', 'blocks']) - ->placeholder('Drag blocks here to build your form') - ->hiddenLabel() - ->saveRelationshipsUsing(function (TiptapEditor $component, EventRegistrationForm | EventRegistrationFormStep $record) { - if ($component->isDisabled()) { - return; - } - - $form = $record instanceof EventRegistrationForm ? $record : $record->submissible; - $formStep = $record instanceof EventRegistrationFormStep ? $record : null; - - EventRegistrationFormStep::query() - ->whereBelongsTo($form, 'submissible') - ->when($formStep, fn (EloquentBuilder $query) => $query->whereBelongsTo($formStep, 'step')) - ->delete(); - - $content = $component->decodeBlocksBeforeSave($component->getJSON(decoded: true)); - $content['content'] = $this->saveFieldsFromComponents( - $form, - $content['content'] ?? [], - $formStep, - ); - - $record->content = $content; - $record->save(); - }) - ->dehydrated(false) - ->columnSpanFull() - ->extraInputAttributes(['style' => 'min-height: 12rem;']); - } - - public function saveFieldsFromComponents(EventRegistrationForm $form, array $components, ?EventRegistrationFormStep $eventRegistrationFormStep): array - { - foreach ($components as $componentKey => $component) { - if (array_key_exists('content', $component)) { - $components[$componentKey]['content'] = $this->saveFieldsFromComponents($form, $component['content'], $eventRegistrationFormStep); - - continue; - } - - if ($component['type'] !== 'tiptapBlock') { - continue; - } - - $componentAttributes = $component['attrs'] ?? []; - - if (array_key_exists('id', $componentAttributes)) { - $id = $componentAttributes['id'] ?? null; - unset($componentAttributes['id']); - } - - if (array_key_exists('label', $componentAttributes['data'])) { - $label = $componentAttributes['data']['label'] ?? null; - unset($componentAttributes['data']['label']); - } - - if (array_key_exists('isRequired', $componentAttributes['data'])) { - $isRequired = $componentAttributes['data']['isRequired'] ?? null; - unset($componentAttributes['data']['isRequired']); - } - - /** @var EventRegistrationFormField $field */ - $field = $form->fields()->findOrNew($id ?? null); - $field->step()->associate($eventRegistrationFormStep); - $field->label = $label ?? $componentAttributes['type']; - $field->is_required = $isRequired ?? false; - $field->type = $componentAttributes['type']; - $field->config = $componentAttributes['data']; - $field->save(); - - $components[$componentKey]['attrs']['id'] = $field->id; - } - - return $components; - } - - protected function afterCreate(): void - { - $this->clearFormContentForWizard(); - } - - protected function afterSave(): void - { - $this->clearFormContentForWizard(); - } - - protected function clearFormContentForWizard(): void - { - /** @var Event $event */ - $event = $this->record; - - $form = $event->eventRegistrationForm; - - if ($form?->is_wizard) { - $form->content = null; - $form->save(); - - return; - } - - $form?->steps()->delete(); + return $form->schema($this->fields()); } protected function getHeaderActions(): array From 265ed0c8b32eb15ac91dd7452402134ef15949fb Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 13:03:40 -0500 Subject: [PATCH 107/152] Start working on adding the content Signed-off-by: Kevin Ullyott --- .../src/Actions/GenerateFormKitSchema.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index 1ce5fa3530..21b693588d 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -68,6 +68,32 @@ public function __invoke(Submissible $submissible): array ]; } + $content = [ + [ + '$formkit' => 'radio', + 'label' => 'Will you be attending?', + 'name' => 'attending', + 'options' => [ + [ + 'label' => 'Yes', + 'value' => 'yes', + ], + [ + 'label' => 'No', + 'value' => 'no', + ], + ], + 'validation' => 'required', + ], + [ + '$el' => 'div', + 'attrs' => [ + 'if' => '$get(form).values.attending === "yes"', + ], + 'children' => $content, + ], + ]; + return [ '$cmp' => 'FormKit', 'props' => [ From d140a07e5c5467a5b031f5f6bf1e113a41d073d4 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 14:17:45 -0500 Subject: [PATCH 108/152] Fix data saving issues Signed-off-by: Kevin Ullyott --- .../src/Actions/GenerateFormKitSchema.php | 11 +++-- .../EventRegistrationWidgetController.php | 43 +++++++++++-------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index 21b693588d..f9f19e2ede 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -72,6 +72,7 @@ public function __invoke(Submissible $submissible): array [ '$formkit' => 'radio', 'label' => 'Will you be attending?', + 'id' => 'attending', 'name' => 'attending', 'options' => [ [ @@ -87,11 +88,15 @@ public function __invoke(Submissible $submissible): array ], [ '$el' => 'div', - 'attrs' => [ - 'if' => '$get(form).values.attending === "yes"', - ], + 'if' => '$get(attending).value === "yes"', 'children' => $content, ], + [ + '$formkit' => 'submit', + 'if' => '$get(attending).value === "no"', + 'label' => 'Submit', + 'disabled' => '$get(form).state.valid !== true', + ], ]; return [ diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index eee1f4c4a1..19672440e5 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -167,12 +167,17 @@ public function store( abort(Response::HTTP_UNAUTHORIZED); } + // TODO See if we can make attending a bool + $validator = Validator::make( $request->all(), - $generateValidation($form) + [ + 'attending' => ['required', 'in:yes,no'], + ...$request->get('attending') === 'yes' ? $generateValidation($form) : [], + ] ); - ray($validator->errors()); + //ray($validator->errors()); if ($validator->fails()) { return response()->json( @@ -192,33 +197,37 @@ public function store( $submission->submitted_at = now(); - // TODO: Adjust the status of the EventAttendee to Attending or Not Attending based on the form submission. - $submission->save(); + $authentication->author->update(['status' => $request->get('attending') === 'yes' ? EventAttendeeStatus::Attending : EventAttendeeStatus::NotAttending]); + $data = $validator->validated(); - unset($data['recaptcha-token']); + // TODO: change the EventFormSubmission to have a column to store the attending data item + + if ($data['attending'] === 'yes') { + unset($data['recaptcha-token'], $data['attending']); - if ($form->is_wizard) { - foreach ($form->steps as $step) { - foreach ($data[$step->label] as $fieldId => $response) { + if ($form->is_wizard) { + foreach ($form->steps as $step) { + foreach ($data[$step->label] as $fieldId => $response) { + $submission->fields()->attach( + $fieldId, + ['id' => Str::orderedUuid(), 'response' => $response], + ); + } + } + } else { + foreach ($data as $fieldId => $response) { $submission->fields()->attach( $fieldId, ['id' => Str::orderedUuid(), 'response' => $response], ); } } - } else { - foreach ($data as $fieldId => $response) { - $submission->fields()->attach( - $fieldId, - ['id' => Str::orderedUuid(), 'response' => $response], - ); - } - } - $submission->save(); + $submission->save(); + } return response()->json( [ From b4d7b4c40b9a574d66c82fdf1a925a8829d504f3 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 14:39:38 -0500 Subject: [PATCH 109/152] Fix more issues Signed-off-by: Kevin Ullyott --- ...nt_registration_form_submissions_table.php | 1 + .../EventRegistrationWidgetController.php | 108 ++++++++++-------- .../EventRegistrationFormSubmission.php | 3 + widgets/event-registration/src/App.vue | 13 ++- 4 files changed, 72 insertions(+), 53 deletions(-) diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php index 0165143dbd..2b362933c9 100644 --- a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php @@ -46,6 +46,7 @@ public function up(): void $table->foreignUuid('form_id')->constrained('event_registration_forms')->cascadeOnDelete(); $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); + $table->string('attendee_status'); $table->timestamp('submitted_at')->nullable(); $table->timestamp('canceled_at')->nullable(); $table->string('request_method')->nullable(); diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index 19672440e5..bae23c1cbd 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -37,10 +37,12 @@ namespace AdvisingApp\MeetingCenter\Http\Controllers; use Closure; +use Exception; use Illuminate\Support\Str; use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; use Filament\Support\Colors\Color; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\URL; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; @@ -153,80 +155,88 @@ public function store( GenerateSubmissibleValidation $generateValidation, Event $event, ): JsonResponse { - $form = $event->eventRegistrationForm; - - $authentication = $request->query('authentication'); + try { + DB::beginTransaction(); - if (filled($authentication)) { - $authentication = EventRegistrationFormAuthentication::findOrFail($authentication); - } - - if ( - ($authentication?->isExpired() ?? true) - ) { - abort(Response::HTTP_UNAUTHORIZED); - } + $form = $event->eventRegistrationForm; - // TODO See if we can make attending a bool + $authentication = $request->query('authentication'); - $validator = Validator::make( - $request->all(), - [ - 'attending' => ['required', 'in:yes,no'], - ...$request->get('attending') === 'yes' ? $generateValidation($form) : [], - ] - ); + if (filled($authentication)) { + $authentication = EventRegistrationFormAuthentication::findOrFail($authentication); + } - //ray($validator->errors()); + if ( + ($authentication?->isExpired() ?? true) + ) { + abort(Response::HTTP_UNAUTHORIZED); + } - if ($validator->fails()) { - return response()->json( + $validator = Validator::make( + $request->all(), [ - 'errors' => (object) $validator->errors(), - ], - Response::HTTP_UNPROCESSABLE_ENTITY + 'attending' => ['required', 'in:yes,no'], + ...$request->get('attending') === 'yes' ? $generateValidation($form) : [], + ] ); - } - /** @var EventRegistrationFormSubmission $submission */ - $submission = $form->submissions()->make(); + if ($validator->fails()) { + return response()->json( + [ + 'errors' => (object) $validator->errors(), + ], + Response::HTTP_UNPROCESSABLE_ENTITY + ); + } - $submission->author()->associate($authentication->author); + /** @var EventRegistrationFormSubmission $submission */ + $submission = $form->submissions()->make(); - $authentication->delete(); + $submission->author()->associate($authentication->author); - $submission->submitted_at = now(); + $authentication->delete(); - $submission->save(); + $submission->submitted_at = now(); - $authentication->author->update(['status' => $request->get('attending') === 'yes' ? EventAttendeeStatus::Attending : EventAttendeeStatus::NotAttending]); + $submission->attendee_status = $request->get('attending') === 'yes' ? EventAttendeeStatus::Attending : EventAttendeeStatus::NotAttending; - $data = $validator->validated(); + $submission->save(); - // TODO: change the EventFormSubmission to have a column to store the attending data item + $authentication->author->update(['status' => $request->get('attending') === 'yes' ? EventAttendeeStatus::Attending : EventAttendeeStatus::NotAttending]); - if ($data['attending'] === 'yes') { - unset($data['recaptcha-token'], $data['attending']); + $data = $validator->validated(); - if ($form->is_wizard) { - foreach ($form->steps as $step) { - foreach ($data[$step->label] as $fieldId => $response) { + if ($data['attending'] === 'yes') { + unset($data['recaptcha-token']); + + if ($form->is_wizard) { + foreach ($form->steps as $step) { + foreach ($data[$step->label] as $fieldId => $response) { + $submission->fields()->attach( + $fieldId, + ['id' => Str::orderedUuid(), 'response' => $response], + ); + } + } + } else { + foreach ($data as $fieldId => $response) { $submission->fields()->attach( $fieldId, ['id' => Str::orderedUuid(), 'response' => $response], ); } } - } else { - foreach ($data as $fieldId => $response) { - $submission->fields()->attach( - $fieldId, - ['id' => Str::orderedUuid(), 'response' => $response], - ); - } + + $submission->save(); } - $submission->save(); + DB::commit(); + } catch (Exception $e) { + // TODO: Tag and report this exception. Send the tag to the frontend as a reference. + + DB::rollBack(); + + throw $e; } return response()->json( diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php index 35fdd58213..2c6aba5124 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php @@ -41,6 +41,7 @@ use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Form\Enums\FormSubmissionStatus; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use AdvisingApp\Form\Enums\FormSubmissionRequestDeliveryMethod; @@ -52,6 +53,7 @@ class EventRegistrationFormSubmission extends Submission protected $fillable = [ 'canceled_at', 'form_id', + 'attendee_status', 'request_method', 'request_note', 'submitted_at', @@ -61,6 +63,7 @@ class EventRegistrationFormSubmission extends Submission 'submitted_at' => 'immutable_datetime', 'canceled_at' => 'immutable_datetime', 'request_method' => FormSubmissionRequestDeliveryMethod::class, + 'attendee_status' => EventAttendeeStatus::class, ]; public function submissible(): BelongsTo diff --git a/widgets/event-registration/src/App.vue b/widgets/event-registration/src/App.vue index 78579b05e8..da5a68bd65 100644 --- a/widgets/event-registration/src/App.vue +++ b/widgets/event-registration/src/App.vue @@ -93,10 +93,15 @@ const data = reactive({ }, body: JSON.stringify(data), }) - .then((response) => response.json()) - .then((json) => { - if (json.errors) { - node.setErrors([], json.errors); + .then((response) => { + if (response.status === 500) { + node.setErrors(['An error occurred while submitting the form. Please try again later.']); + + return; + } + + if (response.json().errors) { + node.setErrors([], response.json().errors); return; } From 0cc9f6656d3193650b9b0110de392ae01cbbb51b Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 15:56:26 -0500 Subject: [PATCH 110/152] Remove todo Signed-off-by: Kevin Ullyott --- .../src/Http/Controllers/EventRegistrationWidgetController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index bae23c1cbd..bc9d4fe1d2 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -69,7 +69,6 @@ public function view(GenerateFormKitSchema $generateSchema, Event $event): JsonR [ 'name' => $form->event->title, 'description' => $form->event->description, - // TODO: Maybe get rid of this? It would never not be authenticated. 'is_authenticated' => true, 'authentication_url' => URL::signedRoute('event-registration.request-authentication', ['event' => $event]), 'recaptcha_enabled' => $form->recaptcha_enabled, From 38fb9d03ff242c1efe29daf25f844bcae1af481c Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 16:00:34 -0500 Subject: [PATCH 111/152] Split the generation logic Signed-off-by: Kevin Ullyott --- .../src/Actions/GenerateFormKitSchema.php | 60 ++++++------------- ...GenerateEventRegistrationFormKitSchema.php | 57 ++++++++++++++++++ .../EventRegistrationWidgetController.php | 4 +- 3 files changed, 77 insertions(+), 44 deletions(-) create mode 100644 app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index f9f19e2ede..42168bffb5 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -44,6 +44,23 @@ class GenerateFormKitSchema { public function __invoke(Submissible $submissible): array + { + $content = $this->generateContent($submissible); + + return [ + '$cmp' => 'FormKit', + 'props' => [ + 'type' => 'form', + 'id' => 'form', + 'onSubmit' => '$submitForm', + 'plugins' => '$plugins', + 'actions' => false, + ], + 'children' => $content, + ]; + } + + public function generateContent(Submissible $submissible): array { if ($submissible->is_wizard) { $submissible->loadMissing([ @@ -68,48 +85,7 @@ public function __invoke(Submissible $submissible): array ]; } - $content = [ - [ - '$formkit' => 'radio', - 'label' => 'Will you be attending?', - 'id' => 'attending', - 'name' => 'attending', - 'options' => [ - [ - 'label' => 'Yes', - 'value' => 'yes', - ], - [ - 'label' => 'No', - 'value' => 'no', - ], - ], - 'validation' => 'required', - ], - [ - '$el' => 'div', - 'if' => '$get(attending).value === "yes"', - 'children' => $content, - ], - [ - '$formkit' => 'submit', - 'if' => '$get(attending).value === "no"', - 'label' => 'Submit', - 'disabled' => '$get(form).state.valid !== true', - ], - ]; - - return [ - '$cmp' => 'FormKit', - 'props' => [ - 'type' => 'form', - 'id' => 'form', - 'onSubmit' => '$submitForm', - 'plugins' => '$plugins', - 'actions' => false, - ], - 'children' => $content, - ]; + return $content; } public function content(array $content, ?Collection $fields = null): array diff --git a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php new file mode 100644 index 0000000000..31adf39373 --- /dev/null +++ b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php @@ -0,0 +1,57 @@ +generateContent($submissible); + + $content = [ + [ + '$formkit' => 'radio', + 'label' => 'Will you be attending?', + 'id' => 'attending', + 'name' => 'attending', + 'options' => [ + [ + 'label' => 'Yes', + 'value' => 'yes', + ], + [ + 'label' => 'No', + 'value' => 'no', + ], + ], + 'validation' => 'required', + ], + [ + '$el' => 'div', + 'if' => '$get(attending).value === "yes"', + 'children' => $content, + ], + [ + '$formkit' => 'submit', + 'if' => '$get(attending).value === "no"', + 'label' => 'Submit', + 'disabled' => '$get(form).state.valid !== true', + ], + ]; + + return [ + '$cmp' => 'FormKit', + 'props' => [ + 'type' => 'form', + 'id' => 'form', + 'onSubmit' => '$submitForm', + 'plugins' => '$plugins', + 'actions' => false, + ], + 'children' => $content, + ]; + } +} \ No newline at end of file diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index bc9d4fe1d2..898e656280 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -50,18 +50,18 @@ use AdvisingApp\MeetingCenter\Models\Event; use Illuminate\Support\Facades\Notification; use Symfony\Component\HttpFoundation\Response; -use AdvisingApp\Form\Actions\GenerateFormKitSchema; use AdvisingApp\MeetingCenter\Models\EventAttendee; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use AdvisingApp\Form\Actions\GenerateSubmissibleValidation; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; use AdvisingApp\IntegrationGoogleRecaptcha\Settings\GoogleRecaptchaSettings; +use AdvisingApp\MeetingCenter\Actions\GenerateEventRegistrationFormKitSchema; use AdvisingApp\MeetingCenter\Notifications\AuthenticateEventRegistrationFormNotification; class EventRegistrationWidgetController extends Controller { - public function view(GenerateFormKitSchema $generateSchema, Event $event): JsonResponse + public function view(GenerateEventRegistrationFormKitSchema $generateSchema, Event $event): JsonResponse { $form = $event->eventRegistrationForm; From 8a2c878853e0e9f15fa9e6479bd3ffba9df8241a Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 16:07:36 -0500 Subject: [PATCH 112/152] Fix bug with multistep Signed-off-by: Kevin Ullyott --- .../Pages/Concerns/HasSharedEventFormConfiguration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php index f3de80786e..15f123c68b 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php @@ -151,7 +151,7 @@ public function fieldBuilder(): TiptapEditor $form = $record instanceof EventRegistrationForm ? $record : $record->submissible; $formStep = $record instanceof EventRegistrationFormStep ? $record : null; - EventRegistrationFormStep::query() + EventRegistrationFormField::query() ->whereBelongsTo($form, 'submissible') ->when($formStep, fn (EloquentBuilder $query) => $query->whereBelongsTo($formStep, 'step')) ->delete(); From 3e348a2ad0c56498e83c6352e53a34880d57c75b Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 16:39:14 -0500 Subject: [PATCH 113/152] Init viewing event attendees Signed-off-by: Kevin Ullyott --- .../src/Enums/EventAttendeeStatus.php | 15 +++- .../src/Filament/Resources/EventResource.php | 12 +++ .../Pages/ManageEventAttendees.php | 88 +++++++++++++++++++ .../meeting-center/src/Models/Event.php | 6 ++ .../src/Models/EventAttendee.php | 6 ++ 5 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php diff --git a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php index f84db2a022..ba6ad0a674 100644 --- a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php +++ b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php @@ -2,7 +2,10 @@ namespace AdvisingApp\MeetingCenter\Enums; -enum EventAttendeeStatus: string +use Filament\Support\Contracts\HasColor; +use Filament\Support\Contracts\HasLabel; + +enum EventAttendeeStatus: string implements HasColor, HasLabel { case Invited = 'invited'; @@ -19,4 +22,14 @@ public function getLabel(): ?string default => $this->name, }; } + + public function getColor(): string + { + return match ($this) { + self::Invited => 'info', + self::Pending => 'warning', + self::Attending => 'success', + self::NotAttending => 'danger', + }; + } } diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource.php b/app-modules/meeting-center/src/Filament/Resources/EventResource.php index 57e54bee16..7f258955d0 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource.php @@ -37,11 +37,13 @@ namespace AdvisingApp\MeetingCenter\Filament\Resources; use Filament\Resources\Resource; +use Filament\Resources\Pages\Page; use AdvisingApp\MeetingCenter\Models\Event; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\EditEvent; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\ViewEvent; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\ListEvents; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\CreateEvent; +use AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\ManageEventAttendees; class EventResource extends Resource { @@ -58,6 +60,15 @@ public static function getRelations(): array return []; } + public static function getRecordSubNavigation(Page $page): array + { + return $page->generateNavigationItems([ + ViewEvent::class, + EditEvent::class, + ManageEventAttendees::class, + ]); + } + public static function getPages(): array { return [ @@ -65,6 +76,7 @@ public static function getPages(): array 'create' => CreateEvent::route('/create'), 'view' => ViewEvent::route('/{record}'), 'edit' => EditEvent::route('/{record}/edit'), + 'manage-attendees' => ManageEventAttendees::route('/{record}/manage-attendees'), ]; } } diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php new file mode 100644 index 0000000000..3ccd98b991 --- /dev/null +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -0,0 +1,88 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages; + +use Filament\Tables\Table; +use App\Filament\Columns\IdColumn; +use Filament\Tables\Columns\TextColumn; +use Filament\Resources\Pages\ManageRelatedRecords; +use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; + +class ManageEventAttendees extends ManageRelatedRecords +{ + protected static string $resource = EventResource::class; + + // TODO: Obsolete when there is no table, remove from Filament + protected static string $relationship = 'attendees'; + + protected static ?string $navigationLabel = 'Attendees'; + + protected static ?string $breadcrumb = 'Attendees'; + + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + public function table(Table $table): Table + { + return $table + ->columns([ + IdColumn::make(), + TextColumn::make('status') + ->badge(), + TextColumn::make('email'), + ]) + ->filters([]) + ->headerActions([]) + ->actions([ + //ViewAction::make() + // ->modalHeading(fn (SurveySubmission $record) => 'Submission Details: ' . $record->submitted_at->format('M j, Y H:i:s')) + // ->infolist(fn (SurveySubmission $record): ?array => ($record->author && $record->submissible->is_authenticated) ? [ + // Section::make('Authenticated author') + // ->schema([ + // TextEntry::make('author.' . $record->author::displayNameKey()) + // ->label('Name'), + // TextEntry::make('author.email') + // ->label('Email address'), + // ]) + // ->columns(2), + // ] : null) + // ->modalContent(fn (SurveySubmission $record) => view('survey::submission', ['submission' => $record])) + // ->visible(fn (SurveySubmission $record) => $record->submitted_at), + //DeleteAction::make(), + ]) + ->bulkActions([]); + } +} diff --git a/app-modules/meeting-center/src/Models/Event.php b/app-modules/meeting-center/src/Models/Event.php index e19a7706e9..4dba05b52f 100644 --- a/app-modules/meeting-center/src/Models/Event.php +++ b/app-modules/meeting-center/src/Models/Event.php @@ -38,6 +38,7 @@ use App\Models\BaseModel; use Illuminate\Database\Eloquent\Relations\HasOne; +use Illuminate\Database\Eloquent\Relations\HasMany; /** * @mixin IdeHelperEvent @@ -62,4 +63,9 @@ public function eventRegistrationForm(): HasOne { return $this->hasOne(EventRegistrationForm::class, 'event_id'); } + + public function attendees(): HasMany + { + return $this->hasMany(EventAttendee::class, 'event_id'); + } } diff --git a/app-modules/meeting-center/src/Models/EventAttendee.php b/app-modules/meeting-center/src/Models/EventAttendee.php index fab1a5c640..f3c957ad13 100644 --- a/app-modules/meeting-center/src/Models/EventAttendee.php +++ b/app-modules/meeting-center/src/Models/EventAttendee.php @@ -39,6 +39,7 @@ use App\Models\BaseModel; use App\Models\Attributes\NoPermissions; use Illuminate\Notifications\Notifiable; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; #[NoPermissions] @@ -58,4 +59,9 @@ class EventAttendee extends BaseModel protected $casts = [ 'status' => EventAttendeeStatus::class, ]; + + public function event(): BelongsTo + { + return $this->belongsTo(Event::class, 'event_id'); + } } From 0be7d34d5393e19e531465780f8f0dbe0c94ec69 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 28 Dec 2023 16:44:14 -0500 Subject: [PATCH 114/152] More work on Attendee Signed-off-by: Kevin Ullyott --- .../Pages/ManageEventAttendees.php | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php index 3ccd98b991..f64949509c 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -38,8 +38,12 @@ use Filament\Tables\Table; use App\Filament\Columns\IdColumn; +use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; +use Filament\Infolists\Components\Section; +use Filament\Infolists\Components\TextEntry; use Filament\Resources\Pages\ManageRelatedRecords; +use AdvisingApp\MeetingCenter\Models\EventAttendee; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; class ManageEventAttendees extends ManageRelatedRecords @@ -67,21 +71,21 @@ public function table(Table $table): Table ->filters([]) ->headerActions([]) ->actions([ - //ViewAction::make() - // ->modalHeading(fn (SurveySubmission $record) => 'Submission Details: ' . $record->submitted_at->format('M j, Y H:i:s')) - // ->infolist(fn (SurveySubmission $record): ?array => ($record->author && $record->submissible->is_authenticated) ? [ - // Section::make('Authenticated author') - // ->schema([ - // TextEntry::make('author.' . $record->author::displayNameKey()) - // ->label('Name'), - // TextEntry::make('author.email') - // ->label('Email address'), - // ]) - // ->columns(2), - // ] : null) - // ->modalContent(fn (SurveySubmission $record) => view('survey::submission', ['submission' => $record])) - // ->visible(fn (SurveySubmission $record) => $record->submitted_at), - //DeleteAction::make(), + ViewAction::make() + ->modalHeading(fn (EventAttendee $record) => $record->event->title . ' - ' . $record->email) + ->infolist(fn (EventAttendee $record): array => [ + Section::make('Attendee Info') + ->schema([ + TextEntry::make('status') + ->label('Status') + ->badge(), + TextEntry::make('email') + ->label('Email address'), + ]) + ->columns(), + ]), + // TODO: Display this Attendees submissions + //->modalContent(fn (EventAttendee $record) => view('survey::submission', ['submission' => $record])), ]) ->bulkActions([]); } From 4c5c3f8bb2ffdccfd98670c9314d1ffc95357035 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 13:59:21 -0500 Subject: [PATCH 115/152] Fix bug Signed-off-by: Kevin Ullyott --- .../src/Http/Controllers/EventRegistrationWidgetController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php index 898e656280..b1c816251e 100644 --- a/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php +++ b/app-modules/meeting-center/src/Http/Controllers/EventRegistrationWidgetController.php @@ -206,7 +206,7 @@ public function store( $data = $validator->validated(); if ($data['attending'] === 'yes') { - unset($data['recaptcha-token']); + unset($data['recaptcha-token'], $data['attending']); if ($form->is_wizard) { foreach ($form->steps as $step) { From 12b6131784d6d2125f54f21151247bc9293f0ea2 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 14:57:22 -0500 Subject: [PATCH 116/152] Start displaying the attendee submission Signed-off-by: Kevin Ullyott --- ...ent-attendee-submissions-manager.blade.php | 3 + .../Pages/ManageEventAttendees.php | 4 ++ .../EventAttendeeSubmissionsManager.php | 60 +++++++++++++++++++ .../src/Models/EventAttendee.php | 6 ++ .../EventRegistrationFormSubmission.php | 45 -------------- .../MeetingCenterServiceProvider.php | 4 ++ 6 files changed, 77 insertions(+), 45 deletions(-) create mode 100644 app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php create mode 100644 app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php diff --git a/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php b/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php new file mode 100644 index 0000000000..c3fedc4aac --- /dev/null +++ b/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php @@ -0,0 +1,3 @@ +
+ {{ $this->table }} +
diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php index f64949509c..ef9922f12c 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -41,6 +41,7 @@ use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; use Filament\Infolists\Components\Section; +use Filament\Infolists\Components\Livewire; use Filament\Infolists\Components\TextEntry; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\MeetingCenter\Models\EventAttendee; @@ -83,6 +84,9 @@ public function table(Table $table): Table ->label('Email address'), ]) ->columns(), + // TODO: Look into Livewire/Filament bug that prevents us from passing the class here, requiring that we define it in the Service Provider + // TODO: Look into bug where, without lazy load, you have to click view twice to get the modal to show + Livewire::make('event-attendee-submissions-manager')->lazy(), ]), // TODO: Display this Attendees submissions //->modalContent(fn (EventAttendee $record) => view('survey::submission', ['submission' => $record])), diff --git a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php new file mode 100644 index 0000000000..211f87bc04 --- /dev/null +++ b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php @@ -0,0 +1,60 @@ +relationship(fn (): HasMany => $this->record->submissions()) + ->inverseRelationship('author') + ->columns([ + TextColumn::make('attendee_status') + ->badge(), + ]) + ->filters([ + // ... + ]) + ->actions([ + ViewAction::make() + ->modalHeading(fn (EventRegistrationFormSubmission $record) => 'Submission Details: ' . $record->submitted_at->format('M j, Y H:i:s')) + ->infolist(fn (EventRegistrationFormSubmission $record): array => [ + Section::make('Authenticated author') + ->schema([ + TextEntry::make('author.email') + ->label('Email Address'), + ]) + ->columns(), + ]), + //->modalContent(fn (FormSubmission $record) => view('form::submission', ['submission' => $record])), + ]) + ->bulkActions([ + // ... + ]); + } +} diff --git a/app-modules/meeting-center/src/Models/EventAttendee.php b/app-modules/meeting-center/src/Models/EventAttendee.php index f3c957ad13..3564fc7334 100644 --- a/app-modules/meeting-center/src/Models/EventAttendee.php +++ b/app-modules/meeting-center/src/Models/EventAttendee.php @@ -39,6 +39,7 @@ use App\Models\BaseModel; use App\Models\Attributes\NoPermissions; use Illuminate\Notifications\Notifiable; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; @@ -64,4 +65,9 @@ public function event(): BelongsTo { return $this->belongsTo(Event::class, 'event_id'); } + + public function submissions(): HasMany + { + return $this->hasMany(EventRegistrationFormSubmission::class, 'event_attendee_id'); + } } diff --git a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php index 2c6aba5124..75d629a0e1 100644 --- a/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php +++ b/app-modules/meeting-center/src/Models/EventRegistrationFormSubmission.php @@ -38,8 +38,6 @@ use App\Models\User; use AdvisingApp\Form\Models\Submission; -use Illuminate\Database\Eloquent\Builder; -use AdvisingApp\Form\Enums\FormSubmissionStatus; use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -92,47 +90,4 @@ public function author(): BelongsTo { return $this->belongsTo(EventAttendee::class, 'event_attendee_id'); } - - public function deliverRequest(): void - { - $this->request_method->deliver($this); - } - - public function scopeRequested(Builder $query): Builder - { - return $query->notSubmitted()->notCanceled(); - } - - public function scopeSubmitted(Builder $query): Builder - { - return $query->whereNotNull('submitted_at'); - } - - public function scopeCanceled(Builder $query): Builder - { - return $query->notSubmitted()->whereNotNull('canceled_at'); - } - - public function scopeNotSubmitted(Builder $query): Builder - { - return $query->whereNull('submitted_at'); - } - - public function scopeNotCanceled(Builder $query): Builder - { - return $query->whereNull('canceled_at'); - } - - public function getStatus(): FormSubmissionStatus - { - if ($this->submitted_at) { - return FormSubmissionStatus::Submitted; - } - - if ($this->canceled_at) { - return FormSubmissionStatus::Canceled; - } - - return FormSubmissionStatus::Requested; - } } diff --git a/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php b/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php index bc5e36b29c..e3dc80d32a 100644 --- a/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php +++ b/app-modules/meeting-center/src/Providers/MeetingCenterServiceProvider.php @@ -37,6 +37,7 @@ namespace AdvisingApp\MeetingCenter\Providers; use Filament\Panel; +use Livewire\Livewire; use Illuminate\Support\ServiceProvider; use AdvisingApp\MeetingCenter\Models\Event; use Illuminate\Console\Scheduling\Schedule; @@ -53,6 +54,7 @@ use AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormField; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission; +use AdvisingApp\MeetingCenter\Livewire\EventAttendeeSubmissionsManager; use AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication; class MeetingCenterServiceProvider extends ServiceProvider @@ -86,6 +88,8 @@ public function boot(): void $this->registerRolesAndPermissions(); $this->registerObservers(); + + Livewire::component('event-attendee-submissions-manager', EventAttendeeSubmissionsManager::class); } protected function registerRolesAndPermissions(): void From 37de56e14709d303eb8e559db1b3a42d63693f14 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 15:16:46 -0500 Subject: [PATCH 117/152] Display an attendees submissions Signed-off-by: Kevin Ullyott --- .../event-registration-submission.blade.php | 55 +++++++++++++++++++ .../Pages/ManageEventAttendees.php | 17 +++--- .../EventAttendeeSubmissionsManager.php | 23 ++++---- 3 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 app-modules/meeting-center/resources/views/event-registration-submission.blade.php diff --git a/app-modules/meeting-center/resources/views/event-registration-submission.blade.php b/app-modules/meeting-center/resources/views/event-registration-submission.blade.php new file mode 100644 index 0000000000..2756746379 --- /dev/null +++ b/app-modules/meeting-center/resources/views/event-registration-submission.blade.php @@ -0,0 +1,55 @@ +{{-- + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +--}} + +
+ @if ($submission->submissible->is_wizard) + @foreach ($submission->submissible->steps as $step) + + + {{ $step->label }} + + + + + @endforeach + @else + + @endif +
diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php index ef9922f12c..a228570e01 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -40,7 +40,7 @@ use App\Filament\Columns\IdColumn; use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; -use Filament\Infolists\Components\Section; +use Filament\Infolists\Components\Fieldset; use Filament\Infolists\Components\Livewire; use Filament\Infolists\Components\TextEntry; use Filament\Resources\Pages\ManageRelatedRecords; @@ -75,7 +75,7 @@ public function table(Table $table): Table ViewAction::make() ->modalHeading(fn (EventAttendee $record) => $record->event->title . ' - ' . $record->email) ->infolist(fn (EventAttendee $record): array => [ - Section::make('Attendee Info') + Fieldset::make('Attendee Info') ->schema([ TextEntry::make('status') ->label('Status') @@ -84,12 +84,15 @@ public function table(Table $table): Table ->label('Email address'), ]) ->columns(), - // TODO: Look into Livewire/Filament bug that prevents us from passing the class here, requiring that we define it in the Service Provider - // TODO: Look into bug where, without lazy load, you have to click view twice to get the modal to show - Livewire::make('event-attendee-submissions-manager')->lazy(), + + Fieldset::make('Attendee Submissions') + ->schema([ + // TODO: Look into Livewire/Filament bug that prevents us from passing the class here, requiring that we define it in the Service Provider + // TODO: Look into bug where, without lazy load, you have to click view twice to get the modal to show + Livewire::make('event-attendee-submissions-manager')->lazy() + ->columnSpanFull(), + ]), ]), - // TODO: Display this Attendees submissions - //->modalContent(fn (EventAttendee $record) => view('survey::submission', ['submission' => $record])), ]) ->bulkActions([]); } diff --git a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php index 211f87bc04..91a41825ad 100644 --- a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php +++ b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php @@ -34,27 +34,30 @@ public function table(Table $table): Table ->relationship(fn (): HasMany => $this->record->submissions()) ->inverseRelationship('author') ->columns([ + TextColumn::make('submitted_at') + ->label('Submitted At') + ->dateTime() + ->sortable(), TextColumn::make('attendee_status') + ->label('Submission Status') ->badge(), ]) - ->filters([ - // ... - ]) + ->defaultSort('submitted_at', 'desc') ->actions([ ViewAction::make() ->modalHeading(fn (EventRegistrationFormSubmission $record) => 'Submission Details: ' . $record->submitted_at->format('M j, Y H:i:s')) ->infolist(fn (EventRegistrationFormSubmission $record): array => [ - Section::make('Authenticated author') + Section::make('Metadata') ->schema([ TextEntry::make('author.email') - ->label('Email Address'), + ->label('Author Email Address'), + TextEntry::make('attendee_status') + ->label('Submission Status') + ->badge(), ]) ->columns(), - ]), - //->modalContent(fn (FormSubmission $record) => view('form::submission', ['submission' => $record])), - ]) - ->bulkActions([ - // ... + ]) + ->modalContent(fn (EventRegistrationFormSubmission $record) => view('meeting-center::event-registration-submission', ['submission' => $record])), ]); } } From f71c2e7218d11d015cb2368486213e2b288b8a22 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 15:53:14 -0500 Subject: [PATCH 118/152] Relate a Student or Prospect to an EventAttendee Signed-off-by: Kevin Ullyott --- .../Pages/ManageEventAttendees.php | 29 +++++++++++++++++++ .../src/Models/EventAttendee.php | 20 +++++++++++++ 2 files changed, 49 insertions(+) diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php index a228570e01..dc7cc511f5 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ManageEventAttendees.php @@ -40,12 +40,17 @@ use App\Filament\Columns\IdColumn; use Filament\Tables\Actions\ViewAction; use Filament\Tables\Columns\TextColumn; +use AdvisingApp\Prospect\Models\Prospect; use Filament\Infolists\Components\Fieldset; use Filament\Infolists\Components\Livewire; use Filament\Infolists\Components\TextEntry; +use AdvisingApp\StudentDataModel\Models\Student; +use Filament\Infolists\Components\RepeatableEntry; use Filament\Resources\Pages\ManageRelatedRecords; use AdvisingApp\MeetingCenter\Models\EventAttendee; +use AdvisingApp\Prospect\Filament\Resources\ProspectResource; use AdvisingApp\MeetingCenter\Filament\Resources\EventResource; +use AdvisingApp\StudentDataModel\Filament\Resources\StudentResource; class ManageEventAttendees extends ManageRelatedRecords { @@ -85,6 +90,30 @@ public function table(Table $table): Table ]) ->columns(), + Fieldset::make('Relations') + ->schema([ + RepeatableEntry::make('prospects') + ->schema([ + TextEntry::make(Prospect::displayNameKey()) + ->label('Name') + ->color('primary') + ->url(fn (Prospect $record): string => ProspectResource::getUrl('view', ['record' => $record])), + ]) + ->columns() + ->visible(fn (EventAttendee $record): bool => $record->prospects->isNotEmpty()), + RepeatableEntry::make('students') + ->schema([ + TextEntry::make(Student::displayNameKey()) + ->label('Name') + ->color('primary') + ->url(fn (Student $record): string => StudentResource::getUrl('view', ['record' => $record])), + ]) + ->columns() + ->visible(fn (EventAttendee $record): bool => $record->students->isNotEmpty()), + ]) + ->visible(fn (EventAttendee $record): bool => $record->prospects->isNotEmpty() || $record->students->isNotEmpty()) + ->columns(), + Fieldset::make('Attendee Submissions') ->schema([ // TODO: Look into Livewire/Filament bug that prevents us from passing the class here, requiring that we define it in the Service Provider diff --git a/app-modules/meeting-center/src/Models/EventAttendee.php b/app-modules/meeting-center/src/Models/EventAttendee.php index 3564fc7334..9590bae852 100644 --- a/app-modules/meeting-center/src/Models/EventAttendee.php +++ b/app-modules/meeting-center/src/Models/EventAttendee.php @@ -39,6 +39,8 @@ use App\Models\BaseModel; use App\Models\Attributes\NoPermissions; use Illuminate\Notifications\Notifiable; +use AdvisingApp\Prospect\Models\Prospect; +use AdvisingApp\StudentDataModel\Models\Student; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus; @@ -70,4 +72,22 @@ public function submissions(): HasMany { return $this->hasMany(EventRegistrationFormSubmission::class, 'event_attendee_id'); } + + public function prospects(): HasMany + { + return $this->hasMany( + related: Prospect::class, + foreignKey: 'email', + localKey: 'email', + ); + } + + public function students(): HasMany + { + return $this->hasMany( + related: Student::class, + foreignKey: 'email', + localKey: 'email', + ); + } } From 5ae60bb5706d2f03eac48382f671f342877d4470 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 16:39:38 -0500 Subject: [PATCH 119/152] Clear out unneded columns Signed-off-by: Kevin Ullyott --- ...94229_create_event_registration_form_submissions_table.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php index 2b362933c9..af7df1dc37 100644 --- a/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php +++ b/app-modules/meeting-center/database/migrations/2023_12_27_194229_create_event_registration_form_submissions_table.php @@ -48,10 +48,6 @@ public function up(): void $table->foreignUuid('event_attendee_id')->constrained('event_attendees')->cascadeOnDelete(); $table->string('attendee_status'); $table->timestamp('submitted_at')->nullable(); - $table->timestamp('canceled_at')->nullable(); - $table->string('request_method')->nullable(); - $table->text('request_note')->nullable(); - $table->foreignUuid('requester_id')->nullable()->constrained('users')->nullOnDelete(); $table->timestamps(); $table->softDeletes(); From 3defeb9962bd453c1850fa8c49388f418f8039af Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Fri, 29 Dec 2023 16:44:03 -0500 Subject: [PATCH 120/152] composer update Signed-off-by: Kevin Ullyott --- composer.lock | 145 +++++++++++++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 55 deletions(-) diff --git a/composer.lock b/composer.lock index 029ba3e12f..ba8789147b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a7c988d45a8bf04ea377069a6dd7b23a", + "content-hash": "19b34ef965a1ec4aa7ec0deb038e20bd", "packages": [ { "name": "amphp/amp", @@ -559,16 +559,16 @@ }, { "name": "awcodes/filament-tiptap-editor", - "version": "v3.2.17", + "version": "v3.2.18", "source": { "type": "git", "url": "https://github.com/awcodes/filament-tiptap-editor.git", - "reference": "0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f" + "reference": "7de016e723ba62908f979a39204955e1801b0967" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f", - "reference": "0c56c96d6dddad9b61ad36aaa500cdb04dd5dd9f", + "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/7de016e723ba62908f979a39204955e1801b0967", + "reference": "7de016e723ba62908f979a39204955e1801b0967", "shasum": "" }, "require": { @@ -630,7 +630,7 @@ ], "support": { "issues": "https://github.com/awcodes/filament-tiptap-editor/issues", - "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.17" + "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.18" }, "funding": [ { @@ -638,7 +638,7 @@ "type": "github" } ], - "time": "2023-12-27T19:10:56+00:00" + "time": "2023-12-28T20:05:06+00:00" }, { "name": "aws/aws-crt-php", @@ -755,16 +755,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.295.2", + "version": "3.295.4", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73" + "reference": "2372661db989fe4229abd95f4434b37252076d58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73", - "reference": "7e8f68580954a01cf9c8f2abd4f4db52ebcb7b73", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2372661db989fe4229abd95f4434b37252076d58", + "reference": "2372661db989fe4229abd95f4434b37252076d58", "shasum": "" }, "require": { @@ -844,9 +844,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.295.2" + "source": "https://github.com/aws/aws-sdk-php/tree/3.295.4" }, - "time": "2023-12-27T19:06:10+00:00" + "time": "2023-12-29T19:07:49+00:00" }, { "name": "barryvdh/laravel-debugbar", @@ -2379,6 +2379,41 @@ "relative": true } }, + { + "name": "canyon-gbs/inventory-management", + "version": "1.0", + "dist": { + "type": "path", + "url": "app-modules/inventory-management", + "reference": "16210c789f3a6d5a4b14ce0db3a17f5cdc4f6e48" + }, + "require": { + "filament/filament": "^3.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "AdvisingApp\\InventoryManagement\\Providers\\InventoryManagementServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "AdvisingApp\\InventoryManagement\\": "src/", + "AdvisingApp\\InventoryManagement\\Tests\\": "tests/", + "AdvisingApp\\InventoryManagement\\Database\\Factories\\": "database/factories/", + "AdvisingApp\\InventoryManagement\\Database\\Seeders\\": "database/seeders/" + } + }, + "license": [ + "proprietary" + ], + "transport-options": { + "symlink": true, + "relative": true + } + }, { "name": "carbonphp/carbon-doctrine-types", "version": "2.1.0", @@ -4071,7 +4106,7 @@ }, { "name": "filament/actions", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", @@ -4122,7 +4157,7 @@ }, { "name": "filament/filament", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", @@ -4187,7 +4222,7 @@ }, { "name": "filament/forms", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", @@ -4243,7 +4278,7 @@ }, { "name": "filament/infolists", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", @@ -4294,7 +4329,7 @@ }, { "name": "filament/notifications", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", @@ -4346,7 +4381,7 @@ }, { "name": "filament/spatie-laravel-media-library-plugin", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-media-library-plugin.git", @@ -4383,7 +4418,7 @@ }, { "name": "filament/spatie-laravel-settings-plugin", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-settings-plugin.git", @@ -4430,7 +4465,7 @@ }, { "name": "filament/support", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", @@ -4487,16 +4522,16 @@ }, { "name": "filament/tables", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67" + "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67", - "reference": "ea8518eeaf15111b4dbd7438a8a00a3c3ab48c67", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/e0701467097f6a82b235ad9f31e3c30ae1035118", + "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118", "shasum": "" }, "require": { @@ -4536,20 +4571,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:29+00:00" + "time": "2023-12-28T17:31:59+00:00" }, { "name": "filament/widgets", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "7195d2fe7d12a9b9595fa445a4dbedd6d7714836" + "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/7195d2fe7d12a9b9595fa445a4dbedd6d7714836", - "reference": "7195d2fe7d12a9b9595fa445a4dbedd6d7714836", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", + "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", "shasum": "" }, "require": { @@ -4580,7 +4615,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-24T21:17:06+00:00" + "time": "2023-12-28T17:31:57+00:00" }, { "name": "firebase/php-jwt", @@ -10161,16 +10196,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.34", + "version": "3.0.35", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "56c79f16a6ae17e42089c06a2144467acc35348a" + "reference": "4b1827beabce71953ca479485c0ae9c51287f2fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56c79f16a6ae17e42089c06a2144467acc35348a", - "reference": "56c79f16a6ae17e42089c06a2144467acc35348a", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4b1827beabce71953ca479485c0ae9c51287f2fe", + "reference": "4b1827beabce71953ca479485c0ae9c51287f2fe", "shasum": "" }, "require": { @@ -10251,7 +10286,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.34" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.35" }, "funding": [ { @@ -10267,7 +10302,7 @@ "type": "tidelift" } ], - "time": "2023-11-27T11:13:31+00:00" + "time": "2023-12-29T01:59:53+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -17148,16 +17183,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.42.0", + "version": "v3.44.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "632ef1be3447a9b890bef06147475facee535d0f" + "reference": "5445834057a744c1a434ed60fcac566b4de3a0f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/632ef1be3447a9b890bef06147475facee535d0f", - "reference": "632ef1be3447a9b890bef06147475facee535d0f", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/5445834057a744c1a434ed60fcac566b4de3a0f2", + "reference": "5445834057a744c1a434ed60fcac566b4de3a0f2", "shasum": "" }, "require": { @@ -17187,7 +17222,7 @@ "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^9.6 || ^10.5.5", "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { @@ -17226,7 +17261,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.42.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.44.0" }, "funding": [ { @@ -17234,7 +17269,7 @@ "type": "github" } ], - "time": "2023-12-24T14:38:51+00:00" + "time": "2023-12-29T20:21:16+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -20765,28 +20800,28 @@ }, { "name": "ta-tikoma/phpunit-architecture-test", - "version": "0.7.5", + "version": "0.7.6", "source": { "type": "git", "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", - "reference": "9eb08437e8f0c0c75cc947a373cf49672c335827" + "reference": "a252cd9488fd62f3c8c6cafa303b1b96e9df24e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/9eb08437e8f0c0c75cc947a373cf49672c335827", - "reference": "9eb08437e8f0c0c75cc947a373cf49672c335827", + "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/a252cd9488fd62f3c8c6cafa303b1b96e9df24e0", + "reference": "a252cd9488fd62f3c8c6cafa303b1b96e9df24e0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.15.4", + "nikic/php-parser": "^4.18.0", "php": "^8.1.0", "phpdocumentor/reflection-docblock": "^5.3.0", - "phpunit/phpunit": "^10.1.1", - "symfony/finder": "^6.2.7 || ^7.0.0" + "phpunit/phpunit": "^10.5.5", + "symfony/finder": "^6.4.0 || ^7.0.0" }, "require-dev": { - "laravel/pint": "^1.9.0", - "phpstan/phpstan": "^1.10.13" + "laravel/pint": "^1.13.7", + "phpstan/phpstan": "^1.10.50" }, "type": "library", "autoload": { @@ -20818,9 +20853,9 @@ ], "support": { "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues", - "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.7.5" + "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.7.6" }, - "time": "2023-10-12T15:31:50+00:00" + "time": "2023-12-29T13:14:58+00:00" }, { "name": "theseer/tokenizer", From f93ac5d8328c3ff92fac981d4fe22c5b002f572e Mon Sep 17 00:00:00 2001 From: Orrison Date: Fri, 29 Dec 2023 21:45:41 +0000 Subject: [PATCH 121/152] chore: fix enforcement of copyright on all files --- ...ent-attendee-submissions-manager.blade.php | 33 ++++++++++++++++++ ...GenerateEventRegistrationFormKitSchema.php | 34 +++++++++++++++++++ .../src/Enums/EventAttendeeStatus.php | 34 +++++++++++++++++++ .../HasSharedEventFormConfiguration.php | 34 +++++++++++++++++++ .../EventAttendeeSubmissionsManager.php | 34 +++++++++++++++++++ 5 files changed, 169 insertions(+) diff --git a/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php b/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php index c3fedc4aac..9c8071e9c4 100644 --- a/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php +++ b/app-modules/meeting-center/resources/views/livewire/event-attendee-submissions-manager.blade.php @@ -1,3 +1,36 @@ +{{-- + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +--}}
{{ $this->table }}
diff --git a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php index 31adf39373..abea705568 100644 --- a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php +++ b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\MeetingCenter\Actions; use AdvisingApp\Form\Models\Submissible; diff --git a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php index ba6ad0a674..407f84ae5e 100644 --- a/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php +++ b/app-modules/meeting-center/src/Enums/EventAttendeeStatus.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\MeetingCenter\Enums; use Filament\Support\Contracts\HasColor; diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php index 15f123c68b..fb5f1f5ce4 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\MeetingCenter\Filament\Resources\EventResource\Pages\Concerns; use App\Models\User; diff --git a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php index 91a41825ad..a93aecee71 100644 --- a/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php +++ b/app-modules/meeting-center/src/Livewire/EventAttendeeSubmissionsManager.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\MeetingCenter\Livewire; use Livewire\Component; From b25e780ade0ce4d0b882cc1b8da45a5c6ce61292 Mon Sep 17 00:00:00 2001 From: joelicatajr Date: Fri, 29 Dec 2023 21:49:05 +0000 Subject: [PATCH 122/152] chore: fix code style --- .../src/Actions/GenerateEventRegistrationFormKitSchema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php index abea705568..49ea7c3720 100644 --- a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php +++ b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php @@ -88,4 +88,4 @@ public function __invoke(Submissible $submissible): array 'children' => $content, ]; } -} \ No newline at end of file +} From 8d495f2d636c7cfd7875b693e34b954dad2e2679 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Tue, 2 Jan 2024 12:02:17 -0500 Subject: [PATCH 123/152] PR Feedback Signed-off-by: Kevin Ullyott --- .../src/Actions/GenerateFormKitSchema.php | 60 +++++++++-------- .../src/Models/SubmissibleAuthentication.php | 3 +- app-modules/form/src/Models/Submission.php | 3 +- ...GenerateEventRegistrationFormKitSchema.php | 64 +++++++++---------- 4 files changed, 61 insertions(+), 69 deletions(-) diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index 42168bffb5..f51dbc2029 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -45,8 +45,6 @@ class GenerateFormKitSchema { public function __invoke(Submissible $submissible): array { - $content = $this->generateContent($submissible); - return [ '$cmp' => 'FormKit', 'props' => [ @@ -56,38 +54,10 @@ public function __invoke(Submissible $submissible): array 'plugins' => '$plugins', 'actions' => false, ], - 'children' => $content, + 'children' => $this->generateContent($submissible), ]; } - public function generateContent(Submissible $submissible): array - { - if ($submissible->is_wizard) { - $submissible->loadMissing([ - 'steps' => [ - 'fields', - ], - ]); - - $content = $this->wizardContent($submissible); - } else { - $submissible->loadMissing([ - 'fields', - ]); - - $content = [ - ...$this->content($submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), - [ - '$formkit' => 'submit', - 'label' => 'Submit', - 'disabled' => '$get(form).state.valid !== true', - ], - ]; - } - - return $content; - } - public function content(array $content, ?Collection $fields = null): array { $blocks = FormFieldBlockRegistry::keyByType(); @@ -278,4 +248,32 @@ public function wizardContent(Submissible $submissible): array ], ]; } + + protected function generateContent(Submissible $submissible): array + { + if ($submissible->is_wizard) { + $submissible->loadMissing([ + 'steps' => [ + 'fields', + ], + ]); + + $content = $this->wizardContent($submissible); + } else { + $submissible->loadMissing([ + 'fields', + ]); + + $content = [ + ...$this->content($submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), + [ + '$formkit' => 'submit', + 'label' => 'Submit', + 'disabled' => '$get(form).state.valid !== true', + ], + ]; + } + + return $content; + } } diff --git a/app-modules/form/src/Models/SubmissibleAuthentication.php b/app-modules/form/src/Models/SubmissibleAuthentication.php index b5a0360f6f..3d6bb26158 100644 --- a/app-modules/form/src/Models/SubmissibleAuthentication.php +++ b/app-modules/form/src/Models/SubmissibleAuthentication.php @@ -41,7 +41,6 @@ use App\Models\Attributes\NoPermissions; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\MassPrunable; -use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** @@ -66,7 +65,7 @@ public function prunable(): Builder ->where('created_at', '<', now()->subMonth()); } - public function author(): MorphTo|BelongsTo + public function author(): BelongsTo { return $this->morphTo(); } diff --git a/app-modules/form/src/Models/Submission.php b/app-modules/form/src/Models/Submission.php index 0816268c2e..86f3e41f3e 100644 --- a/app-modules/form/src/Models/Submission.php +++ b/app-modules/form/src/Models/Submission.php @@ -40,7 +40,6 @@ use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Collection; use AdvisingApp\StudentDataModel\Models\Student; -use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -55,7 +54,7 @@ abstract public function submissible(): BelongsTo; abstract public function fields(): BelongsToMany; - public function author(): MorphTo|BelongsTo + public function author(): BelongsTo { return $this ->morphTo('author'); diff --git a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php index 49ea7c3720..b9646558fb 100644 --- a/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php +++ b/app-modules/meeting-center/src/Actions/GenerateEventRegistrationFormKitSchema.php @@ -43,39 +43,6 @@ class GenerateEventRegistrationFormKitSchema extends GenerateFormKitSchema { public function __invoke(Submissible $submissible): array { - $content = $this->generateContent($submissible); - - $content = [ - [ - '$formkit' => 'radio', - 'label' => 'Will you be attending?', - 'id' => 'attending', - 'name' => 'attending', - 'options' => [ - [ - 'label' => 'Yes', - 'value' => 'yes', - ], - [ - 'label' => 'No', - 'value' => 'no', - ], - ], - 'validation' => 'required', - ], - [ - '$el' => 'div', - 'if' => '$get(attending).value === "yes"', - 'children' => $content, - ], - [ - '$formkit' => 'submit', - 'if' => '$get(attending).value === "no"', - 'label' => 'Submit', - 'disabled' => '$get(form).state.valid !== true', - ], - ]; - return [ '$cmp' => 'FormKit', 'props' => [ @@ -85,7 +52,36 @@ public function __invoke(Submissible $submissible): array 'plugins' => '$plugins', 'actions' => false, ], - 'children' => $content, + 'children' => [ + [ + '$formkit' => 'radio', + 'label' => 'Will you be attending?', + 'id' => 'attending', + 'name' => 'attending', + 'options' => [ + [ + 'label' => 'Yes', + 'value' => 'yes', + ], + [ + 'label' => 'No', + 'value' => 'no', + ], + ], + 'validation' => 'required', + ], + [ + '$el' => 'div', + 'if' => '$get(attending).value === "yes"', + 'children' => $this->generateContent($submissible), + ], + [ + '$formkit' => 'submit', + 'if' => '$get(attending).value === "no"', + 'label' => 'Submit', + 'disabled' => '$get(form).state.valid !== true', + ], + ], ]; } } From 8a3fb317666c9d364f0f2e45bdb926330b9c2887 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Wed, 3 Jan 2024 09:23:32 -0500 Subject: [PATCH 124/152] Regenerate the helper file Signed-off-by: Kevin Ullyott --- _ide_helper_models.php | 118 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/_ide_helper_models.php b/_ide_helper_models.php index 520c0c5be7..1e43672ec5 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -832,6 +832,8 @@ class IdeHelperAudit {} * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @property \Illuminate\Support\Carbon|null $deleted_at + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count * @property-read \App\Models\User $user * @method static \Illuminate\Database\Eloquent\Builder|License newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|License newQuery() @@ -2422,6 +2424,9 @@ class IdeHelperCalendarEvent {} * @property \Illuminate\Support\Carbon $ends_at * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at + * @property-read \Illuminate\Database\Eloquent\Collection $attendees + * @property-read int|null $attendees_count + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationForm|null $eventRegistrationForm * @method static \AdvisingApp\MeetingCenter\Database\Factories\EventFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|Event newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Event newQuery() @@ -2441,6 +2446,119 @@ class IdeHelperCalendarEvent {} class IdeHelperEvent {} } +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventAttendee + * + * @property \AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus $status + * @property-read \AdvisingApp\MeetingCenter\Models\Event|null $event + * @property-read \Illuminate\Notifications\DatabaseNotificationCollection $notifications + * @property-read int|null $notifications_count + * @property-read \Illuminate\Database\Eloquent\Collection $prospects + * @property-read int|null $prospects_count + * @property-read \Illuminate\Database\Eloquent\Collection $students + * @property-read int|null $students_count + * @property-read \Illuminate\Database\Eloquent\Collection $submissions + * @property-read int|null $submissions_count + * @method static \Illuminate\Database\Eloquent\Builder|EventAttendee newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventAttendee newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventAttendee query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventAttendee {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationForm + * + * @property \AdvisingApp\Form\Enums\Rounding $rounding + * @property-read \AdvisingApp\MeetingCenter\Models\Event|null $event + * @property-read \Illuminate\Database\Eloquent\Collection $fields + * @property-read int|null $fields_count + * @property-read \Illuminate\Database\Eloquent\Collection $steps + * @property-read int|null $steps_count + * @property-read \Illuminate\Database\Eloquent\Collection $submissions + * @property-read int|null $submissions_count + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm onlyTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm query() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationForm withoutTrashed() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationForm {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationFormAuthentication + * + * @property-read EventRegistrationForm $submissible + * @property-read \AdvisingApp\MeetingCenter\Models\EventAttendee|null $author + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormAuthentication newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormAuthentication newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormAuthentication query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationFormAuthentication {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationFormField + * + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep $step + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationForm $submissible + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormField newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormField newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormField query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationFormField {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationFormStep + * + * @property-read \Illuminate\Database\Eloquent\Collection $fields + * @property-read int|null $fields_count + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationForm $submissible + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormStep newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormStep newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormStep query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationFormStep {} +} + +namespace AdvisingApp\MeetingCenter\Models{ +/** + * AdvisingApp\MeetingCenter\Models\EventRegistrationFormSubmission + * + * @property \AdvisingApp\Form\Enums\FormSubmissionRequestDeliveryMethod $request_method + * @property \AdvisingApp\MeetingCenter\Enums\EventAttendeeStatus $attendee_status + * @property-read \AdvisingApp\MeetingCenter\Models\EventAttendee|null $author + * @property-read \Illuminate\Database\Eloquent\Collection $fields + * @property-read int|null $fields_count + * @property-read \App\Models\User $requester + * @property-read \AdvisingApp\MeetingCenter\Models\EventRegistrationForm $submissible + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormSubmission newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormSubmission newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|EventRegistrationFormSubmission query() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperEventRegistrationFormSubmission {} +} + namespace AdvisingApp\Notification\Models{ /** * AdvisingApp\Notification\Models\OutboundDeliverable From ebdd78ae5d67c16d5623ea9245c185fc97f5c36c Mon Sep 17 00:00:00 2001 From: mxm1070 Date: Thu, 4 Jan 2024 18:08:11 +0000 Subject: [PATCH 125/152] chore: fix enforcement of copyright on all files --- .../form/src/Actions/ResolveBlockRegistry.php | 34 +++++++++++++++++++ .../Blocks/LikertScaleSurveyBlock.php | 34 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/app-modules/form/src/Actions/ResolveBlockRegistry.php b/app-modules/form/src/Actions/ResolveBlockRegistry.php index 7106088932..daba532442 100644 --- a/app-modules/form/src/Actions/ResolveBlockRegistry.php +++ b/app-modules/form/src/Actions/ResolveBlockRegistry.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Form\Actions; use AdvisingApp\Form\Models\Form; diff --git a/app-modules/survey/src/Filament/Blocks/LikertScaleSurveyBlock.php b/app-modules/survey/src/Filament/Blocks/LikertScaleSurveyBlock.php index e98c8f8f85..2ade068f1f 100644 --- a/app-modules/survey/src/Filament/Blocks/LikertScaleSurveyBlock.php +++ b/app-modules/survey/src/Filament/Blocks/LikertScaleSurveyBlock.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\Survey\Filament\Blocks; use AdvisingApp\Form\Models\SubmissibleField; From 337cec3d822b9b03985dd4bc9f80ea5384e1d781 Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Thu, 4 Jan 2024 13:19:23 -0500 Subject: [PATCH 126/152] Fix merge. --- .../src/Actions/GenerateFormKitSchema.php | 31 +++---------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/app-modules/form/src/Actions/GenerateFormKitSchema.php b/app-modules/form/src/Actions/GenerateFormKitSchema.php index 36d010730a..afa79de3ce 100644 --- a/app-modules/form/src/Actions/GenerateFormKitSchema.php +++ b/app-modules/form/src/Actions/GenerateFormKitSchema.php @@ -44,31 +44,6 @@ class GenerateFormKitSchema { public function __invoke(Submissible $submissible): array { - if ($submissible->is_wizard) { - $submissible->loadMissing([ - 'steps' => [ - 'fields', - ], - ]); - - $content = $this->wizardContent($submissible); - } else { - $submissible->loadMissing([ - 'fields', - ]); - - $blocks = app(ResolveBlockRegistry::class)($submissible); - - $content = [ - ...$this->content($blocks, $submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), - [ - '$formkit' => 'submit', - 'label' => 'Submit', - 'disabled' => '$get(form).state.valid !== true', - ], - ]; - } - return [ '$cmp' => 'FormKit', 'props' => [ @@ -78,7 +53,7 @@ public function __invoke(Submissible $submissible): array 'plugins' => '$plugins', 'actions' => false, ], - 'children' => $content, + 'children' => $this->generateContent($submissible), ]; } @@ -286,8 +261,10 @@ protected function generateContent(Submissible $submissible): array 'fields', ]); + $blocks = app(ResolveBlockRegistry::class)($submissible); + $content = [ - ...$this->content($submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), + ...$this->content($blocks, $submissible->content['content'] ?? [], $submissible->fields->keyBy('id')), [ '$formkit' => 'submit', 'label' => 'Submit', From a687e4515e3ce87f8197d9f24519c99c03aea125 Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Thu, 4 Jan 2024 14:21:11 -0500 Subject: [PATCH 127/152] Feedback. --- .../factories/AnalyticsResourceFactory.php | 19 ++++++------------- ...72758_create_analytics_resources_table.php | 4 ++-- .../AnalyticsResourceCategoryResource.php | 6 ------ .../Pages/CreateAnalyticsResourceCategory.php | 3 +-- .../Pages/ListAnalyticsResourceCategories.php | 2 -- .../Resources/AnalyticsResourceResource.php | 6 ------ .../Pages/CreateAnalyticsResource.php | 8 +++++--- .../Pages/EditAnalyticsResource.php | 5 ++++- .../AnalyticsResourceSourceResource.php | 6 ------ .../Pages/ListAnalyticsResourceSources.php | 2 -- database/seeders/DemoDatabaseSeeder.php | 4 ++++ 11 files changed, 22 insertions(+), 43 deletions(-) diff --git a/app-modules/analytics/database/factories/AnalyticsResourceFactory.php b/app-modules/analytics/database/factories/AnalyticsResourceFactory.php index 552fb5c575..4b8d382e63 100644 --- a/app-modules/analytics/database/factories/AnalyticsResourceFactory.php +++ b/app-modules/analytics/database/factories/AnalyticsResourceFactory.php @@ -57,19 +57,12 @@ public function definition(): array 'url' => fake()->optional()->url(), 'is_active' => fake()->boolean(), 'is_included_in_data_portal' => fake()->boolean(), + 'source_id' => fake()->optional()->randomElement([ + AnalyticsResourceSource::query()->inRandomOrder()->first() ?? AnalyticsResourceSource::factory()->create(), + ]), + 'category_id' => fake()->randomElement([ + AnalyticsResourceCategory::query()->inRandomOrder()->first() ?? AnalyticsResourceCategory::factory()->create(), + ]), ]; } - - public function configure(): AnalyticsResourceFactory|Factory - { - return $this->afterMaking(function (AnalyticsResource $analyticsResource) { - $analyticsResource - ->source() - ->associate(fake()->optional()->randomElement([AnalyticsResourceSource::inRandomOrder()->first() ?? AnalyticsResourceSource::factory()->create()])); - - $analyticsResource - ->category() - ->associate(fake()->randomElement([AnalyticsResourceCategory::inRandomOrder()->first() ?? AnalyticsResourceCategory::factory()->create()])); - }); - } } diff --git a/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php b/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php index b74554ed12..7fdb1498bb 100644 --- a/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php +++ b/app-modules/analytics/database/migrations/2024_01_02_172758_create_analytics_resources_table.php @@ -47,8 +47,8 @@ public function up(): void $table->string('name')->unique(); $table->longText('description')->nullable(); $table->string('url')->nullable(); - $table->boolean('is_active'); - $table->boolean('is_included_in_data_portal'); + $table->boolean('is_active')->default(false); + $table->boolean('is_included_in_data_portal')->default(false); $table->foreignUuid('source_id')->nullable()->constrained('analytics_resource_sources'); $table->foreignUuid('category_id')->constrained('analytics_resource_categories'); diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php index bd3dfa5b7e..403d91b9b1 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource.php @@ -53,12 +53,6 @@ class AnalyticsResourceCategoryResource extends Resource protected static ?int $navigationSort = 20; - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php index 47848d7bf8..f20f590c1c 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/CreateAnalyticsResourceCategory.php @@ -58,8 +58,7 @@ public function form(Form $form): Form ->schema([ TextInput::make('name') ->required() - ->string() - ->unique(ignoreRecord: true), + ->string(), Select::make('classification') ->options(AnalyticsResourceCategoryClassification::class) ->enum(AnalyticsResourceCategoryClassification::class) diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php index 336b1cfb3b..6d745b21e8 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceCategoryResource/Pages/ListAnalyticsResourceCategories.php @@ -66,8 +66,6 @@ public function table(Table $table): Table ->counts('resources') ->sortable(), ]) - ->filters([ - ]) ->actions([ ViewAction::make(), EditAction::make(), diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php index 3caa81cfa8..f9b48f5546 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource.php @@ -54,12 +54,6 @@ class AnalyticsResourceResource extends Resource protected static ?string $navigationLabel = 'Analytics Portal'; - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php index 02bc4e0a9b..b43641e31e 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/CreateAnalyticsResource.php @@ -43,6 +43,7 @@ use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\CreateRecord; +use AdvisingApp\Analytics\Models\AnalyticsResourceCategory; use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource; @@ -59,14 +60,15 @@ public function form(Form $form): Form ->schema([ TextInput::make('name') ->required() - ->string() - ->unique(ignoreRecord: true), + ->string(), Textarea::make('description') ->nullable() ->string(), Select::make('category_id') ->relationship('category', 'name') - ->required(), + ->required() + ->live() + ->helperText(fn ($state) => AnalyticsResourceCategory::find($state)?->description), Select::make('source_id') ->relationship('source', 'name'), TextInput::make('url') diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php index 25d29ab84f..4e0f453a45 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceResource/Pages/EditAnalyticsResource.php @@ -44,6 +44,7 @@ use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Resources\Pages\EditRecord; +use AdvisingApp\Analytics\Models\AnalyticsResourceCategory; use Filament\Forms\Components\SpatieMediaLibraryFileUpload; use AdvisingApp\Analytics\Filament\Resources\AnalyticsResourceResource; @@ -67,7 +68,9 @@ public function form(Form $form): Form ->string(), Select::make('category_id') ->relationship('category', 'name') - ->required(), + ->required() + ->live() + ->helperText(fn ($state) => AnalyticsResourceCategory::find($state)?->description), Select::make('source_id') ->relationship('source', 'name'), TextInput::make('url') diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php index 6f2c859d21..89274b7902 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource.php @@ -53,12 +53,6 @@ class AnalyticsResourceSourceResource extends Resource protected static ?int $navigationSort = 19; - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php index 67c75d32e1..08912cc188 100644 --- a/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php +++ b/app-modules/analytics/src/Filament/Resources/AnalyticsResourceSourceResource/Pages/ListAnalyticsResourceSources.php @@ -64,8 +64,6 @@ public function table(Table $table): Table ->counts('resources') ->sortable(), ]) - ->filters([ - ]) ->actions([ ViewAction::make(), EditAction::make(), diff --git a/database/seeders/DemoDatabaseSeeder.php b/database/seeders/DemoDatabaseSeeder.php index e109ae0565..3f1eea39df 100644 --- a/database/seeders/DemoDatabaseSeeder.php +++ b/database/seeders/DemoDatabaseSeeder.php @@ -45,8 +45,10 @@ use AdvisingApp\Consent\Database\Seeders\ConsentAgreementSeeder; use AdvisingApp\InventoryManagement\Database\Seeders\AssetSeeder; use AdvisingApp\Authorization\Console\Commands\SyncRolesAndPermissions; +use AdvisingApp\Analytics\Database\Seeders\AnalyticsResourceSourceSeeder; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseStatusSeeder; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseQualitySeeder; +use AdvisingApp\Analytics\Database\Seeders\AnalyticsResourceCategorySeeder; use AdvisingApp\KnowledgeBase\Database\Seeders\KnowledgeBaseCategorySeeder; use AdvisingApp\ServiceManagement\Database\Seeders\ServiceRequestTypeSeeder; use AdvisingApp\Application\Database\Seeders\ApplicationSubmissionStateSeeder; @@ -83,6 +85,8 @@ public function run(): void ...AssetSeeder::metadataSeeders(), AssetSeeder::class, MaintenanceProviderSeeder::class, + AnalyticsResourceSourceSeeder::class, + AnalyticsResourceCategorySeeder::class, ]); } } From 9e9eb3ddebb56f3943d871bcf2fbe75d43ce662c Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 19:28:35 +0000 Subject: [PATCH 128/152] start fixing tests --- app-modules/alert/tests/AlertCreateTest.php | 5 +++-- .../tests/Actions/CareTeamCampaignTest.php | 11 ++++++----- .../CaseloadResource/CreateCaseloadTest.php | 3 ++- .../CaseloadResource/EditCaseloadTest.php | 3 ++- .../CaseloadResource/ListCaseloadsTest.php | 3 ++- .../EngagementFile/CreateEngagementFileTest.php | 3 ++- .../EngagementFile/EditEngagementFileTest.php | 3 ++- .../EngagementFile/ListEngagementFileTest.php | 3 ++- .../EngagementFile/ViewEngagementFileTest.php | 3 ++- .../CreateInteractionCampaignTest.php | 3 ++- .../ListInteractionCampaignsTest.php | 3 ++- .../CreateInteractionDriverTest.php | 3 ++- .../EditInteractionDriverTest.php | 3 ++- .../ListInteractionDriversTest.php | 3 ++- .../EditInteractionOutcomeTest.php | 3 ++- .../ListInteractionOutcomesTest.php | 3 ++- .../InteractionResource/CreateInteractionTest.php | 3 ++- .../InteractionResource/EditInteractionTest.php | 3 ++- .../InteractionResource/ListInteractionsTest.php | 3 ++- .../CreateInteractionStatusTest.php | 3 ++- .../EditInteractionStatusTest.php | 3 ++- .../ListInteractionStatusesTest.php | 3 ++- .../CreateInteractionTypeTest.php | 3 ++- .../EditInteractionTypeTest.php | 3 ++- .../ListInteractionTypesTest.php | 3 ++- .../tests/Prospect/CreateProspectTest.php | 2 +- .../prospect/tests/Prospect/EditProspectTest.php | 2 +- .../prospect/tests/Prospect/ListProspectTest.php | 4 ++-- .../prospect/tests/Prospect/ViewProspectTest.php | 2 +- .../ProspectSource/CreateProspectSourceTest.php | 5 ++++- .../ProspectSource/EditProspectSourceTest.php | 5 ++++- .../ProspectSource/ListProspectSourcesTest.php | 3 ++- .../ProspectSource/ViewProspectSourceTest.php | 3 ++- .../ProspectStatus/CreateProspectStatusTest.php | 3 ++- .../ProspectStatus/EditProspectStatusTest.php | 3 ++- .../ProspectStatus/ListProspectStatusesTest.php | 3 ++- .../ProspectStatus/ViewProspectStatusTest.php | 3 ++- .../ServiceRequest/CreateServiceRequestTest.php | 7 +++++-- .../ServiceRequest/EditServiceRequestTest.php | 5 +++-- .../ServiceRequest/ViewServiceRequestTest.php | 5 +++-- .../CreateServiceRequestUpdateTest.php | 5 +++-- .../EditServiceRequestUpdateTest.php | 5 +++-- .../ViewServiceRequestUpdateTest.php | 5 +++-- app-modules/task/tests/CreateTaskTest.php | 3 ++- app-modules/task/tests/EditTaskTest.php | 3 ++- app-modules/task/tests/ListTasksTest.php | 3 ++- database/factories/UserFactory.php | 15 +++++++++++++++ database/seeders/UsersTableSeeder.php | 6 +----- tests/Helpers.php | 8 +++----- 49 files changed, 125 insertions(+), 68 deletions(-) diff --git a/app-modules/alert/tests/AlertCreateTest.php b/app-modules/alert/tests/AlertCreateTest.php index b79cd874f3..3bc939474f 100644 --- a/app-modules/alert/tests/AlertCreateTest.php +++ b/app-modules/alert/tests/AlertCreateTest.php @@ -40,11 +40,12 @@ use function Pest\Laravel\actingAs; use Illuminate\Support\Facades\Notification; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\Alert\Notifications\AlertCreatedNotification; it('creates a subscription for the user that created the Alert', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user); @@ -60,7 +61,7 @@ it('dispatches the proper notifications to subscribers on created', function () { Notification::fake(); - $users = User::factory()->count(5)->create(); + $users = User::factory()->licensed(LicenseType::cases())->count(5)->create(); /** @var Student $student */ $student = Student::factory()->create(); diff --git a/app-modules/campaign/tests/Actions/CareTeamCampaignTest.php b/app-modules/campaign/tests/Actions/CareTeamCampaignTest.php index eaed91e6f3..028ab8721e 100644 --- a/app-modules/campaign/tests/Actions/CareTeamCampaignTest.php +++ b/app-modules/campaign/tests/Actions/CareTeamCampaignTest.php @@ -39,6 +39,7 @@ use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Collection; use AdvisingApp\Campaign\Models\CampaignAction; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\StudentDataModel\Models\Student; use AdvisingApp\Campaign\Enums\CampaignActionType; use AdvisingApp\CaseloadManagement\Models\Caseload; @@ -63,7 +64,7 @@ 'caseload_id' => $caseload->id, ]); - $users = User::factory()->count(3)->create(); + $users = User::factory()->licensed(LicenseType::cases())->count(3)->create(); $action = CampaignAction::factory() ->for($campaign, 'campaign') @@ -101,12 +102,12 @@ 'removePrior' => true, ], 'prior care team | prospects | remove prior false' => [ - 'priorCareTeam' => fn () => User::factory()->count(3)->create()->pluck('id')->toArray(), + 'priorCareTeam' => fn () => User::factory()->licensed(LicenseType::cases())->count(3)->create()->pluck('id')->toArray(), 'educatables' => fn () => Prospect::factory()->count(3)->create(), 'removePrior' => false, ], 'prior care team | prospects | remove prior true' => [ - 'priorCareTeam' => fn () => User::factory()->count(3)->create()->pluck('id')->toArray(), + 'priorCareTeam' => fn () => User::factory()->licensed(LicenseType::cases())->count(3)->create()->pluck('id')->toArray(), 'educatables' => fn () => Prospect::factory()->count(3)->create(), 'removePrior' => true, ], @@ -121,12 +122,12 @@ 'removePrior' => true, ], 'prior care team | students | remove prior false' => [ - 'priorCareTeam' => fn () => User::factory()->count(3)->create()->pluck('id')->toArray(), + 'priorCareTeam' => fn () => User::factory()->licensed(LicenseType::cases())->count(3)->create()->pluck('id')->toArray(), 'educatables' => fn () => Student::factory()->count(3)->create(), 'removePrior' => false, ], 'prior care team | students | remove prior true' => [ - 'priorCareTeam' => fn () => User::factory()->count(3)->create()->pluck('id')->toArray(), + 'priorCareTeam' => fn () => User::factory()->licensed(LicenseType::cases())->count(3)->create()->pluck('id')->toArray(), 'educatables' => fn () => Student::factory()->count(3)->create(), 'removePrior' => true, ], diff --git a/app-modules/caseload-management/tests/Filament/CaseloadResource/CreateCaseloadTest.php b/app-modules/caseload-management/tests/Filament/CaseloadResource/CreateCaseloadTest.php index c8bbe49653..8e82962450 100644 --- a/app-modules/caseload-management/tests/Filament/CaseloadResource/CreateCaseloadTest.php +++ b/app-modules/caseload-management/tests/Filament/CaseloadResource/CreateCaseloadTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\CaseloadManagement\Filament\Resources\CaseloadResource; test('CreateCaseload is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/caseload-management/tests/Filament/CaseloadResource/EditCaseloadTest.php b/app-modules/caseload-management/tests/Filament/CaseloadResource/EditCaseloadTest.php index cdf342645c..c600f855a1 100644 --- a/app-modules/caseload-management/tests/Filament/CaseloadResource/EditCaseloadTest.php +++ b/app-modules/caseload-management/tests/Filament/CaseloadResource/EditCaseloadTest.php @@ -38,13 +38,14 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\CaseloadManagement\Models\Caseload; use AdvisingApp\CaseloadManagement\Filament\Resources\CaseloadResource; test('EditCaseload is gated with proper access control', function () { $user = User::factory()->create(); - $caseload = Caseload::factory()->create(); + $caseload = Caseload::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/caseload-management/tests/Filament/CaseloadResource/ListCaseloadsTest.php b/app-modules/caseload-management/tests/Filament/CaseloadResource/ListCaseloadsTest.php index 8cf4e4ac3a..9a57532e80 100644 --- a/app-modules/caseload-management/tests/Filament/CaseloadResource/ListCaseloadsTest.php +++ b/app-modules/caseload-management/tests/Filament/CaseloadResource/ListCaseloadsTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\CaseloadManagement\Filament\Resources\CaseloadResource; test('ListCaseloads is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/engagement/tests/EngagementFile/CreateEngagementFileTest.php b/app-modules/engagement/tests/EngagementFile/CreateEngagementFileTest.php index a6946137f1..31760e3aca 100644 --- a/app-modules/engagement/tests/EngagementFile/CreateEngagementFileTest.php +++ b/app-modules/engagement/tests/EngagementFile/CreateEngagementFileTest.php @@ -39,6 +39,7 @@ use function Pest\Laravel\actingAs; use function Pest\Livewire\livewire; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Engagement\Filament\Resources\EngagementFileResource; // TODO: Add tests for the CreateEngagementFile @@ -49,7 +50,7 @@ // Permission Tests test('CreateEngagementFile is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/engagement/tests/EngagementFile/EditEngagementFileTest.php b/app-modules/engagement/tests/EngagementFile/EditEngagementFileTest.php index 3d475c68b8..5aeb12d8bf 100644 --- a/app-modules/engagement/tests/EngagementFile/EditEngagementFileTest.php +++ b/app-modules/engagement/tests/EngagementFile/EditEngagementFileTest.php @@ -39,6 +39,7 @@ use function Pest\Laravel\actingAs; use function Pest\Livewire\livewire; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Engagement\Models\EngagementFile; use AdvisingApp\Engagement\Filament\Resources\EngagementFileResource; @@ -50,7 +51,7 @@ // Permission Tests test('EditEngagementFile is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $engagementFile = EngagementFile::factory()->create(); diff --git a/app-modules/engagement/tests/EngagementFile/ListEngagementFileTest.php b/app-modules/engagement/tests/EngagementFile/ListEngagementFileTest.php index 21ae7e4d23..c27e6f846e 100644 --- a/app-modules/engagement/tests/EngagementFile/ListEngagementFileTest.php +++ b/app-modules/engagement/tests/EngagementFile/ListEngagementFileTest.php @@ -38,6 +38,7 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Engagement\Filament\Resources\EngagementFileResource; // TODO: Add tests for the ListEngagementFiles @@ -48,7 +49,7 @@ // Permission Tests test('ListEngagementFiles is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/engagement/tests/EngagementFile/ViewEngagementFileTest.php b/app-modules/engagement/tests/EngagementFile/ViewEngagementFileTest.php index 92df52df94..ddccbb5c23 100644 --- a/app-modules/engagement/tests/EngagementFile/ViewEngagementFileTest.php +++ b/app-modules/engagement/tests/EngagementFile/ViewEngagementFileTest.php @@ -38,6 +38,7 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Engagement\Models\EngagementFile; use AdvisingApp\Engagement\Filament\Resources\EngagementFileResource; @@ -47,7 +48,7 @@ // Permission Tests test('ViewEngagementFile is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $engagementFile = EngagementFile::factory()->create(); diff --git a/app-modules/interaction/tests/Filament/InteractionCampaignResource/CreateInteractionCampaignTest.php b/app-modules/interaction/tests/Filament/InteractionCampaignResource/CreateInteractionCampaignTest.php index b6aad91bbc..e724614596 100644 --- a/app-modules/interaction/tests/Filament/InteractionCampaignResource/CreateInteractionCampaignTest.php +++ b/app-modules/interaction/tests/Filament/InteractionCampaignResource/CreateInteractionCampaignTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionCampaignResource; test('CreateInteractionCampaign is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionCampaignResource/ListInteractionCampaignsTest.php b/app-modules/interaction/tests/Filament/InteractionCampaignResource/ListInteractionCampaignsTest.php index 4084b20f60..fe9bf21414 100644 --- a/app-modules/interaction/tests/Filament/InteractionCampaignResource/ListInteractionCampaignsTest.php +++ b/app-modules/interaction/tests/Filament/InteractionCampaignResource/ListInteractionCampaignsTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionCampaignResource; test('ListInteractionCampaigns is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionDriverResource/CreateInteractionDriverTest.php b/app-modules/interaction/tests/Filament/InteractionDriverResource/CreateInteractionDriverTest.php index 59a89f79df..7cd4c55155 100644 --- a/app-modules/interaction/tests/Filament/InteractionDriverResource/CreateInteractionDriverTest.php +++ b/app-modules/interaction/tests/Filament/InteractionDriverResource/CreateInteractionDriverTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionDriverResource; test('CreateInteractionDriver is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionDriverResource/EditInteractionDriverTest.php b/app-modules/interaction/tests/Filament/InteractionDriverResource/EditInteractionDriverTest.php index 3ae7f08abf..6b57807c9d 100644 --- a/app-modules/interaction/tests/Filament/InteractionDriverResource/EditInteractionDriverTest.php +++ b/app-modules/interaction/tests/Filament/InteractionDriverResource/EditInteractionDriverTest.php @@ -38,11 +38,12 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Models\InteractionDriver; use AdvisingApp\Interaction\Filament\Resources\InteractionDriverResource; test('EditInteractionDriver is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $driver = InteractionDriver::factory()->create(); diff --git a/app-modules/interaction/tests/Filament/InteractionDriverResource/ListInteractionDriversTest.php b/app-modules/interaction/tests/Filament/InteractionDriverResource/ListInteractionDriversTest.php index 7914ca12c8..a22de34dc3 100644 --- a/app-modules/interaction/tests/Filament/InteractionDriverResource/ListInteractionDriversTest.php +++ b/app-modules/interaction/tests/Filament/InteractionDriverResource/ListInteractionDriversTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionDriverResource; test('ListInteractionDrivers is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionOutcomeResource/EditInteractionOutcomeTest.php b/app-modules/interaction/tests/Filament/InteractionOutcomeResource/EditInteractionOutcomeTest.php index 31b5692b43..3f48f6db79 100644 --- a/app-modules/interaction/tests/Filament/InteractionOutcomeResource/EditInteractionOutcomeTest.php +++ b/app-modules/interaction/tests/Filament/InteractionOutcomeResource/EditInteractionOutcomeTest.php @@ -38,11 +38,12 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Models\InteractionOutcome; use AdvisingApp\Interaction\Filament\Resources\InteractionOutcomeResource; test('EditInteractionOutcome is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $outcome = InteractionOutcome::factory()->create(); diff --git a/app-modules/interaction/tests/Filament/InteractionOutcomeResource/ListInteractionOutcomesTest.php b/app-modules/interaction/tests/Filament/InteractionOutcomeResource/ListInteractionOutcomesTest.php index 56927ac181..fa640865b2 100644 --- a/app-modules/interaction/tests/Filament/InteractionOutcomeResource/ListInteractionOutcomesTest.php +++ b/app-modules/interaction/tests/Filament/InteractionOutcomeResource/ListInteractionOutcomesTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionOutcomeResource; test('ListInteractionOutcomes is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionResource/CreateInteractionTest.php b/app-modules/interaction/tests/Filament/InteractionResource/CreateInteractionTest.php index 1fa7606285..63739db0f5 100644 --- a/app-modules/interaction/tests/Filament/InteractionResource/CreateInteractionTest.php +++ b/app-modules/interaction/tests/Filament/InteractionResource/CreateInteractionTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionResource; test('CreateInteraction is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionResource/EditInteractionTest.php b/app-modules/interaction/tests/Filament/InteractionResource/EditInteractionTest.php index 59f50d40cb..25e2c1f7a3 100644 --- a/app-modules/interaction/tests/Filament/InteractionResource/EditInteractionTest.php +++ b/app-modules/interaction/tests/Filament/InteractionResource/EditInteractionTest.php @@ -39,10 +39,11 @@ use function Pest\Laravel\actingAs; use AdvisingApp\Interaction\Models\Interaction; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionResource; test('EditInteraction is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $interaction = Interaction::factory()->create(); diff --git a/app-modules/interaction/tests/Filament/InteractionResource/ListInteractionsTest.php b/app-modules/interaction/tests/Filament/InteractionResource/ListInteractionsTest.php index b50a63d8e6..5d069b3a2a 100644 --- a/app-modules/interaction/tests/Filament/InteractionResource/ListInteractionsTest.php +++ b/app-modules/interaction/tests/Filament/InteractionResource/ListInteractionsTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionResource; test('ListInteractions is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionStatusResource/CreateInteractionStatusTest.php b/app-modules/interaction/tests/Filament/InteractionStatusResource/CreateInteractionStatusTest.php index e28d1969fb..a2cf22e777 100644 --- a/app-modules/interaction/tests/Filament/InteractionStatusResource/CreateInteractionStatusTest.php +++ b/app-modules/interaction/tests/Filament/InteractionStatusResource/CreateInteractionStatusTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionStatusResource; test('CreateInteractionStatus is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionStatusResource/EditInteractionStatusTest.php b/app-modules/interaction/tests/Filament/InteractionStatusResource/EditInteractionStatusTest.php index 7229de5568..04047a4f83 100644 --- a/app-modules/interaction/tests/Filament/InteractionStatusResource/EditInteractionStatusTest.php +++ b/app-modules/interaction/tests/Filament/InteractionStatusResource/EditInteractionStatusTest.php @@ -38,11 +38,12 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Models\InteractionStatus; use AdvisingApp\Interaction\Filament\Resources\InteractionStatusResource; test('EditInteractionStatus is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $status = InteractionStatus::factory()->create(); diff --git a/app-modules/interaction/tests/Filament/InteractionStatusResource/ListInteractionStatusesTest.php b/app-modules/interaction/tests/Filament/InteractionStatusResource/ListInteractionStatusesTest.php index d1021a93f3..0e2aa26520 100644 --- a/app-modules/interaction/tests/Filament/InteractionStatusResource/ListInteractionStatusesTest.php +++ b/app-modules/interaction/tests/Filament/InteractionStatusResource/ListInteractionStatusesTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionStatusResource; test('ListInteractionStatuses is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionTypeResource/CreateInteractionTypeTest.php b/app-modules/interaction/tests/Filament/InteractionTypeResource/CreateInteractionTypeTest.php index 4c005db8ff..8d7f9ee4b5 100644 --- a/app-modules/interaction/tests/Filament/InteractionTypeResource/CreateInteractionTypeTest.php +++ b/app-modules/interaction/tests/Filament/InteractionTypeResource/CreateInteractionTypeTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionTypeResource; test('CreateInteractionType is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/interaction/tests/Filament/InteractionTypeResource/EditInteractionTypeTest.php b/app-modules/interaction/tests/Filament/InteractionTypeResource/EditInteractionTypeTest.php index 6978750634..d69d3bef8e 100644 --- a/app-modules/interaction/tests/Filament/InteractionTypeResource/EditInteractionTypeTest.php +++ b/app-modules/interaction/tests/Filament/InteractionTypeResource/EditInteractionTypeTest.php @@ -38,11 +38,12 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Models\InteractionType; use AdvisingApp\Interaction\Filament\Resources\InteractionTypeResource; test('EditInteractionType is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $type = InteractionType::factory()->create(); diff --git a/app-modules/interaction/tests/Filament/InteractionTypeResource/ListInteractionTypesTest.php b/app-modules/interaction/tests/Filament/InteractionTypeResource/ListInteractionTypesTest.php index 2f8e716d07..439bd249ef 100644 --- a/app-modules/interaction/tests/Filament/InteractionTypeResource/ListInteractionTypesTest.php +++ b/app-modules/interaction/tests/Filament/InteractionTypeResource/ListInteractionTypesTest.php @@ -38,10 +38,11 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Interaction\Filament\Resources\InteractionTypeResource; test('ListInteractionTypes is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/prospect/tests/Prospect/CreateProspectTest.php b/app-modules/prospect/tests/Prospect/CreateProspectTest.php index c9e2791351..768bb0fb48 100644 --- a/app-modules/prospect/tests/Prospect/CreateProspectTest.php +++ b/app-modules/prospect/tests/Prospect/CreateProspectTest.php @@ -55,7 +55,7 @@ // Permission Tests test('CreateProspect is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); actingAs($user) ->get( diff --git a/app-modules/prospect/tests/Prospect/EditProspectTest.php b/app-modules/prospect/tests/Prospect/EditProspectTest.php index 5afffddf31..e2402565e5 100644 --- a/app-modules/prospect/tests/Prospect/EditProspectTest.php +++ b/app-modules/prospect/tests/Prospect/EditProspectTest.php @@ -51,7 +51,7 @@ // Permission Tests test('EditProspect is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); $prospect = Prospect::factory()->create(); diff --git a/app-modules/prospect/tests/Prospect/ListProspectTest.php b/app-modules/prospect/tests/Prospect/ListProspectTest.php index 07d5161ae1..7753ee0cbe 100644 --- a/app-modules/prospect/tests/Prospect/ListProspectTest.php +++ b/app-modules/prospect/tests/Prospect/ListProspectTest.php @@ -52,7 +52,7 @@ // Permission Tests test('ListProspects is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); actingAs($user) ->get( @@ -68,7 +68,7 @@ }); test('ListProspects can bulk update characteristics', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); $user->givePermissionTo('prospect.view-any'); diff --git a/app-modules/prospect/tests/Prospect/ViewProspectTest.php b/app-modules/prospect/tests/Prospect/ViewProspectTest.php index 739265db92..cc9a5cd866 100644 --- a/app-modules/prospect/tests/Prospect/ViewProspectTest.php +++ b/app-modules/prospect/tests/Prospect/ViewProspectTest.php @@ -47,7 +47,7 @@ // Permission Tests test('ViewProspect is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); $prospect = Prospect::factory()->create(); diff --git a/app-modules/prospect/tests/ProspectSource/CreateProspectSourceTest.php b/app-modules/prospect/tests/ProspectSource/CreateProspectSourceTest.php index 97475a9155..2511e40cbb 100644 --- a/app-modules/prospect/tests/ProspectSource/CreateProspectSourceTest.php +++ b/app-modules/prospect/tests/ProspectSource/CreateProspectSourceTest.php @@ -39,6 +39,9 @@ use function Tests\asSuperAdmin; use function Pest\Laravel\actingAs; use function Pest\Livewire\livewire; + +use AdvisingApp\Prospect\Models\Prospect; + use function PHPUnit\Framework\assertCount; use function PHPUnit\Framework\assertEmpty; use function Pest\Laravel\assertDatabaseHas; @@ -85,7 +88,7 @@ // Permission Tests test('CreateProspectSource is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); actingAs($user) ->get( diff --git a/app-modules/prospect/tests/ProspectSource/EditProspectSourceTest.php b/app-modules/prospect/tests/ProspectSource/EditProspectSourceTest.php index 136227cca7..4bd6a4eb0a 100644 --- a/app-modules/prospect/tests/ProspectSource/EditProspectSourceTest.php +++ b/app-modules/prospect/tests/ProspectSource/EditProspectSourceTest.php @@ -39,6 +39,9 @@ use function Tests\asSuperAdmin; use function Pest\Laravel\actingAs; use function Pest\Livewire\livewire; + +use AdvisingApp\Prospect\Models\Prospect; + use function Pest\Laravel\assertDatabaseHas; use function PHPUnit\Framework\assertEquals; @@ -98,7 +101,7 @@ // Permission Tests test('EditProspectSource is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); $prospectSource = ProspectSource::factory()->create(); diff --git a/app-modules/prospect/tests/ProspectSource/ListProspectSourcesTest.php b/app-modules/prospect/tests/ProspectSource/ListProspectSourcesTest.php index abdc6732a6..26921ac0d1 100644 --- a/app-modules/prospect/tests/ProspectSource/ListProspectSourcesTest.php +++ b/app-modules/prospect/tests/ProspectSource/ListProspectSourcesTest.php @@ -40,6 +40,7 @@ use function Pest\Laravel\actingAs; use function Pest\Livewire\livewire; +use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\Prospect\Models\ProspectSource; use AdvisingApp\Prospect\Filament\Resources\ProspectSourceResource; use AdvisingApp\Prospect\Filament\Resources\ProspectSourceResource\Pages\ListProspectSources; @@ -82,7 +83,7 @@ // Permission Tests test('ListProspectSources is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); actingAs($user) ->get( diff --git a/app-modules/prospect/tests/ProspectSource/ViewProspectSourceTest.php b/app-modules/prospect/tests/ProspectSource/ViewProspectSourceTest.php index eafb748e8a..3952557805 100644 --- a/app-modules/prospect/tests/ProspectSource/ViewProspectSourceTest.php +++ b/app-modules/prospect/tests/ProspectSource/ViewProspectSourceTest.php @@ -39,6 +39,7 @@ use function Tests\asSuperAdmin; use function Pest\Laravel\actingAs; +use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\Prospect\Models\ProspectSource; use AdvisingApp\Prospect\Filament\Resources\ProspectSourceResource; @@ -63,7 +64,7 @@ // Permission Tests test('ViewProspectSource is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); $prospectSource = ProspectSource::factory()->create(); diff --git a/app-modules/prospect/tests/ProspectStatus/CreateProspectStatusTest.php b/app-modules/prospect/tests/ProspectStatus/CreateProspectStatusTest.php index adaa6257f1..3ca07cb9fd 100644 --- a/app-modules/prospect/tests/ProspectStatus/CreateProspectStatusTest.php +++ b/app-modules/prospect/tests/ProspectStatus/CreateProspectStatusTest.php @@ -41,6 +41,7 @@ use function Pest\Livewire\livewire; use Illuminate\Validation\Rules\Enum; +use AdvisingApp\Prospect\Models\Prospect; use function PHPUnit\Framework\assertCount; use function PHPUnit\Framework\assertEmpty; @@ -90,7 +91,7 @@ // Permission Tests test('CreateProspectStatus is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); actingAs($user) ->get( diff --git a/app-modules/prospect/tests/ProspectStatus/EditProspectStatusTest.php b/app-modules/prospect/tests/ProspectStatus/EditProspectStatusTest.php index cefae7ad4f..6070aa6c24 100644 --- a/app-modules/prospect/tests/ProspectStatus/EditProspectStatusTest.php +++ b/app-modules/prospect/tests/ProspectStatus/EditProspectStatusTest.php @@ -41,6 +41,7 @@ use function Pest\Livewire\livewire; use Illuminate\Validation\Rules\Enum; +use AdvisingApp\Prospect\Models\Prospect; use function Pest\Laravel\assertDatabaseHas; use function PHPUnit\Framework\assertEquals; @@ -109,7 +110,7 @@ // Permission Tests test('EditProspectStatus is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); $prospectStatus = ProspectStatus::factory()->create(); diff --git a/app-modules/prospect/tests/ProspectStatus/ListProspectStatusesTest.php b/app-modules/prospect/tests/ProspectStatus/ListProspectStatusesTest.php index 0b9c2c6c39..76cffacfe4 100644 --- a/app-modules/prospect/tests/ProspectStatus/ListProspectStatusesTest.php +++ b/app-modules/prospect/tests/ProspectStatus/ListProspectStatusesTest.php @@ -40,6 +40,7 @@ use function Pest\Laravel\actingAs; use function Pest\Livewire\livewire; +use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\Prospect\Models\ProspectStatus; use AdvisingApp\Prospect\Filament\Resources\ProspectStatusResource; use AdvisingApp\Prospect\Filament\Resources\ProspectStatusResource\Pages\ListProspectStatuses; @@ -92,7 +93,7 @@ // Permission Tests test('ListProspectStatuses is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); actingAs($user) ->get( diff --git a/app-modules/prospect/tests/ProspectStatus/ViewProspectStatusTest.php b/app-modules/prospect/tests/ProspectStatus/ViewProspectStatusTest.php index 720cf591b6..757ee2b8ac 100644 --- a/app-modules/prospect/tests/ProspectStatus/ViewProspectStatusTest.php +++ b/app-modules/prospect/tests/ProspectStatus/ViewProspectStatusTest.php @@ -39,6 +39,7 @@ use function Tests\asSuperAdmin; use function Pest\Laravel\actingAs; +use AdvisingApp\Prospect\Models\Prospect; use AdvisingApp\Prospect\Models\ProspectStatus; use AdvisingApp\Prospect\Filament\Resources\ProspectStatusResource; @@ -67,7 +68,7 @@ // Permission Tests test('ViewProspectStatus is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(Prospect::getLicenseType())->create(); $prospectStatus = ProspectStatus::factory()->create(); diff --git a/app-modules/service-management/tests/ServiceRequest/CreateServiceRequestTest.php b/app-modules/service-management/tests/ServiceRequest/CreateServiceRequestTest.php index 66779f517e..c24c45bb55 100644 --- a/app-modules/service-management/tests/ServiceRequest/CreateServiceRequestTest.php +++ b/app-modules/service-management/tests/ServiceRequest/CreateServiceRequestTest.php @@ -44,6 +44,9 @@ use function Pest\Livewire\livewire; use function PHPUnit\Framework\assertCount; use function Pest\Laravel\assertDatabaseHas; + +use AdvisingApp\Authorization\Enums\LicenseType; + use function Pest\Laravel\assertDatabaseMissing; use AdvisingApp\ServiceManagement\Models\ServiceRequest; @@ -136,7 +139,7 @@ // Permission Tests test('CreateServiceRequest is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( @@ -194,7 +197,7 @@ $settings->save(); - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/service-management/tests/ServiceRequest/EditServiceRequestTest.php b/app-modules/service-management/tests/ServiceRequest/EditServiceRequestTest.php index 366aeea70a..88046f8c1a 100644 --- a/app-modules/service-management/tests/ServiceRequest/EditServiceRequestTest.php +++ b/app-modules/service-management/tests/ServiceRequest/EditServiceRequestTest.php @@ -44,6 +44,7 @@ use function Pest\Livewire\livewire; use function Pest\Laravel\assertDatabaseHas; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\ServiceManagement\Models\ServiceRequest; use AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestResource; use AdvisingApp\ServiceManagement\Tests\RequestFactories\EditServiceRequestRequestFactory; @@ -147,7 +148,7 @@ // Permission Tests test('EditServiceRequest is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $serviceRequest = ServiceRequest::factory()->create(); @@ -213,7 +214,7 @@ $settings->save(); - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $user->givePermissionTo('service_request.view-any'); $user->givePermissionTo('service_request.*.update'); diff --git a/app-modules/service-management/tests/ServiceRequest/ViewServiceRequestTest.php b/app-modules/service-management/tests/ServiceRequest/ViewServiceRequestTest.php index 4038d381fe..7ead04a87b 100644 --- a/app-modules/service-management/tests/ServiceRequest/ViewServiceRequestTest.php +++ b/app-modules/service-management/tests/ServiceRequest/ViewServiceRequestTest.php @@ -42,6 +42,7 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\ServiceManagement\Models\ServiceRequest; use AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestResource; @@ -78,7 +79,7 @@ // Permission Tests test('ViewServiceRequest is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $serviceRequest = ServiceRequest::factory()->create(); @@ -107,7 +108,7 @@ $settings->save(); - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $user->givePermissionTo('service_request.view-any'); $user->givePermissionTo('service_request.*.view'); diff --git a/app-modules/service-management/tests/ServiceRequestUpdate/CreateServiceRequestUpdateTest.php b/app-modules/service-management/tests/ServiceRequestUpdate/CreateServiceRequestUpdateTest.php index afb7b9766e..6b6894cbbd 100644 --- a/app-modules/service-management/tests/ServiceRequestUpdate/CreateServiceRequestUpdateTest.php +++ b/app-modules/service-management/tests/ServiceRequestUpdate/CreateServiceRequestUpdateTest.php @@ -49,6 +49,7 @@ use function PHPUnit\Framework\assertEmpty; use function Pest\Laravel\assertDatabaseHas; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Notification\Events\TriggeredAutoSubscription; use AdvisingApp\ServiceManagement\Models\ServiceRequestUpdate; use AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestUpdateResource; @@ -112,7 +113,7 @@ // Preventing the Subscription creation for now Event::fake([TriggeredAutoSubscription::class]); - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( @@ -149,7 +150,7 @@ $settings->save(); - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $user->givePermissionTo('service_request_update.view-any'); $user->givePermissionTo('service_request_update.create'); diff --git a/app-modules/service-management/tests/ServiceRequestUpdate/EditServiceRequestUpdateTest.php b/app-modules/service-management/tests/ServiceRequestUpdate/EditServiceRequestUpdateTest.php index 46f0e55065..ec01078464 100644 --- a/app-modules/service-management/tests/ServiceRequestUpdate/EditServiceRequestUpdateTest.php +++ b/app-modules/service-management/tests/ServiceRequestUpdate/EditServiceRequestUpdateTest.php @@ -48,6 +48,7 @@ use function Pest\Laravel\assertDatabaseHas; use function PHPUnit\Framework\assertEquals; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\ServiceManagement\Models\ServiceRequestUpdate; use AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestUpdateResource; use AdvisingApp\ServiceManagement\Tests\RequestFactories\EditServiceRequestUpdateRequestFactory; @@ -112,7 +113,7 @@ // Permission Tests test('EditServiceRequestUpdate is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $serviceRequestUpdate = ServiceRequestUpdate::factory()->create(); @@ -160,7 +161,7 @@ $settings->save(); - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $user->givePermissionTo('service_request_update.view-any'); $user->givePermissionTo('service_request_update.*.update'); diff --git a/app-modules/service-management/tests/ServiceRequestUpdate/ViewServiceRequestUpdateTest.php b/app-modules/service-management/tests/ServiceRequestUpdate/ViewServiceRequestUpdateTest.php index 78e59ec193..ca2bc0e307 100644 --- a/app-modules/service-management/tests/ServiceRequestUpdate/ViewServiceRequestUpdateTest.php +++ b/app-modules/service-management/tests/ServiceRequestUpdate/ViewServiceRequestUpdateTest.php @@ -42,6 +42,7 @@ use function Pest\Laravel\actingAs; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\ServiceManagement\Models\ServiceRequestUpdate; use AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestUpdateResource; @@ -72,7 +73,7 @@ // Permission Tests test('ViewServiceRequestUpdate is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $serviceRequestUpdate = ServiceRequestUpdate::factory()->create(); @@ -101,7 +102,7 @@ $settings->save(); - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $user->givePermissionTo('service_request_update.view-any'); $user->givePermissionTo('service_request_update.*.view'); diff --git a/app-modules/task/tests/CreateTaskTest.php b/app-modules/task/tests/CreateTaskTest.php index bf5bdca811..3b57181f24 100644 --- a/app-modules/task/tests/CreateTaskTest.php +++ b/app-modules/task/tests/CreateTaskTest.php @@ -39,6 +39,7 @@ use function Pest\Laravel\actingAs; use function Pest\Livewire\livewire; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Task\Filament\Resources\TaskResource; // TODO: Write CreateTask page tests @@ -49,7 +50,7 @@ // Permission Tests test('CreateTask is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/app-modules/task/tests/EditTaskTest.php b/app-modules/task/tests/EditTaskTest.php index f8b3eddcbd..e19a1e9fc4 100644 --- a/app-modules/task/tests/EditTaskTest.php +++ b/app-modules/task/tests/EditTaskTest.php @@ -40,6 +40,7 @@ use function Pest\Laravel\actingAs; use function Pest\Livewire\livewire; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Task\Filament\Resources\TaskResource; use AdvisingApp\Task\Tests\RequestFactories\EditTaskRequestFactory; @@ -51,7 +52,7 @@ // Permission Tests test('EditTask is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); $task = Task::factory()->create(); diff --git a/app-modules/task/tests/ListTasksTest.php b/app-modules/task/tests/ListTasksTest.php index 76c6bbfde3..ca3121f9f7 100644 --- a/app-modules/task/tests/ListTasksTest.php +++ b/app-modules/task/tests/ListTasksTest.php @@ -44,6 +44,7 @@ use function Pest\Livewire\livewire; use AdvisingApp\Task\Enums\TaskStatus; +use AdvisingApp\Authorization\Enums\LicenseType; use AdvisingApp\Task\Filament\Resources\TaskResource; use AdvisingApp\Task\Filament\Resources\TaskResource\Pages\ListTasks; @@ -104,7 +105,7 @@ // Permission Tests test('ListTasks is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); actingAs($user) ->get( diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index eec1f36a20..c735828c12 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -36,7 +36,10 @@ namespace Database\Factories; +use App\Models\User; +use Illuminate\Support\Arr; use Illuminate\Support\Str; +use AdvisingApp\Authorization\Enums\LicenseType; use Illuminate\Database\Eloquent\Factories\Factory; /** @@ -76,4 +79,16 @@ public function external(): static 'is_external' => true, ]); } + + /** + * @param LicenseType | array $licenseTypes + */ + public function licensed(LicenseType | array $licenseTypes): static + { + return $this->afterCreating(function (User $user) use ($licenseTypes) { + foreach (Arr::wrap($licenseTypes) as $licenseType) { + $user->licenses()->create(['type' => $licenseType]); + } + }); + } } diff --git a/database/seeders/UsersTableSeeder.php b/database/seeders/UsersTableSeeder.php index f2fbc10378..12a17fa8b2 100644 --- a/database/seeders/UsersTableSeeder.php +++ b/database/seeders/UsersTableSeeder.php @@ -50,17 +50,13 @@ public function run(): void $superAdminRoleGroup = RoleGroup::where('name', 'Super Administrator')->firstOrFail(); if (app()->environment('local')) { - $superAdmin = User::factory()->create([ + $superAdmin = User::factory()->licensed(LicenseType::cases())->create([ 'name' => 'Super Admin', 'email' => 'sampleadmin@advising.app', 'password' => Hash::make('password'), ]); $superAdmin->roleGroups()->sync($superAdminRoleGroup); - - foreach (LicenseType::cases() as $licenseType) { - $superAdmin->licenses()->create(['type' => $licenseType]); - } } collect(config('internal-users.emails'))->each(function ($email) use ($superAdminRoleGroup) { diff --git a/tests/Helpers.php b/tests/Helpers.php index 83fe275081..4fff7b9a55 100644 --- a/tests/Helpers.php +++ b/tests/Helpers.php @@ -43,16 +43,14 @@ function asSuperAdmin(?User $user = null): TestCase { - $superAdmin = $user ?? User::factory()->create(); + $superAdmin = $user ?? User::factory() + ->licensed(LicenseType::cases()) + ->create(); $superAdminRoles = Role::superAdmin()->get(); $superAdmin->assignRole($superAdminRoles); - foreach (LicenseType::cases() as $licenseType) { - $superAdmin->licenses()->create(['type' => $licenseType]); - } - return test()->actingAs($superAdmin); } From db5387f5e1134217a9ddfd820f773f0c4fa967cb Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Thu, 4 Jan 2024 14:32:57 -0500 Subject: [PATCH 129/152] Fix composer. --- composer.lock | 485 +++++++++++++++++++++++++++----------------------- 1 file changed, 258 insertions(+), 227 deletions(-) diff --git a/composer.lock b/composer.lock index ba8789147b..6c1b8513bc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "19b34ef965a1ec4aa7ec0deb038e20bd", + "content-hash": "8f6e763126265c0256844dae31464a24", "packages": [ { "name": "amphp/amp", @@ -755,16 +755,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.295.4", + "version": "3.295.5", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "2372661db989fe4229abd95f4434b37252076d58" + "reference": "cd9d48ebfdfc8fb5f6df9fe95dced622287f3412" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2372661db989fe4229abd95f4434b37252076d58", - "reference": "2372661db989fe4229abd95f4434b37252076d58", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/cd9d48ebfdfc8fb5f6df9fe95dced622287f3412", + "reference": "cd9d48ebfdfc8fb5f6df9fe95dced622287f3412", "shasum": "" }, "require": { @@ -844,9 +844,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.295.4" + "source": "https://github.com/aws/aws-sdk-php/tree/3.295.5" }, - "time": "2023-12-29T19:07:49+00:00" + "time": "2024-01-03T19:12:43+00:00" }, { "name": "barryvdh/laravel-debugbar", @@ -2379,6 +2379,41 @@ "relative": true } }, + { + "name": "canyon-gbs/analytics", + "version": "1.0", + "dist": { + "type": "path", + "url": "app-modules/analytics", + "reference": "ee7fa00ee78ce3e31c49566043aaf89cca68ad6b" + }, + "require": { + "filament/filament": "^3.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "AdvisingApp\\Analytics\\Providers\\AnalyticsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "AdvisingApp\\Analytics\\": "src/", + "AdvisingApp\\Analytics\\Tests\\": "tests/", + "AdvisingApp\\Analytics\\Database\\Factories\\": "database/factories/", + "AdvisingApp\\Analytics\\Database\\Seeders\\": "database/seeders/" + } + }, + "license": [ + "proprietary" + ], + "transport-options": { + "symlink": true, + "relative": true + } + }, { "name": "canyon-gbs/inventory-management", "version": "1.0", @@ -4106,16 +4141,16 @@ }, { "name": "filament/actions", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203" + "reference": "fdbf3b543f9650d988e11813f1fe96d5e275b725" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/8f2a3df7c607a24c2433a3a71cb27b20a8dea203", - "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/fdbf3b543f9650d988e11813f1fe96d5e275b725", + "reference": "fdbf3b543f9650d988e11813f1fe96d5e275b725", "shasum": "" }, "require": { @@ -4153,20 +4188,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:29+00:00" + "time": "2024-01-02T23:07:25+00:00" }, { "name": "filament/filament", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "ae12dc49094560188a4289778a54773045880e44" + "reference": "4c6f1e1efdd3be5582af249055b893a09123777e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/ae12dc49094560188a4289778a54773045880e44", - "reference": "ae12dc49094560188a4289778a54773045880e44", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/4c6f1e1efdd3be5582af249055b893a09123777e", + "reference": "4c6f1e1efdd3be5582af249055b893a09123777e", "shasum": "" }, "require": { @@ -4218,20 +4253,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:35+00:00" + "time": "2024-01-04T12:28:40+00:00" }, { "name": "filament/forms", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506" + "reference": "23526fc23555d55d3fb3b9965efeba2ac04d6bbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/26e177a4b3a8ef7b8326d992bb5073f02220a506", - "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/23526fc23555d55d3fb3b9965efeba2ac04d6bbf", + "reference": "23526fc23555d55d3fb3b9965efeba2ac04d6bbf", "shasum": "" }, "require": { @@ -4274,20 +4309,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:30+00:00" + "time": "2024-01-04T12:28:34+00:00" }, { "name": "filament/infolists", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", - "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3" + "reference": "5bc1bfb47d34efd0ee7b3cee43d18996f99d9999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/infolists/zipball/66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", - "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", + "url": "https://api.github.com/repos/filamentphp/infolists/zipball/5bc1bfb47d34efd0ee7b3cee43d18996f99d9999", + "reference": "5bc1bfb47d34efd0ee7b3cee43d18996f99d9999", "shasum": "" }, "require": { @@ -4325,11 +4360,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-26T22:39:20+00:00" + "time": "2024-01-02T23:07:20+00:00" }, { "name": "filament/notifications", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", @@ -4381,7 +4416,7 @@ }, { "name": "filament/spatie-laravel-media-library-plugin", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-media-library-plugin.git", @@ -4418,7 +4453,7 @@ }, { "name": "filament/spatie-laravel-settings-plugin", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-settings-plugin.git", @@ -4465,16 +4500,16 @@ }, { "name": "filament/support", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "97792dad038a87b7a6bfe465c4f1913252c99017" + "reference": "bb580e362e66ae8071d8386e13841c1dc1a252b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/97792dad038a87b7a6bfe465c4f1913252c99017", - "reference": "97792dad038a87b7a6bfe465c4f1913252c99017", + "url": "https://api.github.com/repos/filamentphp/support/zipball/bb580e362e66ae8071d8386e13841c1dc1a252b4", + "reference": "bb580e362e66ae8071d8386e13841c1dc1a252b4", "shasum": "" }, "require": { @@ -4518,20 +4553,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-24T21:16:58+00:00" + "time": "2024-01-04T12:29:08+00:00" }, { "name": "filament/tables", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118" + "reference": "ba00ac1bf300756a4b240decf8c82d550ff2d024" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/e0701467097f6a82b235ad9f31e3c30ae1035118", - "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/ba00ac1bf300756a4b240decf8c82d550ff2d024", + "reference": "ba00ac1bf300756a4b240decf8c82d550ff2d024", "shasum": "" }, "require": { @@ -4571,20 +4606,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T17:31:59+00:00" + "time": "2024-01-04T12:29:06+00:00" }, { "name": "filament/widgets", - "version": "v3.1.31", + "version": "v3.1.34", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd" + "reference": "d9baa132c89f58f537b41cdfb319cc90d8a21e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", - "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/d9baa132c89f58f537b41cdfb319cc90d8a21e34", + "reference": "d9baa132c89f58f537b41cdfb319cc90d8a21e34", "shasum": "" }, "require": { @@ -4615,7 +4650,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T17:31:57+00:00" + "time": "2024-01-02T23:08:01+00:00" }, { "name": "firebase/php-jwt", @@ -5120,27 +5155,27 @@ }, { "name": "google/apiclient", - "version": "v2.15.1", + "version": "v2.15.3", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client.git", - "reference": "7a95ed29e4b6c6859d2d22300c5455a92e2622ad" + "reference": "e70273c06d18824de77e114247ae3102f8aec64d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/7a95ed29e4b6c6859d2d22300c5455a92e2622ad", - "reference": "7a95ed29e4b6c6859d2d22300c5455a92e2622ad", + "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/e70273c06d18824de77e114247ae3102f8aec64d", + "reference": "e70273c06d18824de77e114247ae3102f8aec64d", "shasum": "" }, "require": { "firebase/php-jwt": "~6.0", "google/apiclient-services": "~0.200", - "google/auth": "^1.28", - "guzzlehttp/guzzle": "~6.5||~7.0", + "google/auth": "^1.33", + "guzzlehttp/guzzle": "^6.5.8||^7.4.5", "guzzlehttp/psr7": "^1.8.4||^2.2.1", "monolog/monolog": "^2.9||^3.0", "php": "^7.4|^8.0", - "phpseclib/phpseclib": "^3.0.19" + "phpseclib/phpseclib": "^3.0.34" }, "require-dev": { "cache/filesystem-adapter": "^1.1", @@ -5148,7 +5183,7 @@ "phpcompatibility/php-compatibility": "^9.2", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", - "squizlabs/php_codesniffer": "^3.0", + "squizlabs/php_codesniffer": "^3.8", "symfony/css-selector": "~2.1", "symfony/dom-crawler": "~2.1" }, @@ -5183,13 +5218,13 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client/issues", - "source": "https://github.com/googleapis/google-api-php-client/tree/v2.15.1" + "source": "https://github.com/googleapis/google-api-php-client/tree/v2.15.3" }, - "time": "2023-09-13T21:46:39+00:00" + "time": "2024-01-04T19:15:22+00:00" }, { "name": "google/apiclient-services", - "version": "v0.329.0", + "version": "v0.330.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", @@ -5227,22 +5262,22 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.329.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.330.0" }, "time": "2023-12-24T01:02:15+00:00" }, { "name": "google/auth", - "version": "v1.33.0", + "version": "v1.34.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-auth-library-php.git", - "reference": "682dc6c30bb509953c9e43bb0960d901582da00b" + "reference": "155daeadfd2f09743f611ea493b828d382519575" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/682dc6c30bb509953c9e43bb0960d901582da00b", - "reference": "682dc6c30bb509953c9e43bb0960d901582da00b", + "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/155daeadfd2f09743f611ea493b828d382519575", + "reference": "155daeadfd2f09743f611ea493b828d382519575", "shasum": "" }, "require": { @@ -5285,9 +5320,9 @@ "support": { "docs": "https://googleapis.github.io/google-auth-library-php/main/", "issues": "https://github.com/googleapis/google-auth-library-php/issues", - "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.33.0" + "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.34.0" }, - "time": "2023-11-30T15:49:27+00:00" + "time": "2024-01-03T20:45:15+00:00" }, { "name": "graham-campbell/result-type", @@ -6881,16 +6916,16 @@ }, { "name": "lastdragon-ru/lara-asp-core", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-core.git", - "reference": "36108ae9dfc8764f601e2187b5a795a5071b19fc" + "reference": "77f40f8b6ce69df7ddf90d04dfbcff751ca8416d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-core/zipball/36108ae9dfc8764f601e2187b5a795a5071b19fc", - "reference": "36108ae9dfc8764f601e2187b5a795a5071b19fc", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-core/zipball/77f40f8b6ce69df7ddf90d04dfbcff751ca8416d", + "reference": "77f40f8b6ce69df7ddf90d04dfbcff751ca8416d", "shasum": "" }, "require": { @@ -6932,20 +6967,20 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "lastdragon-ru/lara-asp-eloquent", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-eloquent.git", - "reference": "9a63254e9fd4819de32e0be3bab0f6424de1ecc6" + "reference": "f588294e635b809cbc67abeeede18d497cff897e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-eloquent/zipball/9a63254e9fd4819de32e0be3bab0f6424de1ecc6", - "reference": "9a63254e9fd4819de32e0be3bab0f6424de1ecc6", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-eloquent/zipball/f588294e635b809cbc67abeeede18d497cff897e", + "reference": "f588294e635b809cbc67abeeede18d497cff897e", "shasum": "" }, "require": { @@ -6992,20 +7027,20 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "lastdragon-ru/lara-asp-graphql", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-graphql.git", - "reference": "94570deceba9b2639fb810df43c13a52ccf40f19" + "reference": "d3450a790badba452d7add51b7bf2e2fa2446c3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-graphql/zipball/94570deceba9b2639fb810df43c13a52ccf40f19", - "reference": "94570deceba9b2639fb810df43c13a52ccf40f19", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-graphql/zipball/d3450a790badba452d7add51b7bf2e2fa2446c3f", + "reference": "d3450a790badba452d7add51b7bf2e2fa2446c3f", "shasum": "" }, "require": { @@ -7066,20 +7101,20 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "lastdragon-ru/lara-asp-graphql-printer", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-graphql-printer.git", - "reference": "93fc1f40a025b4a2ece5c8bab6cc82509d8a79da" + "reference": "37e0a8e5c38b7bcbb5086cd715fe84cab9de3a39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-graphql-printer/zipball/93fc1f40a025b4a2ece5c8bab6cc82509d8a79da", - "reference": "93fc1f40a025b4a2ece5c8bab6cc82509d8a79da", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-graphql-printer/zipball/37e0a8e5c38b7bcbb5086cd715fe84cab9de3a39", + "reference": "37e0a8e5c38b7bcbb5086cd715fe84cab9de3a39", "shasum": "" }, "require": { @@ -7120,20 +7155,20 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "lastdragon-ru/lara-asp-serializer", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-serializer.git", - "reference": "2e59e3c8984f680d57ad0a3bb0f66b7d626d1c21" + "reference": "23c7cb4b152a47af1146ee82317b749d7600ccbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-serializer/zipball/2e59e3c8984f680d57ad0a3bb0f66b7d626d1c21", - "reference": "2e59e3c8984f680d57ad0a3bb0f66b7d626d1c21", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-serializer/zipball/23c7cb4b152a47af1146ee82317b749d7600ccbc", + "reference": "23c7cb4b152a47af1146ee82317b749d7600ccbc", "shasum": "" }, "require": { @@ -7185,7 +7220,7 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "league/commonmark", @@ -8122,35 +8157,35 @@ }, { "name": "livewire/livewire", - "version": "v3.3.3", + "version": "v3.3.5", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "6dd3bec8c711cd792742be4620057637e261e6f7" + "reference": "1ef880fbcdc7b6e5e405cc9135a62cd5fdbcd06a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/6dd3bec8c711cd792742be4620057637e261e6f7", - "reference": "6dd3bec8c711cd792742be4620057637e261e6f7", + "url": "https://api.github.com/repos/livewire/livewire/zipball/1ef880fbcdc7b6e5e405cc9135a62cd5fdbcd06a", + "reference": "1ef880fbcdc7b6e5e405cc9135a62cd5fdbcd06a", "shasum": "" }, "require": { - "illuminate/database": "^10.0", - "illuminate/support": "^10.0", - "illuminate/validation": "^10.0", + "illuminate/database": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0", + "illuminate/validation": "^10.0|^11.0", "league/mime-type-detection": "^1.9", "php": "^8.1", - "symfony/http-kernel": "^6.2" + "symfony/http-kernel": "^6.2|^7.0" }, "require-dev": { "calebporzio/sushi": "^2.1", - "laravel/framework": "^10.0", + "laravel/framework": "^10.0|^11.0", "laravel/prompts": "^0.1.6", "mockery/mockery": "^1.3.1", - "orchestra/testbench": "^8.0", - "orchestra/testbench-dusk": "^8.0", - "phpunit/phpunit": "^9.0", - "psy/psysh": "@stable" + "orchestra/testbench": "^8.0|^9.0", + "orchestra/testbench-dusk": "^8.0|^9.0", + "phpunit/phpunit": "^10.4", + "psy/psysh": "^0.11.22|^0.12" }, "type": "library", "extra": { @@ -8184,7 +8219,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.3.3" + "source": "https://github.com/livewire/livewire/tree/v3.3.5" }, "funding": [ { @@ -8192,7 +8227,7 @@ "type": "github" } ], - "time": "2023-12-20T05:34:05+00:00" + "time": "2024-01-02T14:29:17+00:00" }, { "name": "maatwebsite/excel", @@ -10306,16 +10341,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.5", + "version": "1.25.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc" + "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fedf211ff14ec8381c9bf5714e33a7a552dd1acc", - "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bd84b629c8de41aa2ae82c067c955e06f1b00240", + "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240", "shasum": "" }, "require": { @@ -10347,9 +10382,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.5" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.25.0" }, - "time": "2023-12-16T09:33:33+00:00" + "time": "2024-01-04T17:06:16+00:00" }, { "name": "psr/cache", @@ -13216,16 +13251,16 @@ }, { "name": "symfony/console", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd" + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a550a7c99daeedef3f9d23fb82e3531525ff11fd", - "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd", + "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", "shasum": "" }, "require": { @@ -13290,7 +13325,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.1" + "source": "https://github.com/symfony/console/tree/v6.4.2" }, "funding": [ { @@ -13306,7 +13341,7 @@ "type": "tidelift" } ], - "time": "2023-11-30T10:54:28+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/css-selector", @@ -13517,16 +13552,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v7.0.0", + "version": "v7.0.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e" + "reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c459b40ffe67c49af6fd392aac374c9edf8a027e", - "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/098b62ae81fdd6cbf941f355059f617db28f4f9a", + "reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a", "shasum": "" }, "require": { @@ -13577,7 +13612,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.2" }, "funding": [ { @@ -13593,7 +13628,7 @@ "type": "tidelift" } ], - "time": "2023-07-27T16:29:09+00:00" + "time": "2023-12-27T22:24:19+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -13869,16 +13904,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771" + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/44a6d39a9cc11e154547d882d5aac1e014440771", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/172d807f9ef3fc3fbed8377cc57c20d389269271", + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271", "shasum": "" }, "require": { @@ -13926,7 +13961,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.0" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.2" }, "funding": [ { @@ -13942,20 +13977,20 @@ "type": "tidelift" } ], - "time": "2023-11-20T16:41:16+00:00" + "time": "2023-12-27T22:16:42+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "2953274c16a229b3933ef73a6898e18388e12e1b" + "reference": "13e8387320b5942d0dc408440c888e2d526efef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2953274c16a229b3933ef73a6898e18388e12e1b", - "reference": "2953274c16a229b3933ef73a6898e18388e12e1b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/13e8387320b5942d0dc408440c888e2d526efef4", + "reference": "13e8387320b5942d0dc408440c888e2d526efef4", "shasum": "" }, "require": { @@ -14039,7 +14074,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.1" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.2" }, "funding": [ { @@ -14055,20 +14090,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T17:02:02+00:00" + "time": "2023-12-30T15:31:44+00:00" }, { "name": "symfony/mailer", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba" + "reference": "6da89e5c9202f129717a770a03183fb140720168" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", - "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", + "url": "https://api.github.com/repos/symfony/mailer/zipball/6da89e5c9202f129717a770a03183fb140720168", + "reference": "6da89e5c9202f129717a770a03183fb140720168", "shasum": "" }, "require": { @@ -14119,7 +14154,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.4.0" + "source": "https://github.com/symfony/mailer/tree/v6.4.2" }, "funding": [ { @@ -14135,7 +14170,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T18:02:22+00:00" + "time": "2023-12-19T09:12:31+00:00" }, { "name": "symfony/mime", @@ -15119,16 +15154,16 @@ }, { "name": "symfony/process", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa" + "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/191703b1566d97a5425dc969e4350d32b8ef17aa", - "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa", + "url": "https://api.github.com/repos/symfony/process/zipball/c4b1ef0bc80533d87a2e969806172f1c2a980241", + "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241", "shasum": "" }, "require": { @@ -15160,7 +15195,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.0" + "source": "https://github.com/symfony/process/tree/v6.4.2" }, "funding": [ { @@ -15176,7 +15211,7 @@ "type": "tidelift" } ], - "time": "2023-11-17T21:06:49+00:00" + "time": "2023-12-22T16:42:54+00:00" }, { "name": "symfony/property-access", @@ -15340,16 +15375,16 @@ }, { "name": "symfony/routing", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40" + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0c95c164fdba18b12523b75e64199ca3503e6d40", - "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40", + "url": "https://api.github.com/repos/symfony/routing/zipball/98eab13a07fddc85766f1756129c69f207ffbc21", + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21", "shasum": "" }, "require": { @@ -15403,7 +15438,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.1" + "source": "https://github.com/symfony/routing/tree/v6.4.2" }, "funding": [ { @@ -15419,20 +15454,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T14:54:37+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/serializer", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "7ead272e62c9567df619ef3c49809bf934ddbc1f" + "reference": "f87ea9d7bfd4cf2f7b72be554607e6c96e6664af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/7ead272e62c9567df619ef3c49809bf934ddbc1f", - "reference": "7ead272e62c9567df619ef3c49809bf934ddbc1f", + "url": "https://api.github.com/repos/symfony/serializer/zipball/f87ea9d7bfd4cf2f7b72be554607e6c96e6664af", + "reference": "f87ea9d7bfd4cf2f7b72be554607e6c96e6664af", "shasum": "" }, "require": { @@ -15501,7 +15536,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.4.1" + "source": "https://github.com/symfony/serializer/tree/v6.4.2" }, "funding": [ { @@ -15517,7 +15552,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T14:54:37+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/service-contracts", @@ -15603,16 +15638,16 @@ }, { "name": "symfony/string", - "version": "v7.0.0", + "version": "v7.0.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620" + "reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/92bd2bfbba476d4a1838e5e12168bef2fd1e6620", - "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620", + "url": "https://api.github.com/repos/symfony/string/zipball/cc78f14f91f5e53b42044d0620961c48028ff9f5", + "reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5", "shasum": "" }, "require": { @@ -15669,7 +15704,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.0" + "source": "https://github.com/symfony/string/tree/v7.0.2" }, "funding": [ { @@ -15685,20 +15720,20 @@ "type": "tidelift" } ], - "time": "2023-11-29T08:40:23+00:00" + "time": "2023-12-10T16:54:46+00:00" }, { "name": "symfony/translation", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37" + "reference": "a2ab2ec1a462e53016de8e8d5e8912bfd62ea681" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", - "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", + "url": "https://api.github.com/repos/symfony/translation/zipball/a2ab2ec1a462e53016de8e8d5e8912bfd62ea681", + "reference": "a2ab2ec1a462e53016de8e8d5e8912bfd62ea681", "shasum": "" }, "require": { @@ -15764,7 +15799,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.0" + "source": "https://github.com/symfony/translation/tree/v6.4.2" }, "funding": [ { @@ -15780,7 +15815,7 @@ "type": "tidelift" } ], - "time": "2023-11-29T08:14:36+00:00" + "time": "2023-12-18T09:25:29+00:00" }, { "name": "symfony/translation-contracts", @@ -15936,16 +15971,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", "shasum": "" }, "require": { @@ -16001,7 +16036,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.0" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.2" }, "funding": [ { @@ -16017,7 +16052,7 @@ "type": "tidelift" } ], - "time": "2023-11-09T08:28:32+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "tapp/filament-timezone-field", @@ -16983,16 +17018,16 @@ }, { "name": "fakerphp/faker", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01" + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", - "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", "shasum": "" }, "require": { @@ -17018,11 +17053,6 @@ "ext-mbstring": "Required for multibyte Unicode string functionality." }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "v1.21-dev" - } - }, "autoload": { "psr-4": { "Faker\\": "src/Faker/" @@ -17045,9 +17075,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.23.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" }, - "time": "2023-06-12T08:44:38+00:00" + "time": "2024-01-02T13:46:09+00:00" }, { "name": "fidry/cpu-core-counter", @@ -17183,21 +17213,22 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.44.0", + "version": "v3.46.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "5445834057a744c1a434ed60fcac566b4de3a0f2" + "reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/5445834057a744c1a434ed60fcac566b4de3a0f2", - "reference": "5445834057a744c1a434ed60fcac566b4de3a0f2", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/be6831c9af1740470d2a773119b9273f8ac1c3d2", + "reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2", "shasum": "" }, "require": { "composer/semver": "^3.4", "composer/xdebug-handler": "^3.0.3", + "ext-filter": "*", "ext-json": "*", "ext-tokenizer": "*", "php": "^7.4 || ^8.0", @@ -17261,7 +17292,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.44.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.46.0" }, "funding": [ { @@ -17269,7 +17300,7 @@ "type": "github" } ], - "time": "2023-12-29T20:21:16+00:00" + "time": "2024-01-03T21:38:46+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -17383,36 +17414,36 @@ }, { "name": "larastan/larastan", - "version": "v2.7.0", + "version": "v2.8.0", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "a2610d46b9999cf558d9900ccb641962d1442f55" + "reference": "d60c1a6d49fcbb54b78922a955a55820abdbe3c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/a2610d46b9999cf558d9900ccb641962d1442f55", - "reference": "a2610d46b9999cf558d9900ccb641962d1442f55", + "url": "https://api.github.com/repos/larastan/larastan/zipball/d60c1a6d49fcbb54b78922a955a55820abdbe3c7", + "reference": "d60c1a6d49fcbb54b78922a955a55820abdbe3c7", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^9.52.16 || ^10.28.0", - "illuminate/container": "^9.52.16 || ^10.28.0", - "illuminate/contracts": "^9.52.16 || ^10.28.0", - "illuminate/database": "^9.52.16 || ^10.28.0", - "illuminate/http": "^9.52.16 || ^10.28.0", - "illuminate/pipeline": "^9.52.16 || ^10.28.0", - "illuminate/support": "^9.52.16 || ^10.28.0", + "illuminate/console": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/container": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/contracts": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/database": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/http": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/pipeline": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/support": "^9.52.16 || ^10.28.0 || ^11.0", "php": "^8.0.2", "phpmyadmin/sql-parser": "^5.8.2", - "phpstan/phpstan": "^1.10.41" + "phpstan/phpstan": "^1.10.50" }, "require-dev": { "nikic/php-parser": "^4.17.1", - "orchestra/canvas": "^7.11.1 || ^8.11.0", - "orchestra/testbench": "^7.33.0 || ^8.13.0", - "phpunit/phpunit": "^9.6.13" + "orchestra/canvas": "^7.11.1 || ^8.11.0 || ^9.0.0", + "orchestra/testbench": "^7.33.0 || ^8.13.0 || ^9.0.0", + "phpunit/phpunit": "^9.6.13 || ^10.5" }, "suggest": { "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" @@ -17460,7 +17491,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v2.7.0" + "source": "https://github.com/larastan/larastan/tree/v2.8.0" }, "funding": [ { @@ -17480,7 +17511,7 @@ "type": "patreon" } ], - "time": "2023-12-04T19:21:38+00:00" + "time": "2024-01-02T22:09:07+00:00" }, { "name": "laravel/sail", @@ -20131,16 +20162,16 @@ }, { "name": "spatie/ignition", - "version": "1.11.3", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044" + "reference": "5b6f801c605a593106b623e45ca41496a6e7d56d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/3d886de644ff7a5b42e4d27c1e1f67c8b5f00044", - "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044", + "url": "https://api.github.com/repos/spatie/ignition/zipball/5b6f801c605a593106b623e45ca41496a6e7d56d", + "reference": "5b6f801c605a593106b623e45ca41496a6e7d56d", "shasum": "" }, "require": { @@ -20210,39 +20241,39 @@ "type": "github" } ], - "time": "2023-10-18T14:09:40+00:00" + "time": "2024-01-03T15:49:39+00:00" }, { "name": "spatie/laravel-ignition", - "version": "2.3.3", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "66499cd3c858642ded56dafb8fa0352057ca20dd" + "reference": "b9395ba48d3f30d42092cf6ceff75ed7256cd604" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/66499cd3c858642ded56dafb8fa0352057ca20dd", - "reference": "66499cd3c858642ded56dafb8fa0352057ca20dd", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/b9395ba48d3f30d42092cf6ceff75ed7256cd604", + "reference": "b9395ba48d3f30d42092cf6ceff75ed7256cd604", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "illuminate/support": "^10.0", + "illuminate/support": "^10.0|^11.0", "php": "^8.1", "spatie/flare-client-php": "^1.3.5", "spatie/ignition": "^1.9", - "symfony/console": "^6.2.3", - "symfony/var-dumper": "^6.2.3" + "symfony/console": "^6.2.3|^7.0", + "symfony/var-dumper": "^6.2.3|^7.0" }, "require-dev": { - "livewire/livewire": "^2.11", + "livewire/livewire": "^2.11|^3.3.5", "mockery/mockery": "^1.5.1", - "openai-php/client": "^0.3.4", - "orchestra/testbench": "^8.0", - "pestphp/pest": "^1.22.3", + "openai-php/client": "^0.8.1", + "orchestra/testbench": "^8.0|^9.0", + "pestphp/pest": "^2.30", "phpstan/extension-installer": "^1.2", "phpstan/phpstan-deprecation-rules": "^1.1.1", "phpstan/phpstan-phpunit": "^1.3.3", @@ -20302,7 +20333,7 @@ "type": "github" } ], - "time": "2023-12-21T09:43:05+00:00" + "time": "2024-01-04T14:51:24+00:00" }, { "name": "spatie/laravel-ray", @@ -21202,5 +21233,5 @@ "ext-pdo": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From 3d38a961552bad09b459595d53e34e6de397ad32 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 19:33:48 +0000 Subject: [PATCH 130/152] Update EditCaseloadTest.php --- .../tests/Filament/CaseloadResource/EditCaseloadTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app-modules/caseload-management/tests/Filament/CaseloadResource/EditCaseloadTest.php b/app-modules/caseload-management/tests/Filament/CaseloadResource/EditCaseloadTest.php index c600f855a1..30b5e5943e 100644 --- a/app-modules/caseload-management/tests/Filament/CaseloadResource/EditCaseloadTest.php +++ b/app-modules/caseload-management/tests/Filament/CaseloadResource/EditCaseloadTest.php @@ -43,9 +43,9 @@ use AdvisingApp\CaseloadManagement\Filament\Resources\CaseloadResource; test('EditCaseload is gated with proper access control', function () { - $user = User::factory()->create(); + $user = User::factory()->licensed(LicenseType::cases())->create(); - $caseload = Caseload::factory()->licensed(LicenseType::cases())->create(); + $caseload = Caseload::factory()->create(); actingAs($user) ->get( From f3509e3434cf0a5a9c044377a58acb77209f6aab Mon Sep 17 00:00:00 2001 From: mxm1070 Date: Thu, 4 Jan 2024 19:36:32 +0000 Subject: [PATCH 131/152] chore: fix code style --- config/data.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/data.php b/config/data.php index 9cd8296ad4..6a92fd3033 100644 --- a/config/data.php +++ b/config/data.php @@ -47,8 +47,8 @@ * types. */ 'transformers' => [ - DateTimeInterface::class => \Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer::class, - \Illuminate\Contracts\Support\Arrayable::class => \Spatie\LaravelData\Transformers\ArrayableTransformer::class, + DateTimeInterface::class => Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer::class, + Illuminate\Contracts\Support\Arrayable::class => Spatie\LaravelData\Transformers\ArrayableTransformer::class, BackedEnum::class => Spatie\LaravelData\Transformers\EnumTransformer::class, ], From 1b5a6d3b3f8d477e0e7d843fec00dd34ca563bdc Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 19:51:37 +0000 Subject: [PATCH 132/152] requested changes --- app-modules/alert/src/Models/Alert.php | 3 +- .../CaseloadResource/Pages/CreateCaseload.php | 5 +- .../engagement/src/Models/Engagement.php | 3 +- app-modules/form/src/Models/Submission.php | 3 +- .../interaction/src/Models/Interaction.php | 3 +- .../HasSharedEventFormConfiguration.php | 2 +- .../notification/src/Models/Subscription.php | 3 +- .../src/Policies/SubscriptionPolicy.php | 2 +- .../ProspectResource/Pages/CreateProspect.php | 3 +- .../ProspectResource/Pages/EditProspect.php | 3 +- .../Pages/ManageProspectCareTeam.php | 3 +- .../Pages/ManageProspectSubscriptions.php | 3 +- .../src/Models/ServiceRequest.php | 3 +- .../Pages/ManageStudentCareTeam.php | 3 +- .../Pages/ManageStudentSubscriptions.php | 3 +- .../Models/Scopes/LicensedToEducatable.php | 48 +++++++++++++++++++ .../task/src/Filament/Concerns/TaskForm.php | 7 +-- .../BaseTaskRelationManager.php | 5 +- app-modules/task/src/Models/Task.php | 3 +- app/Filament/Fields/EducatableSelect.php | 4 +- app/Models/Scopes/HasLicense.php | 28 +++++++++++ app/Models/User.php | 32 ------------- 22 files changed, 114 insertions(+), 58 deletions(-) create mode 100644 app-modules/student-data-model/src/Models/Scopes/LicensedToEducatable.php create mode 100644 app/Models/Scopes/HasLicense.php diff --git a/app-modules/alert/src/Models/Alert.php b/app-modules/alert/src/Models/Alert.php index 66c042bbc3..0e990c667f 100644 --- a/app-modules/alert/src/Models/Alert.php +++ b/app-modules/alert/src/Models/Alert.php @@ -50,6 +50,7 @@ use AdvisingApp\Notification\Models\Contracts\Subscribable; use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; use AdvisingApp\Notification\Models\Contracts\CanTriggerAutoSubscription; @@ -119,7 +120,7 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s protected static function booted(): void { static::addGlobalScope('licensed', function (Builder $builder) { - $builder->licensedToEducatable('concern'); + $builder->tap(new LicensedToEducatable('concern')); }); } } diff --git a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php index 3d3400125e..6e696f2872 100644 --- a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php +++ b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/CreateCaseload.php @@ -302,11 +302,8 @@ protected function getCaseloadModel(): CaseloadModel $canAccessStudents = auth()->user()->hasLicense(Student::getLicenseType()); $canAccessProspects = auth()->user()->hasLicense(Prospect::getLicenseType()); - if ($canAccessStudents && $canAccessProspects) { - return CaseloadModel::tryFromCaseOrValue($this->form->getRawState()['model']) ?? throw new Exception('Neither students nor prospects were selected.'); - } - return match (true) { + $canAccessStudents && $canAccessProspects => CaseloadModel::tryFromCaseOrValue($this->form->getRawState()['model']) ?? throw new Exception('Neither students nor prospects were selected.'), $canAccessStudents => CaseloadModel::Student, $canAccessProspects => CaseloadModel::Prospect, default => throw new Exception('User cannot access students or prospects.'), diff --git a/app-modules/engagement/src/Models/Engagement.php b/app-modules/engagement/src/Models/Engagement.php index 197607d3a5..68441e7df3 100644 --- a/app-modules/engagement/src/Models/Engagement.php +++ b/app-modules/engagement/src/Models/Engagement.php @@ -56,6 +56,7 @@ use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\Engagement\Actions\GenerateEmailMarkdownContent; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Notification\Models\Contracts\CanTriggerAutoSubscription; @@ -211,7 +212,7 @@ public function getMergeData(): array protected static function booted(): void { static::addGlobalScope('licensed', function (Builder $builder) { - $builder->licensedToEducatable('recipient'); + $builder->tap(new LicensedToEducatable('recipient')); }); } } diff --git a/app-modules/form/src/Models/Submission.php b/app-modules/form/src/Models/Submission.php index 51bd0c1750..0e986b4082 100644 --- a/app-modules/form/src/Models/Submission.php +++ b/app-modules/form/src/Models/Submission.php @@ -43,6 +43,7 @@ use AdvisingApp\StudentDataModel\Models\Student; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; /** @@ -67,7 +68,7 @@ public function author(): BelongsTo protected static function booted(): void { static::addGlobalScope('licensed', function (Builder $builder) { - $builder->licensedToEducatable('author'); + $builder->tap(new LicensedToEducatable('author')); }); } } diff --git a/app-modules/interaction/src/Models/Interaction.php b/app-modules/interaction/src/Models/Interaction.php index 4bbddadc90..bebcda9b9f 100644 --- a/app-modules/interaction/src/Models/Interaction.php +++ b/app-modules/interaction/src/Models/Interaction.php @@ -49,6 +49,7 @@ use AdvisingApp\Notification\Models\Contracts\Subscribable; use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; use AdvisingApp\Notification\Models\Contracts\CanTriggerAutoSubscription; @@ -171,7 +172,7 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s protected static function booted(): void { static::addGlobalScope('licensed', function (Builder $builder) { - $builder->licensedToEducatable('interactable'); + $builder->tap(new LicensedToEducatable('interactable')); }); } } diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php index fb5f1f5ce4..f2409a7f24 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/Concerns/HasSharedEventFormConfiguration.php @@ -41,7 +41,7 @@ use Filament\Forms\Components\Grid; use AdvisingApp\Form\Enums\Rounding; use AdvisingApp\Form\Rules\IsDomain; -use App\Forms\Components\ColorSelect; +use App\Filament\Fields\ColorSelect; use Filament\Forms\Components\Select; use Filament\Forms\Components\Toggle; use Filament\Forms\Components\Section; diff --git a/app-modules/notification/src/Models/Subscription.php b/app-modules/notification/src/Models/Subscription.php index 165406157a..58961855ac 100644 --- a/app-modules/notification/src/Models/Subscription.php +++ b/app-modules/notification/src/Models/Subscription.php @@ -50,6 +50,7 @@ use AdvisingApp\Notification\Actions\SubscriptionCreate; use AdvisingApp\Notification\Models\Contracts\Subscribable; use AdvisingApp\Authorization\Models\Concerns\DefinesPermissions; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; @@ -115,7 +116,7 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s protected static function booted(): void { static::addGlobalScope('licensed', function (Builder $builder) { - $builder->licensedToEducatable('subscribable'); + $builder->tap(new LicensedToEducatable('subscribable')); }); } diff --git a/app-modules/notification/src/Policies/SubscriptionPolicy.php b/app-modules/notification/src/Policies/SubscriptionPolicy.php index 4c1f7bc6d3..2b5f8876e0 100644 --- a/app-modules/notification/src/Policies/SubscriptionPolicy.php +++ b/app-modules/notification/src/Policies/SubscriptionPolicy.php @@ -53,7 +53,7 @@ public function viewAny(Authenticatable $authenticatable): Response public function view(Authenticatable $authenticatable, Subscription $subscription): Response { if (! $authenticatable->hasLicense($subscription->subscribable?->getLicenseType())) { - return Response::deny('You do not have permission to view this alert.'); + return Response::deny('You do not have permission to view this subscription.'); } return $authenticatable->canOrElse( diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php index ceff760d48..ce538162e5 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/CreateProspect.php @@ -38,6 +38,7 @@ use App\Models\User; use Filament\Forms\Form; +use App\Models\Scopes\HasLicense; use Filament\Forms\Components\Radio; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; @@ -137,7 +138,7 @@ public function form(Form $form): Form ->relationship( 'assignedTo', 'name', - fn (Builder $query) => $query->hasLicense(Prospect::getLicenseType()), + fn (Builder $query) => $query->tap(new HasLicense(Prospect::getLicenseType())), ) ->searchable() ->nullable() diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php index ce7a51fc21..b1d958329e 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php @@ -36,6 +36,7 @@ namespace AdvisingApp\Prospect\Filament\Resources\ProspectResource\Pages; +use App\Models\Scopes\HasLicense; use App\Models\User; use Filament\Forms\Form; use Filament\Actions\ViewAction; @@ -140,7 +141,7 @@ public function form(Form $form): Form ->relationship( 'assignedTo', 'name', - fn (Builder $query) => $query->hasLicense(Prospect::getLicenseType()), + fn (Builder $query) => $query->tap(new HasLicense(Prospect::getLicenseType())), ) ->searchable() ->nullable() diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php index 1b34c33dfb..bb2ee0f2d2 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectCareTeam.php @@ -38,6 +38,7 @@ use App\Models\User; use Filament\Tables\Table; +use App\Models\Scopes\HasLicense; use App\Filament\Columns\IdColumn; use Filament\Forms\Components\Select; use Filament\Tables\Columns\TextColumn; @@ -95,7 +96,7 @@ public function table(Table $table): Table fn (Select $select) => $select->placeholder('Select a User'), ) ->recordSelectOptionsQuery( - fn (Builder $query) => $query->hasLicense(Prospect::getLicenseType()), + fn (Builder $query) => $query->tap(new HasLicense(Prospect::getLicenseType())), ) ->successNotificationTitle(function (User $record) { /** @var Prospect $prospect */ diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php index b147d9e5dc..bb5684f8b6 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/ManageProspectSubscriptions.php @@ -38,6 +38,7 @@ use App\Models\User; use Filament\Tables\Table; +use App\Models\Scopes\HasLicense; use App\Filament\Columns\IdColumn; use Filament\Forms\Components\Select; use Filament\Tables\Columns\TextColumn; @@ -97,7 +98,7 @@ public function table(Table $table): Table fn (Select $select) => $select->placeholder('Select a User'), ) ->recordSelectOptionsQuery( - fn (Builder $query) => $query->hasLicense(Prospect::getLicenseType()), + fn (Builder $query) => $query->tap(new HasLicense(Prospect::getLicenseType())), ) ->successNotificationTitle(function (User $record) { /** @var Prospect $prospect */ diff --git a/app-modules/service-management/src/Models/ServiceRequest.php b/app-modules/service-management/src/Models/ServiceRequest.php index 5cd2b3c32b..fb48c12dfc 100644 --- a/app-modules/service-management/src/Models/ServiceRequest.php +++ b/app-modules/service-management/src/Models/ServiceRequest.php @@ -60,6 +60,7 @@ use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\StudentDataModel\Models\Contracts\Identifiable; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Interaction\Models\Concerns\HasManyMorphedInteractions; use AdvisingApp\ServiceManagement\Enums\ServiceRequestAssignmentStatus; @@ -249,7 +250,7 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s protected static function booted(): void { static::addGlobalScope('licensed', function (Builder $builder) { - $builder->licensedToEducatable('respondent'); + $builder->tap(new LicensedToEducatable('respondent')); }); } diff --git a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php index a93fe6b03d..a86baf10c3 100644 --- a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php +++ b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentCareTeam.php @@ -38,6 +38,7 @@ use App\Models\User; use Filament\Tables\Table; +use App\Models\Scopes\HasLicense; use App\Filament\Columns\IdColumn; use Filament\Forms\Components\Select; use Filament\Tables\Columns\TextColumn; @@ -95,7 +96,7 @@ public function table(Table $table): Table fn (Select $select) => $select->placeholder('Select a User'), ) ->recordSelectOptionsQuery( - fn (Builder $query) => $query->hasLicense(Student::getLicenseType()), + fn (Builder $query) => $query->tap(new HasLicense(Student::getLicenseType())), ) ->successNotificationTitle(function (User $record) { /** @var Student $student */ diff --git a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php index 4fef1e04e8..bb4eb19117 100644 --- a/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php +++ b/app-modules/student-data-model/src/Filament/Resources/StudentResource/Pages/ManageStudentSubscriptions.php @@ -38,6 +38,7 @@ use App\Models\User; use Filament\Tables\Table; +use App\Models\Scopes\HasLicense; use App\Filament\Columns\IdColumn; use Filament\Forms\Components\Select; use Filament\Tables\Columns\TextColumn; @@ -97,7 +98,7 @@ public function table(Table $table): Table fn (Select $select) => $select->placeholder('Select a User'), ) ->recordSelectOptionsQuery( - fn (Builder $query) => $query->hasLicense(Student::getLicenseType()), + fn (Builder $query) => $query->tap(new HasLicense(Student::getLicenseType())), ) ->successNotificationTitle(function (User $record) { /** @var Student $student */ diff --git a/app-modules/student-data-model/src/Models/Scopes/LicensedToEducatable.php b/app-modules/student-data-model/src/Models/Scopes/LicensedToEducatable.php new file mode 100644 index 0000000000..5342d38896 --- /dev/null +++ b/app-modules/student-data-model/src/Models/Scopes/LicensedToEducatable.php @@ -0,0 +1,48 @@ +check()) { + return; + } + + /** @var Authenticatable $user */ + $user = auth()->user(); + + $model = $query->getModel(); + + if ( + (! method_exists($model, $this->relationship)) || + (! ($model->{$this->relationship}() instanceof MorphTo)) + ) { + throw new Exception('The [' . static::class . "] model does not have a [{$this->relationship}] [" . MorphTo::class . '] relationship where educatables can be assigned.'); + } + + $typeColumn = $model->{$this->relationship}()->getMorphType(); + + $query + ->when( + ! $user->hasLicense(Student::getLicenseType()), + fn (Builder $query) => $query->where($typeColumn, '!=', app(Student::class)->getMorphClass()), + ) + ->when( + ! $user->hasLicense(Prospect::getLicenseType()), + fn (Builder $query) => $query->where($typeColumn, '!=', app(Prospect::class)->getMorphClass()), + ); + } +} diff --git a/app-modules/task/src/Filament/Concerns/TaskForm.php b/app-modules/task/src/Filament/Concerns/TaskForm.php index fed62a3e0d..ad3eb69931 100644 --- a/app-modules/task/src/Filament/Concerns/TaskForm.php +++ b/app-modules/task/src/Filament/Concerns/TaskForm.php @@ -41,6 +41,7 @@ use Filament\Forms\Get; use Filament\Forms\Set; use App\Models\Authenticatable; +use App\Models\Scopes\HasLicense; use AdvisingApp\Prospect\Models\Prospect; use Illuminate\Database\Eloquent\Builder; use AdvisingApp\StudentDataModel\Models\Student; @@ -54,7 +55,7 @@ protected function scopeAssignmentRelationshipBasedOnConcern(): Closure $concernType = $get('concern_type'); if (filled($concernType = (Relation::getMorphedModel($concernType) ?? $concernType))) { - return $query->hasLicense($concernType::getLicenseType()); + return $query->tap(new HasLicense($concernType::getLicenseType())); } /** @var Authenticatable $user */ @@ -68,8 +69,8 @@ protected function scopeAssignmentRelationshipBasedOnConcern(): Closure } return match (true) { - $canAccessStudents => $query->hasLicense(Student::getLicenseType()), - $canAccessProspects => $query->hasLicense(Prospect::getLicenseType()), + $canAccessStudents => $query->tap(new HasLicense(Student::getLicenseType())), + $canAccessProspects => $query->tap(new HasLicense(Prospect::getLicenseType())), default => $query, }; }; diff --git a/app-modules/task/src/Filament/RelationManagers/BaseTaskRelationManager.php b/app-modules/task/src/Filament/RelationManagers/BaseTaskRelationManager.php index 3e5e6f3d6b..1ce0c5581b 100644 --- a/app-modules/task/src/Filament/RelationManagers/BaseTaskRelationManager.php +++ b/app-modules/task/src/Filament/RelationManagers/BaseTaskRelationManager.php @@ -39,6 +39,7 @@ use Filament\Forms\Form; use Filament\Tables\Table; use AdvisingApp\Task\Models\Task; +use App\Models\Scopes\HasLicense; use App\Filament\Columns\IdColumn; use Filament\Tables\Filters\Filter; use Filament\Forms\Components\Select; @@ -84,7 +85,7 @@ public function form(Form $form): Form ->relationship( 'assignedTo', 'name', - fn (Builder $query) => $query->hasLicense($this->getOwnerRecord()->getLicenseType()), + fn (Builder $query) => $query->tap(new HasLicense($this->getOwnerRecord()->getLicenseType())), ) ->nullable() ->searchable(['name', 'email']) @@ -130,7 +131,7 @@ public function table(Table $table): Table ->relationship( 'assignedTo', 'name', - fn (Builder $query) => $query->hasLicense($this->getOwnerRecord()->getLicenseType()), + fn (Builder $query) => $query->tap(new HasLicense($this->getOwnerRecord()->getLicenseType())), ) ->searchable() ->multiple(), diff --git a/app-modules/task/src/Models/Task.php b/app-modules/task/src/Models/Task.php index 8fdbd5560b..a67ecf909d 100644 --- a/app-modules/task/src/Models/Task.php +++ b/app-modules/task/src/Models/Task.php @@ -56,6 +56,7 @@ use AdvisingApp\Notification\Models\Contracts\Subscribable; use AdvisingApp\StudentDataModel\Models\Contracts\Educatable; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; use AdvisingApp\Campaign\Models\Contracts\ExecutableFromACampaignAction; use AdvisingApp\Notification\Models\Contracts\CanTriggerAutoSubscription; @@ -168,7 +169,7 @@ public static function executeFromCampaignAction(CampaignAction $action): bool|s protected static function booted(): void { static::addGlobalScope('licensed', function (Builder $builder) { - $builder->licensedToEducatable('concern'); + $builder->tap(new LicensedToEducatable('concern')); }); } } diff --git a/app/Filament/Fields/EducatableSelect.php b/app/Filament/Fields/EducatableSelect.php index bdfcdb880d..ad41a91f1e 100644 --- a/app/Filament/Fields/EducatableSelect.php +++ b/app/Filament/Fields/EducatableSelect.php @@ -80,13 +80,13 @@ public static function make(string $name): EducatableSelect | MorphToSelect public static function getStudentType(): Type { - return MorphToSelect\Type::make(Student::class) + return Type::make(Student::class) ->titleAttribute(Student::displayNameKey()); } public static function getProspectType(): Type { - return MorphToSelect\Type::make(Prospect::class) + return Type::make(Prospect::class) ->titleAttribute(Prospect::displayNameKey()); } diff --git a/app/Models/Scopes/HasLicense.php b/app/Models/Scopes/HasLicense.php new file mode 100644 index 0000000000..8ff9cfcbd1 --- /dev/null +++ b/app/Models/Scopes/HasLicense.php @@ -0,0 +1,28 @@ + | null $type + */ + public function __construct( + protected LicenseType | string | array | null $type, + ) {} + + public function __invoke(Builder $query): void + { + if (blank($this->type)) { + return; + } + + foreach (Arr::wrap($this->type) as $type) { + $query->whereRelation('licenses', 'type', $type); + } + } +} diff --git a/app/Models/User.php b/app/Models/User.php index b5ea36bbf4..34b3d28e61 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -49,7 +49,6 @@ use OwenIt\Auditing\Contracts\Auditable; use AdvisingApp\CareTeam\Models\CareTeam; use AdvisingApp\Prospect\Models\Prospect; -use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Authorization\Models\Role; use Lab404\Impersonate\Models\Impersonate; use Filament\Models\Contracts\FilamentUser; @@ -421,37 +420,6 @@ public function hasAnyLicense(LicenseType | string | array | null $type): bool return false; } - /** - * @param LicenseType | string | array | null $type - */ - public function scopeHasLicense(Builder $query, LicenseType | string | array | null $type): Builder - { - if (blank($type)) { - return $query; - } - - foreach (Arr::wrap($type) as $type) { - $query->whereRelation('licenses', 'type', $type); - } - - return $query; - } - - /** - * @param LicenseType | string | array | null $type - */ - public function scopeHasAnyLicense(Builder $query, LicenseType | string | array | null $type): Builder - { - if (blank($type)) { - return $query; - } - - return $query->whereHas( - 'licenses', - fn (Builder $query) => $query->whereIn('type', Arr::wrap($type)), - ); - } - protected function serializeDate(DateTimeInterface $date): string { return $date->format(config('project.datetime_format') ?? 'Y-m-d H:i:s'); From ffdf8538bebebe958d6ed4cdfc7479c84aa7c196 Mon Sep 17 00:00:00 2001 From: danharrin Date: Thu, 4 Jan 2024 19:55:47 +0000 Subject: [PATCH 133/152] chore: fix enforcement of copyright on all files --- .../Models/Scopes/LicensedToEducatable.php | 34 +++++++++++++++++++ app/Models/Scopes/HasLicense.php | 34 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/app-modules/student-data-model/src/Models/Scopes/LicensedToEducatable.php b/app-modules/student-data-model/src/Models/Scopes/LicensedToEducatable.php index 5342d38896..27a4ceb4c1 100644 --- a/app-modules/student-data-model/src/Models/Scopes/LicensedToEducatable.php +++ b/app-modules/student-data-model/src/Models/Scopes/LicensedToEducatable.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace AdvisingApp\StudentDataModel\Models\Scopes; use Exception; diff --git a/app/Models/Scopes/HasLicense.php b/app/Models/Scopes/HasLicense.php index 8ff9cfcbd1..9dec999544 100644 --- a/app/Models/Scopes/HasLicense.php +++ b/app/Models/Scopes/HasLicense.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + namespace App\Models\Scopes; use Illuminate\Support\Arr; From 1dbf410c593dfaedc5d4b11c98c229ba599b9b94 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 19:57:10 +0000 Subject: [PATCH 134/152] fix copy --- app-modules/alert/src/Policies/AlertPolicy.php | 2 +- app-modules/caseload-management/src/Policies/CaseloadPolicy.php | 2 +- app-modules/engagement/src/Policies/EngagementPolicy.php | 2 +- app-modules/prospect/src/Policies/ProspectPolicy.php | 2 +- app-modules/prospect/src/Policies/ProspectSourcePolicy.php | 2 +- app-modules/prospect/src/Policies/ProspectStatusPolicy.php | 2 +- app-modules/student-data-model/src/Policies/StudentPolicy.php | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app-modules/alert/src/Policies/AlertPolicy.php b/app-modules/alert/src/Policies/AlertPolicy.php index 143300b859..fa1a250608 100644 --- a/app-modules/alert/src/Policies/AlertPolicy.php +++ b/app-modules/alert/src/Policies/AlertPolicy.php @@ -47,7 +47,7 @@ class AlertPolicy public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { - return Response::deny('You do not have permission to view students or prospects.'); + return Response::deny('You are not licensed for the Retention or Recruitment CRM.'); } return null; diff --git a/app-modules/caseload-management/src/Policies/CaseloadPolicy.php b/app-modules/caseload-management/src/Policies/CaseloadPolicy.php index b41ed07c8c..21a9a400ff 100644 --- a/app-modules/caseload-management/src/Policies/CaseloadPolicy.php +++ b/app-modules/caseload-management/src/Policies/CaseloadPolicy.php @@ -47,7 +47,7 @@ class CaseloadPolicy public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { - return Response::deny('You do not have permission to view students or prospects.'); + return Response::deny('You are not licensed for the Retention or Recruitment CRM.'); } return null; diff --git a/app-modules/engagement/src/Policies/EngagementPolicy.php b/app-modules/engagement/src/Policies/EngagementPolicy.php index 39790dc2fd..f4b3cd0fdc 100644 --- a/app-modules/engagement/src/Policies/EngagementPolicy.php +++ b/app-modules/engagement/src/Policies/EngagementPolicy.php @@ -47,7 +47,7 @@ class EngagementPolicy public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasAnyLicense([Student::getLicenseType(), Prospect::getLicenseType()])) { - return Response::deny('You do not have permission to view students or prospects.'); + return Response::deny('You are not licensed for the Retention or Recruitment CRM.'); } return null; diff --git a/app-modules/prospect/src/Policies/ProspectPolicy.php b/app-modules/prospect/src/Policies/ProspectPolicy.php index aca0724433..f17f5941ff 100644 --- a/app-modules/prospect/src/Policies/ProspectPolicy.php +++ b/app-modules/prospect/src/Policies/ProspectPolicy.php @@ -45,7 +45,7 @@ class ProspectPolicy public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasLicense(Prospect::getLicenseType())) { - return Response::deny('You are not licensed for the recruitment CRM.'); + return Response::deny('You are not licensed for the Recruitment CRM.'); } return null; diff --git a/app-modules/prospect/src/Policies/ProspectSourcePolicy.php b/app-modules/prospect/src/Policies/ProspectSourcePolicy.php index ae2a1001c1..2f21e10e0a 100644 --- a/app-modules/prospect/src/Policies/ProspectSourcePolicy.php +++ b/app-modules/prospect/src/Policies/ProspectSourcePolicy.php @@ -46,7 +46,7 @@ class ProspectSourcePolicy public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasLicense(Prospect::getLicenseType())) { - return Response::deny('You are not licensed for the recruitment CRM.'); + return Response::deny('You are not licensed for the Recruitment CRM.'); } return null; diff --git a/app-modules/prospect/src/Policies/ProspectStatusPolicy.php b/app-modules/prospect/src/Policies/ProspectStatusPolicy.php index ebb37dae87..eb92812f59 100644 --- a/app-modules/prospect/src/Policies/ProspectStatusPolicy.php +++ b/app-modules/prospect/src/Policies/ProspectStatusPolicy.php @@ -46,7 +46,7 @@ class ProspectStatusPolicy public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasLicense(Prospect::getLicenseType())) { - return Response::deny('You are not licensed for the recruitment CRM.'); + return Response::deny('You are not licensed for the Recruitment CRM.'); } return null; diff --git a/app-modules/student-data-model/src/Policies/StudentPolicy.php b/app-modules/student-data-model/src/Policies/StudentPolicy.php index 68ea835d02..efd67a44e8 100644 --- a/app-modules/student-data-model/src/Policies/StudentPolicy.php +++ b/app-modules/student-data-model/src/Policies/StudentPolicy.php @@ -45,7 +45,7 @@ class StudentPolicy public function before(Authenticatable $authenticatable): ?Response { if (! $authenticatable->hasLicense(Student::getLicenseType())) { - return Response::deny('You are not licensed for the retention CRM.'); + return Response::deny('You are not licensed for the Retention CRM.'); } return null; From 6ff63a4952a345cbc8dcf1f72cb736a32d9c8311 Mon Sep 17 00:00:00 2001 From: danharrin Date: Thu, 4 Jan 2024 20:01:09 +0000 Subject: [PATCH 135/152] chore: fix code style --- .../Filament/Resources/ProspectResource/Pages/EditProspect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php index b1d958329e..2d38622eea 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php @@ -36,10 +36,10 @@ namespace AdvisingApp\Prospect\Filament\Resources\ProspectResource\Pages; -use App\Models\Scopes\HasLicense; use App\Models\User; use Filament\Forms\Form; use Filament\Actions\ViewAction; +use App\Models\Scopes\HasLicense; use Filament\Actions\DeleteAction; use Filament\Forms\Components\Radio; use Filament\Forms\Components\Select; From a4acf75c15af7d3a6e6dffd427ac98427370bbbb Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 20:02:43 +0000 Subject: [PATCH 136/152] swap scope --- .../Resources/ProspectResource/Pages/EditProspect.php | 2 +- app-modules/prospect/src/Models/Prospect.php | 5 +++-- app-modules/student-data-model/src/Models/Student.php | 5 +++-- app/Models/Scopes/HasLicense.php | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php index b1d958329e..2d38622eea 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource/Pages/EditProspect.php @@ -36,10 +36,10 @@ namespace AdvisingApp\Prospect\Filament\Resources\ProspectResource\Pages; -use App\Models\Scopes\HasLicense; use App\Models\User; use Filament\Forms\Form; use Filament\Actions\ViewAction; +use App\Models\Scopes\HasLicense; use Filament\Actions\DeleteAction; use Filament\Forms\Components\Radio; use Filament\Forms\Components\Select; diff --git a/app-modules/prospect/src/Models/Prospect.php b/app-modules/prospect/src/Models/Prospect.php index 7b4befead0..c9f3ef5118 100644 --- a/app-modules/prospect/src/Models/Prospect.php +++ b/app-modules/prospect/src/Models/Prospect.php @@ -41,6 +41,7 @@ use App\Models\BaseModel; use App\Models\Authenticatable; use AdvisingApp\Task\Models\Task; +use App\Models\Scopes\HasLicense; use Illuminate\Support\Collection; use AdvisingApp\Alert\Models\Alert; use Illuminate\Notifications\Notifiable; @@ -186,7 +187,7 @@ public function careTeam(): MorphToMany ->using(CareTeam::class) ->withPivot('id') ->withTimestamps() - ->hasLicense($this->getLicenseType()); + ->tap(new HasLicense($this->getLicenseType())); } public function formSubmissions(): MorphMany @@ -229,7 +230,7 @@ public function subscribedUsers(): MorphToMany ->using(Subscription::class) ->withPivot('id') ->withTimestamps() - ->hasLicense($this->getLicenseType()); + ->tap(new HasLicense($this->getLicenseType())); } public static function getLicenseType(): LicenseType diff --git a/app-modules/student-data-model/src/Models/Student.php b/app-modules/student-data-model/src/Models/Student.php index 4c31386bcf..98c6daaed1 100644 --- a/app-modules/student-data-model/src/Models/Student.php +++ b/app-modules/student-data-model/src/Models/Student.php @@ -39,6 +39,7 @@ use App\Models\User; use App\Models\Authenticatable; use AdvisingApp\Task\Models\Task; +use App\Models\Scopes\HasLicense; use Illuminate\Support\Collection; use AdvisingApp\Alert\Models\Alert; use Illuminate\Database\Eloquent\Model; @@ -196,7 +197,7 @@ public function careTeam(): MorphToMany ->using(CareTeam::class) ->withPivot('id') ->withTimestamps() - ->hasLicense($this->getLicenseType()); + ->tap(new HasLicense($this->getLicenseType())); } public function subscribedUsers(): MorphToMany @@ -209,7 +210,7 @@ public function subscribedUsers(): MorphToMany ->using(Subscription::class) ->withPivot('id') ->withTimestamps() - ->hasLicense($this->getLicenseType()); + ->tap(new HasLicense($this->getLicenseType())); } public static function filamentResource(): string diff --git a/app/Models/Scopes/HasLicense.php b/app/Models/Scopes/HasLicense.php index 9dec999544..cd3c83dd21 100644 --- a/app/Models/Scopes/HasLicense.php +++ b/app/Models/Scopes/HasLicense.php @@ -39,6 +39,7 @@ use Illuminate\Support\Arr; use Illuminate\Database\Eloquent\Builder; use AdvisingApp\Authorization\Enums\LicenseType; +use Illuminate\Database\Eloquent\Relations\Relation; class HasLicense { @@ -49,7 +50,7 @@ public function __construct( protected LicenseType | string | array | null $type, ) {} - public function __invoke(Builder $query): void + public function __invoke(Builder | Relation $query): void { if (blank($this->type)) { return; From 1d6b93338013b2d5075d4aa02b048d9ab82b70f6 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 20:03:58 +0000 Subject: [PATCH 137/152] Update AssignedToRelationManager.php --- .../RelationManagers/AssignedToRelationManager.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/RelationManagers/AssignedToRelationManager.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/RelationManagers/AssignedToRelationManager.php index 2af2d6c64a..ac07cf43e3 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/RelationManagers/AssignedToRelationManager.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/RelationManagers/AssignedToRelationManager.php @@ -39,6 +39,7 @@ use App\Models\User; use Filament\Forms\Form; use Filament\Tables\Table; +use App\Models\Scopes\HasLicense; use App\Filament\Columns\IdColumn; use Filament\Tables\Actions\Action; use Filament\Forms\Components\Select; @@ -92,7 +93,7 @@ public function table(Table $table): Table ->label('Reassign Service Request To') ->searchable() ->getSearchResultsUsing(fn (string $search): array => User::query() - ->hasLicense($this->getOwnerRecord()->respondent?->getLicenseType()) + ->tap(new HasLicense($this->getOwnerRecord()->respondent?->getLicenseType())) ->where(new Expression('lower(name)'), 'like', '%' . str($search)->lower() . '%') ->pluck('name', 'id') ->all()) From a5b97bb64b4b70e646ff5e382a33804a086a740f Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Thu, 4 Jan 2024 20:32:38 +0000 Subject: [PATCH 138/152] Update composer.lock --- composer.lock | 456 +++++++++++++++++++++++++------------------------- 1 file changed, 226 insertions(+), 230 deletions(-) diff --git a/composer.lock b/composer.lock index ba8789147b..03422bbf0c 100644 --- a/composer.lock +++ b/composer.lock @@ -755,16 +755,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.295.4", + "version": "3.295.6", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "2372661db989fe4229abd95f4434b37252076d58" + "reference": "9b0b2daf46d5e6a4600575917cea0764e4dbb6b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2372661db989fe4229abd95f4434b37252076d58", - "reference": "2372661db989fe4229abd95f4434b37252076d58", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9b0b2daf46d5e6a4600575917cea0764e4dbb6b5", + "reference": "9b0b2daf46d5e6a4600575917cea0764e4dbb6b5", "shasum": "" }, "require": { @@ -844,9 +844,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.295.4" + "source": "https://github.com/aws/aws-sdk-php/tree/3.295.6" }, - "time": "2023-12-29T19:07:49+00:00" + "time": "2024-01-04T19:43:02+00:00" }, { "name": "barryvdh/laravel-debugbar", @@ -4106,16 +4106,16 @@ }, { "name": "filament/actions", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", - "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203" + "reference": "d615834a6785b87a6eaf59d4935eeb3759683d5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/actions/zipball/8f2a3df7c607a24c2433a3a71cb27b20a8dea203", - "reference": "8f2a3df7c607a24c2433a3a71cb27b20a8dea203", + "url": "https://api.github.com/repos/filamentphp/actions/zipball/d615834a6785b87a6eaf59d4935eeb3759683d5d", + "reference": "d615834a6785b87a6eaf59d4935eeb3759683d5d", "shasum": "" }, "require": { @@ -4153,20 +4153,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:29+00:00" + "time": "2024-01-04T20:29:07+00:00" }, { "name": "filament/filament", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "ae12dc49094560188a4289778a54773045880e44" + "reference": "4c6f1e1efdd3be5582af249055b893a09123777e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/ae12dc49094560188a4289778a54773045880e44", - "reference": "ae12dc49094560188a4289778a54773045880e44", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/4c6f1e1efdd3be5582af249055b893a09123777e", + "reference": "4c6f1e1efdd3be5582af249055b893a09123777e", "shasum": "" }, "require": { @@ -4218,20 +4218,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:35+00:00" + "time": "2024-01-04T12:28:40+00:00" }, { "name": "filament/forms", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506" + "reference": "23526fc23555d55d3fb3b9965efeba2ac04d6bbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/26e177a4b3a8ef7b8326d992bb5073f02220a506", - "reference": "26e177a4b3a8ef7b8326d992bb5073f02220a506", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/23526fc23555d55d3fb3b9965efeba2ac04d6bbf", + "reference": "23526fc23555d55d3fb3b9965efeba2ac04d6bbf", "shasum": "" }, "require": { @@ -4274,20 +4274,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T15:54:30+00:00" + "time": "2024-01-04T12:28:34+00:00" }, { "name": "filament/infolists", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", - "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3" + "reference": "5bc1bfb47d34efd0ee7b3cee43d18996f99d9999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/infolists/zipball/66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", - "reference": "66d69c06dbcf74a72dd3a435eda27b1e5e11eaf3", + "url": "https://api.github.com/repos/filamentphp/infolists/zipball/5bc1bfb47d34efd0ee7b3cee43d18996f99d9999", + "reference": "5bc1bfb47d34efd0ee7b3cee43d18996f99d9999", "shasum": "" }, "require": { @@ -4325,11 +4325,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-26T22:39:20+00:00" + "time": "2024-01-02T23:07:20+00:00" }, { "name": "filament/notifications", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", @@ -4381,16 +4381,16 @@ }, { "name": "filament/spatie-laravel-media-library-plugin", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-media-library-plugin.git", - "reference": "386775c13dab597df57b9b02fcb3cc1535700c97" + "reference": "64337a634115ea27602e972389c555f2a2e3f3d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/spatie-laravel-media-library-plugin/zipball/386775c13dab597df57b9b02fcb3cc1535700c97", - "reference": "386775c13dab597df57b9b02fcb3cc1535700c97", + "url": "https://api.github.com/repos/filamentphp/spatie-laravel-media-library-plugin/zipball/64337a634115ea27602e972389c555f2a2e3f3d3", + "reference": "64337a634115ea27602e972389c555f2a2e3f3d3", "shasum": "" }, "require": { @@ -4414,11 +4414,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-17T22:25:47+00:00" + "time": "2024-01-04T20:29:06+00:00" }, { "name": "filament/spatie-laravel-settings-plugin", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/spatie-laravel-settings-plugin.git", @@ -4465,16 +4465,16 @@ }, { "name": "filament/support", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "97792dad038a87b7a6bfe465c4f1913252c99017" + "reference": "bb580e362e66ae8071d8386e13841c1dc1a252b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/97792dad038a87b7a6bfe465c4f1913252c99017", - "reference": "97792dad038a87b7a6bfe465c4f1913252c99017", + "url": "https://api.github.com/repos/filamentphp/support/zipball/bb580e362e66ae8071d8386e13841c1dc1a252b4", + "reference": "bb580e362e66ae8071d8386e13841c1dc1a252b4", "shasum": "" }, "require": { @@ -4518,20 +4518,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-24T21:16:58+00:00" + "time": "2024-01-04T12:29:08+00:00" }, { "name": "filament/tables", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118" + "reference": "ba00ac1bf300756a4b240decf8c82d550ff2d024" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/e0701467097f6a82b235ad9f31e3c30ae1035118", - "reference": "e0701467097f6a82b235ad9f31e3c30ae1035118", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/ba00ac1bf300756a4b240decf8c82d550ff2d024", + "reference": "ba00ac1bf300756a4b240decf8c82d550ff2d024", "shasum": "" }, "require": { @@ -4571,20 +4571,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T17:31:59+00:00" + "time": "2024-01-04T12:29:06+00:00" }, { "name": "filament/widgets", - "version": "v3.1.31", + "version": "v3.1.35", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", - "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd" + "reference": "d9baa132c89f58f537b41cdfb319cc90d8a21e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/widgets/zipball/26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", - "reference": "26240d5f7d6aec4dd9c5987880b4deb5f9000ddd", + "url": "https://api.github.com/repos/filamentphp/widgets/zipball/d9baa132c89f58f537b41cdfb319cc90d8a21e34", + "reference": "d9baa132c89f58f537b41cdfb319cc90d8a21e34", "shasum": "" }, "require": { @@ -4615,7 +4615,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2023-12-28T17:31:57+00:00" + "time": "2024-01-02T23:08:01+00:00" }, { "name": "firebase/php-jwt", @@ -5120,27 +5120,27 @@ }, { "name": "google/apiclient", - "version": "v2.15.1", + "version": "v2.15.3", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client.git", - "reference": "7a95ed29e4b6c6859d2d22300c5455a92e2622ad" + "reference": "e70273c06d18824de77e114247ae3102f8aec64d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/7a95ed29e4b6c6859d2d22300c5455a92e2622ad", - "reference": "7a95ed29e4b6c6859d2d22300c5455a92e2622ad", + "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/e70273c06d18824de77e114247ae3102f8aec64d", + "reference": "e70273c06d18824de77e114247ae3102f8aec64d", "shasum": "" }, "require": { "firebase/php-jwt": "~6.0", "google/apiclient-services": "~0.200", - "google/auth": "^1.28", - "guzzlehttp/guzzle": "~6.5||~7.0", + "google/auth": "^1.33", + "guzzlehttp/guzzle": "^6.5.8||^7.4.5", "guzzlehttp/psr7": "^1.8.4||^2.2.1", "monolog/monolog": "^2.9||^3.0", "php": "^7.4|^8.0", - "phpseclib/phpseclib": "^3.0.19" + "phpseclib/phpseclib": "^3.0.34" }, "require-dev": { "cache/filesystem-adapter": "^1.1", @@ -5148,7 +5148,7 @@ "phpcompatibility/php-compatibility": "^9.2", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", - "squizlabs/php_codesniffer": "^3.0", + "squizlabs/php_codesniffer": "^3.8", "symfony/css-selector": "~2.1", "symfony/dom-crawler": "~2.1" }, @@ -5183,13 +5183,13 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client/issues", - "source": "https://github.com/googleapis/google-api-php-client/tree/v2.15.1" + "source": "https://github.com/googleapis/google-api-php-client/tree/v2.15.3" }, - "time": "2023-09-13T21:46:39+00:00" + "time": "2024-01-04T19:15:22+00:00" }, { "name": "google/apiclient-services", - "version": "v0.329.0", + "version": "v0.330.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", @@ -5227,22 +5227,22 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.329.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.330.0" }, "time": "2023-12-24T01:02:15+00:00" }, { "name": "google/auth", - "version": "v1.33.0", + "version": "v1.34.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-auth-library-php.git", - "reference": "682dc6c30bb509953c9e43bb0960d901582da00b" + "reference": "155daeadfd2f09743f611ea493b828d382519575" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/682dc6c30bb509953c9e43bb0960d901582da00b", - "reference": "682dc6c30bb509953c9e43bb0960d901582da00b", + "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/155daeadfd2f09743f611ea493b828d382519575", + "reference": "155daeadfd2f09743f611ea493b828d382519575", "shasum": "" }, "require": { @@ -5285,9 +5285,9 @@ "support": { "docs": "https://googleapis.github.io/google-auth-library-php/main/", "issues": "https://github.com/googleapis/google-auth-library-php/issues", - "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.33.0" + "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.34.0" }, - "time": "2023-11-30T15:49:27+00:00" + "time": "2024-01-03T20:45:15+00:00" }, { "name": "graham-campbell/result-type", @@ -6881,16 +6881,16 @@ }, { "name": "lastdragon-ru/lara-asp-core", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-core.git", - "reference": "36108ae9dfc8764f601e2187b5a795a5071b19fc" + "reference": "77f40f8b6ce69df7ddf90d04dfbcff751ca8416d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-core/zipball/36108ae9dfc8764f601e2187b5a795a5071b19fc", - "reference": "36108ae9dfc8764f601e2187b5a795a5071b19fc", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-core/zipball/77f40f8b6ce69df7ddf90d04dfbcff751ca8416d", + "reference": "77f40f8b6ce69df7ddf90d04dfbcff751ca8416d", "shasum": "" }, "require": { @@ -6932,20 +6932,20 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "lastdragon-ru/lara-asp-eloquent", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-eloquent.git", - "reference": "9a63254e9fd4819de32e0be3bab0f6424de1ecc6" + "reference": "f588294e635b809cbc67abeeede18d497cff897e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-eloquent/zipball/9a63254e9fd4819de32e0be3bab0f6424de1ecc6", - "reference": "9a63254e9fd4819de32e0be3bab0f6424de1ecc6", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-eloquent/zipball/f588294e635b809cbc67abeeede18d497cff897e", + "reference": "f588294e635b809cbc67abeeede18d497cff897e", "shasum": "" }, "require": { @@ -6992,20 +6992,20 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "lastdragon-ru/lara-asp-graphql", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-graphql.git", - "reference": "94570deceba9b2639fb810df43c13a52ccf40f19" + "reference": "d3450a790badba452d7add51b7bf2e2fa2446c3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-graphql/zipball/94570deceba9b2639fb810df43c13a52ccf40f19", - "reference": "94570deceba9b2639fb810df43c13a52ccf40f19", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-graphql/zipball/d3450a790badba452d7add51b7bf2e2fa2446c3f", + "reference": "d3450a790badba452d7add51b7bf2e2fa2446c3f", "shasum": "" }, "require": { @@ -7066,20 +7066,20 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "lastdragon-ru/lara-asp-graphql-printer", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-graphql-printer.git", - "reference": "93fc1f40a025b4a2ece5c8bab6cc82509d8a79da" + "reference": "37e0a8e5c38b7bcbb5086cd715fe84cab9de3a39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-graphql-printer/zipball/93fc1f40a025b4a2ece5c8bab6cc82509d8a79da", - "reference": "93fc1f40a025b4a2ece5c8bab6cc82509d8a79da", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-graphql-printer/zipball/37e0a8e5c38b7bcbb5086cd715fe84cab9de3a39", + "reference": "37e0a8e5c38b7bcbb5086cd715fe84cab9de3a39", "shasum": "" }, "require": { @@ -7120,20 +7120,20 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "lastdragon-ru/lara-asp-serializer", - "version": "5.3.1", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/LastDragon-ru/lara-asp-serializer.git", - "reference": "2e59e3c8984f680d57ad0a3bb0f66b7d626d1c21" + "reference": "23c7cb4b152a47af1146ee82317b749d7600ccbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-serializer/zipball/2e59e3c8984f680d57ad0a3bb0f66b7d626d1c21", - "reference": "2e59e3c8984f680d57ad0a3bb0f66b7d626d1c21", + "url": "https://api.github.com/repos/LastDragon-ru/lara-asp-serializer/zipball/23c7cb4b152a47af1146ee82317b749d7600ccbc", + "reference": "23c7cb4b152a47af1146ee82317b749d7600ccbc", "shasum": "" }, "require": { @@ -7185,7 +7185,7 @@ "issues": "https://github.com/LastDragon-ru/lara-asp/issues", "source": "https://github.com/LastDragon-ru/lara-asp" }, - "time": "2023-12-13T05:06:05+00:00" + "time": "2024-01-01T05:37:16+00:00" }, { "name": "league/commonmark", @@ -8122,35 +8122,35 @@ }, { "name": "livewire/livewire", - "version": "v3.3.3", + "version": "v3.3.5", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "6dd3bec8c711cd792742be4620057637e261e6f7" + "reference": "1ef880fbcdc7b6e5e405cc9135a62cd5fdbcd06a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/6dd3bec8c711cd792742be4620057637e261e6f7", - "reference": "6dd3bec8c711cd792742be4620057637e261e6f7", + "url": "https://api.github.com/repos/livewire/livewire/zipball/1ef880fbcdc7b6e5e405cc9135a62cd5fdbcd06a", + "reference": "1ef880fbcdc7b6e5e405cc9135a62cd5fdbcd06a", "shasum": "" }, "require": { - "illuminate/database": "^10.0", - "illuminate/support": "^10.0", - "illuminate/validation": "^10.0", + "illuminate/database": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0", + "illuminate/validation": "^10.0|^11.0", "league/mime-type-detection": "^1.9", "php": "^8.1", - "symfony/http-kernel": "^6.2" + "symfony/http-kernel": "^6.2|^7.0" }, "require-dev": { "calebporzio/sushi": "^2.1", - "laravel/framework": "^10.0", + "laravel/framework": "^10.0|^11.0", "laravel/prompts": "^0.1.6", "mockery/mockery": "^1.3.1", - "orchestra/testbench": "^8.0", - "orchestra/testbench-dusk": "^8.0", - "phpunit/phpunit": "^9.0", - "psy/psysh": "@stable" + "orchestra/testbench": "^8.0|^9.0", + "orchestra/testbench-dusk": "^8.0|^9.0", + "phpunit/phpunit": "^10.4", + "psy/psysh": "^0.11.22|^0.12" }, "type": "library", "extra": { @@ -8184,7 +8184,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.3.3" + "source": "https://github.com/livewire/livewire/tree/v3.3.5" }, "funding": [ { @@ -8192,7 +8192,7 @@ "type": "github" } ], - "time": "2023-12-20T05:34:05+00:00" + "time": "2024-01-02T14:29:17+00:00" }, { "name": "maatwebsite/excel", @@ -10306,16 +10306,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.5", + "version": "1.25.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc" + "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fedf211ff14ec8381c9bf5714e33a7a552dd1acc", - "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bd84b629c8de41aa2ae82c067c955e06f1b00240", + "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240", "shasum": "" }, "require": { @@ -10347,9 +10347,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.5" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.25.0" }, - "time": "2023-12-16T09:33:33+00:00" + "time": "2024-01-04T17:06:16+00:00" }, { "name": "psr/cache", @@ -13216,16 +13216,16 @@ }, { "name": "symfony/console", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd" + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a550a7c99daeedef3f9d23fb82e3531525ff11fd", - "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd", + "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", "shasum": "" }, "require": { @@ -13290,7 +13290,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.1" + "source": "https://github.com/symfony/console/tree/v6.4.2" }, "funding": [ { @@ -13306,7 +13306,7 @@ "type": "tidelift" } ], - "time": "2023-11-30T10:54:28+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/css-selector", @@ -13517,16 +13517,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v7.0.0", + "version": "v7.0.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e" + "reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c459b40ffe67c49af6fd392aac374c9edf8a027e", - "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/098b62ae81fdd6cbf941f355059f617db28f4f9a", + "reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a", "shasum": "" }, "require": { @@ -13577,7 +13577,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.2" }, "funding": [ { @@ -13593,7 +13593,7 @@ "type": "tidelift" } ], - "time": "2023-07-27T16:29:09+00:00" + "time": "2023-12-27T22:24:19+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -13869,16 +13869,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771" + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/44a6d39a9cc11e154547d882d5aac1e014440771", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/172d807f9ef3fc3fbed8377cc57c20d389269271", + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271", "shasum": "" }, "require": { @@ -13926,7 +13926,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.0" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.2" }, "funding": [ { @@ -13942,20 +13942,20 @@ "type": "tidelift" } ], - "time": "2023-11-20T16:41:16+00:00" + "time": "2023-12-27T22:16:42+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "2953274c16a229b3933ef73a6898e18388e12e1b" + "reference": "13e8387320b5942d0dc408440c888e2d526efef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2953274c16a229b3933ef73a6898e18388e12e1b", - "reference": "2953274c16a229b3933ef73a6898e18388e12e1b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/13e8387320b5942d0dc408440c888e2d526efef4", + "reference": "13e8387320b5942d0dc408440c888e2d526efef4", "shasum": "" }, "require": { @@ -14039,7 +14039,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.1" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.2" }, "funding": [ { @@ -14055,20 +14055,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T17:02:02+00:00" + "time": "2023-12-30T15:31:44+00:00" }, { "name": "symfony/mailer", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba" + "reference": "6da89e5c9202f129717a770a03183fb140720168" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", - "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", + "url": "https://api.github.com/repos/symfony/mailer/zipball/6da89e5c9202f129717a770a03183fb140720168", + "reference": "6da89e5c9202f129717a770a03183fb140720168", "shasum": "" }, "require": { @@ -14119,7 +14119,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.4.0" + "source": "https://github.com/symfony/mailer/tree/v6.4.2" }, "funding": [ { @@ -14135,7 +14135,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T18:02:22+00:00" + "time": "2023-12-19T09:12:31+00:00" }, { "name": "symfony/mime", @@ -15119,16 +15119,16 @@ }, { "name": "symfony/process", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa" + "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/191703b1566d97a5425dc969e4350d32b8ef17aa", - "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa", + "url": "https://api.github.com/repos/symfony/process/zipball/c4b1ef0bc80533d87a2e969806172f1c2a980241", + "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241", "shasum": "" }, "require": { @@ -15160,7 +15160,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.0" + "source": "https://github.com/symfony/process/tree/v6.4.2" }, "funding": [ { @@ -15176,7 +15176,7 @@ "type": "tidelift" } ], - "time": "2023-11-17T21:06:49+00:00" + "time": "2023-12-22T16:42:54+00:00" }, { "name": "symfony/property-access", @@ -15340,16 +15340,16 @@ }, { "name": "symfony/routing", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40" + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0c95c164fdba18b12523b75e64199ca3503e6d40", - "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40", + "url": "https://api.github.com/repos/symfony/routing/zipball/98eab13a07fddc85766f1756129c69f207ffbc21", + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21", "shasum": "" }, "require": { @@ -15403,7 +15403,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.1" + "source": "https://github.com/symfony/routing/tree/v6.4.2" }, "funding": [ { @@ -15419,20 +15419,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T14:54:37+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/serializer", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "7ead272e62c9567df619ef3c49809bf934ddbc1f" + "reference": "f87ea9d7bfd4cf2f7b72be554607e6c96e6664af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/7ead272e62c9567df619ef3c49809bf934ddbc1f", - "reference": "7ead272e62c9567df619ef3c49809bf934ddbc1f", + "url": "https://api.github.com/repos/symfony/serializer/zipball/f87ea9d7bfd4cf2f7b72be554607e6c96e6664af", + "reference": "f87ea9d7bfd4cf2f7b72be554607e6c96e6664af", "shasum": "" }, "require": { @@ -15501,7 +15501,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.4.1" + "source": "https://github.com/symfony/serializer/tree/v6.4.2" }, "funding": [ { @@ -15517,7 +15517,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T14:54:37+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/service-contracts", @@ -15603,16 +15603,16 @@ }, { "name": "symfony/string", - "version": "v7.0.0", + "version": "v7.0.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620" + "reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/92bd2bfbba476d4a1838e5e12168bef2fd1e6620", - "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620", + "url": "https://api.github.com/repos/symfony/string/zipball/cc78f14f91f5e53b42044d0620961c48028ff9f5", + "reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5", "shasum": "" }, "require": { @@ -15669,7 +15669,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.0" + "source": "https://github.com/symfony/string/tree/v7.0.2" }, "funding": [ { @@ -15685,20 +15685,20 @@ "type": "tidelift" } ], - "time": "2023-11-29T08:40:23+00:00" + "time": "2023-12-10T16:54:46+00:00" }, { "name": "symfony/translation", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37" + "reference": "a2ab2ec1a462e53016de8e8d5e8912bfd62ea681" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", - "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", + "url": "https://api.github.com/repos/symfony/translation/zipball/a2ab2ec1a462e53016de8e8d5e8912bfd62ea681", + "reference": "a2ab2ec1a462e53016de8e8d5e8912bfd62ea681", "shasum": "" }, "require": { @@ -15764,7 +15764,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.0" + "source": "https://github.com/symfony/translation/tree/v6.4.2" }, "funding": [ { @@ -15780,7 +15780,7 @@ "type": "tidelift" } ], - "time": "2023-11-29T08:14:36+00:00" + "time": "2023-12-18T09:25:29+00:00" }, { "name": "symfony/translation-contracts", @@ -15936,16 +15936,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", "shasum": "" }, "require": { @@ -16001,7 +16001,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.0" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.2" }, "funding": [ { @@ -16017,7 +16017,7 @@ "type": "tidelift" } ], - "time": "2023-11-09T08:28:32+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "tapp/filament-timezone-field", @@ -16983,16 +16983,16 @@ }, { "name": "fakerphp/faker", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01" + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", - "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", "shasum": "" }, "require": { @@ -17018,11 +17018,6 @@ "ext-mbstring": "Required for multibyte Unicode string functionality." }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "v1.21-dev" - } - }, "autoload": { "psr-4": { "Faker\\": "src/Faker/" @@ -17045,9 +17040,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.23.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" }, - "time": "2023-06-12T08:44:38+00:00" + "time": "2024-01-02T13:46:09+00:00" }, { "name": "fidry/cpu-core-counter", @@ -17183,21 +17178,22 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.44.0", + "version": "v3.46.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "5445834057a744c1a434ed60fcac566b4de3a0f2" + "reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/5445834057a744c1a434ed60fcac566b4de3a0f2", - "reference": "5445834057a744c1a434ed60fcac566b4de3a0f2", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/be6831c9af1740470d2a773119b9273f8ac1c3d2", + "reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2", "shasum": "" }, "require": { "composer/semver": "^3.4", "composer/xdebug-handler": "^3.0.3", + "ext-filter": "*", "ext-json": "*", "ext-tokenizer": "*", "php": "^7.4 || ^8.0", @@ -17261,7 +17257,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.44.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.46.0" }, "funding": [ { @@ -17269,7 +17265,7 @@ "type": "github" } ], - "time": "2023-12-29T20:21:16+00:00" + "time": "2024-01-03T21:38:46+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -17383,36 +17379,36 @@ }, { "name": "larastan/larastan", - "version": "v2.7.0", + "version": "v2.8.0", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "a2610d46b9999cf558d9900ccb641962d1442f55" + "reference": "d60c1a6d49fcbb54b78922a955a55820abdbe3c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/a2610d46b9999cf558d9900ccb641962d1442f55", - "reference": "a2610d46b9999cf558d9900ccb641962d1442f55", + "url": "https://api.github.com/repos/larastan/larastan/zipball/d60c1a6d49fcbb54b78922a955a55820abdbe3c7", + "reference": "d60c1a6d49fcbb54b78922a955a55820abdbe3c7", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^9.52.16 || ^10.28.0", - "illuminate/container": "^9.52.16 || ^10.28.0", - "illuminate/contracts": "^9.52.16 || ^10.28.0", - "illuminate/database": "^9.52.16 || ^10.28.0", - "illuminate/http": "^9.52.16 || ^10.28.0", - "illuminate/pipeline": "^9.52.16 || ^10.28.0", - "illuminate/support": "^9.52.16 || ^10.28.0", + "illuminate/console": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/container": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/contracts": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/database": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/http": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/pipeline": "^9.52.16 || ^10.28.0 || ^11.0", + "illuminate/support": "^9.52.16 || ^10.28.0 || ^11.0", "php": "^8.0.2", "phpmyadmin/sql-parser": "^5.8.2", - "phpstan/phpstan": "^1.10.41" + "phpstan/phpstan": "^1.10.50" }, "require-dev": { "nikic/php-parser": "^4.17.1", - "orchestra/canvas": "^7.11.1 || ^8.11.0", - "orchestra/testbench": "^7.33.0 || ^8.13.0", - "phpunit/phpunit": "^9.6.13" + "orchestra/canvas": "^7.11.1 || ^8.11.0 || ^9.0.0", + "orchestra/testbench": "^7.33.0 || ^8.13.0 || ^9.0.0", + "phpunit/phpunit": "^9.6.13 || ^10.5" }, "suggest": { "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" @@ -17460,7 +17456,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v2.7.0" + "source": "https://github.com/larastan/larastan/tree/v2.8.0" }, "funding": [ { @@ -17480,7 +17476,7 @@ "type": "patreon" } ], - "time": "2023-12-04T19:21:38+00:00" + "time": "2024-01-02T22:09:07+00:00" }, { "name": "laravel/sail", @@ -20131,16 +20127,16 @@ }, { "name": "spatie/ignition", - "version": "1.11.3", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044" + "reference": "5b6f801c605a593106b623e45ca41496a6e7d56d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/3d886de644ff7a5b42e4d27c1e1f67c8b5f00044", - "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044", + "url": "https://api.github.com/repos/spatie/ignition/zipball/5b6f801c605a593106b623e45ca41496a6e7d56d", + "reference": "5b6f801c605a593106b623e45ca41496a6e7d56d", "shasum": "" }, "require": { @@ -20210,39 +20206,39 @@ "type": "github" } ], - "time": "2023-10-18T14:09:40+00:00" + "time": "2024-01-03T15:49:39+00:00" }, { "name": "spatie/laravel-ignition", - "version": "2.3.3", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "66499cd3c858642ded56dafb8fa0352057ca20dd" + "reference": "b9395ba48d3f30d42092cf6ceff75ed7256cd604" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/66499cd3c858642ded56dafb8fa0352057ca20dd", - "reference": "66499cd3c858642ded56dafb8fa0352057ca20dd", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/b9395ba48d3f30d42092cf6ceff75ed7256cd604", + "reference": "b9395ba48d3f30d42092cf6ceff75ed7256cd604", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "illuminate/support": "^10.0", + "illuminate/support": "^10.0|^11.0", "php": "^8.1", "spatie/flare-client-php": "^1.3.5", "spatie/ignition": "^1.9", - "symfony/console": "^6.2.3", - "symfony/var-dumper": "^6.2.3" + "symfony/console": "^6.2.3|^7.0", + "symfony/var-dumper": "^6.2.3|^7.0" }, "require-dev": { - "livewire/livewire": "^2.11", + "livewire/livewire": "^2.11|^3.3.5", "mockery/mockery": "^1.5.1", - "openai-php/client": "^0.3.4", - "orchestra/testbench": "^8.0", - "pestphp/pest": "^1.22.3", + "openai-php/client": "^0.8.1", + "orchestra/testbench": "^8.0|^9.0", + "pestphp/pest": "^2.30", "phpstan/extension-installer": "^1.2", "phpstan/phpstan-deprecation-rules": "^1.1.1", "phpstan/phpstan-phpunit": "^1.3.3", @@ -20302,7 +20298,7 @@ "type": "github" } ], - "time": "2023-12-21T09:43:05+00:00" + "time": "2024-01-04T14:51:24+00:00" }, { "name": "spatie/laravel-ray", @@ -21202,5 +21198,5 @@ "ext-pdo": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From 7d575a042696b923173f25c6f3717f1469eedd36 Mon Sep 17 00:00:00 2001 From: danharrin Date: Thu, 4 Jan 2024 20:36:51 +0000 Subject: [PATCH 139/152] chore: fix code style --- config/data.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/data.php b/config/data.php index 9cd8296ad4..6a92fd3033 100644 --- a/config/data.php +++ b/config/data.php @@ -47,8 +47,8 @@ * types. */ 'transformers' => [ - DateTimeInterface::class => \Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer::class, - \Illuminate\Contracts\Support\Arrayable::class => \Spatie\LaravelData\Transformers\ArrayableTransformer::class, + DateTimeInterface::class => Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer::class, + Illuminate\Contracts\Support\Arrayable::class => Spatie\LaravelData\Transformers\ArrayableTransformer::class, BackedEnum::class => Spatie\LaravelData\Transformers\EnumTransformer::class, ], From 12de47ab9126d680ecbd12d7379c72c24abba5d5 Mon Sep 17 00:00:00 2001 From: Matthew Myers Date: Thu, 4 Jan 2024 17:08:36 -0500 Subject: [PATCH 140/152] Fix composer. --- composer.lock | 73 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/composer.lock b/composer.lock index 03422bbf0c..938786121b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "19b34ef965a1ec4aa7ec0deb038e20bd", + "content-hash": "8f6e763126265c0256844dae31464a24", "packages": [ { "name": "amphp/amp", @@ -559,16 +559,16 @@ }, { "name": "awcodes/filament-tiptap-editor", - "version": "v3.2.18", + "version": "v3.2.19", "source": { "type": "git", "url": "https://github.com/awcodes/filament-tiptap-editor.git", - "reference": "7de016e723ba62908f979a39204955e1801b0967" + "reference": "88db4735a2a8f7bc74e62b48446b7d806afec723" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/7de016e723ba62908f979a39204955e1801b0967", - "reference": "7de016e723ba62908f979a39204955e1801b0967", + "url": "https://api.github.com/repos/awcodes/filament-tiptap-editor/zipball/88db4735a2a8f7bc74e62b48446b7d806afec723", + "reference": "88db4735a2a8f7bc74e62b48446b7d806afec723", "shasum": "" }, "require": { @@ -630,7 +630,7 @@ ], "support": { "issues": "https://github.com/awcodes/filament-tiptap-editor/issues", - "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.18" + "source": "https://github.com/awcodes/filament-tiptap-editor/tree/v3.2.19" }, "funding": [ { @@ -638,7 +638,7 @@ "type": "github" } ], - "time": "2023-12-28T20:05:06+00:00" + "time": "2024-01-04T21:41:06+00:00" }, { "name": "aws/aws-crt-php", @@ -2379,6 +2379,41 @@ "relative": true } }, + { + "name": "canyon-gbs/analytics", + "version": "1.0", + "dist": { + "type": "path", + "url": "app-modules/analytics", + "reference": "ee7fa00ee78ce3e31c49566043aaf89cca68ad6b" + }, + "require": { + "filament/filament": "^3.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "AdvisingApp\\Analytics\\Providers\\AnalyticsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "AdvisingApp\\Analytics\\": "src/", + "AdvisingApp\\Analytics\\Tests\\": "tests/", + "AdvisingApp\\Analytics\\Database\\Factories\\": "database/factories/", + "AdvisingApp\\Analytics\\Database\\Seeders\\": "database/seeders/" + } + }, + "license": [ + "proprietary" + ], + "transport-options": { + "symlink": true, + "relative": true + } + }, { "name": "canyon-gbs/inventory-management", "version": "1.0", @@ -18487,16 +18522,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.50", + "version": "1.10.51", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4" + "reference": "5082fa72dc13944578806ca1196a385818d8b077" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/06a98513ac72c03e8366b5a0cb00750b487032e4", - "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5082fa72dc13944578806ca1196a385818d8b077", + "reference": "5082fa72dc13944578806ca1196a385818d8b077", "shasum": "" }, "require": { @@ -18545,7 +18580,7 @@ "type": "tidelift" } ], - "time": "2023-12-13T10:59:42+00:00" + "time": "2024-01-04T21:16:30+00:00" }, { "name": "phpunit/php-code-coverage", @@ -20302,16 +20337,16 @@ }, { "name": "spatie/laravel-ray", - "version": "1.33.0", + "version": "1.33.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ray.git", - "reference": "5028ae44a09451b26eb44490e3471998650788e3" + "reference": "b9574cec543b932d99e68247eaeb37876c71c8eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/5028ae44a09451b26eb44490e3471998650788e3", - "reference": "5028ae44a09451b26eb44490e3471998650788e3", + "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/b9574cec543b932d99e68247eaeb37876c71c8eb", + "reference": "b9574cec543b932d99e68247eaeb37876c71c8eb", "shasum": "" }, "require": { @@ -20323,7 +20358,7 @@ "php": "^7.4|^8.0", "spatie/backtrace": "^1.0", "spatie/ray": "^1.37", - "symfony/stopwatch": "4.2|^5.1|^6.0", + "symfony/stopwatch": "4.2|^5.1|^6.0|^7.0", "zbateson/mail-mime-parser": "^1.3.1|^2.0" }, "require-dev": { @@ -20371,7 +20406,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-ray/issues", - "source": "https://github.com/spatie/laravel-ray/tree/1.33.0" + "source": "https://github.com/spatie/laravel-ray/tree/1.33.1" }, "funding": [ { @@ -20383,7 +20418,7 @@ "type": "other" } ], - "time": "2023-09-04T10:16:53+00:00" + "time": "2024-01-04T21:36:17+00:00" }, { "name": "spatie/macroable", From 631ad2a00742e968d3fd0dbb11754e956a35d734 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 18:36:53 -0500 Subject: [PATCH 141/152] Fix booted for submissions Signed-off-by: Kevin Ullyott --- .../application/src/Models/ApplicationSubmission.php | 9 +++++++++ app-modules/form/src/Actions/ResolveBlockRegistry.php | 3 ++- app-modules/form/src/Models/FormSubmission.php | 8 ++++++++ app-modules/form/src/Models/Submission.php | 9 --------- app-modules/survey/src/Models/SurveySubmission.php | 8 ++++++++ 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/app-modules/application/src/Models/ApplicationSubmission.php b/app-modules/application/src/Models/ApplicationSubmission.php index d0bed4dbf5..3938dc574d 100644 --- a/app-modules/application/src/Models/ApplicationSubmission.php +++ b/app-modules/application/src/Models/ApplicationSubmission.php @@ -37,8 +37,10 @@ namespace AdvisingApp\Application\Models; use AdvisingApp\Form\Models\Submission; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; /** * @mixin IdeHelperApplicationSubmission @@ -68,4 +70,11 @@ public function state(): BelongsTo return $this ->belongsTo(ApplicationSubmissionState::class, 'state_id'); } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->tap(new LicensedToEducatable('author')); + }); + } } diff --git a/app-modules/form/src/Actions/ResolveBlockRegistry.php b/app-modules/form/src/Actions/ResolveBlockRegistry.php index daba532442..d904945db5 100644 --- a/app-modules/form/src/Actions/ResolveBlockRegistry.php +++ b/app-modules/form/src/Actions/ResolveBlockRegistry.php @@ -40,6 +40,7 @@ use AdvisingApp\Survey\Models\Survey; use AdvisingApp\Form\Models\Submissible; use AdvisingApp\Application\Models\Application; +use AdvisingApp\MeetingCenter\Models\EventRegistrationForm; use AdvisingApp\Form\Filament\Blocks\FormFieldBlockRegistry; use AdvisingApp\Survey\Filament\Blocks\SurveyFieldBlockRegistry; @@ -48,7 +49,7 @@ class ResolveBlockRegistry public function __invoke(Submissible $submissible): array { return match ($submissible::class) { - Form::class, Application::class => FormFieldBlockRegistry::keyByType(), + Form::class, Application::class, EventRegistrationForm::class => FormFieldBlockRegistry::keyByType(), Survey::class => SurveyFieldBlockRegistry::keyByType(), }; } diff --git a/app-modules/form/src/Models/FormSubmission.php b/app-modules/form/src/Models/FormSubmission.php index 047f67bdb9..d79ea27539 100644 --- a/app-modules/form/src/Models/FormSubmission.php +++ b/app-modules/form/src/Models/FormSubmission.php @@ -44,6 +44,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use AdvisingApp\Form\Enums\FormSubmissionRequestDeliveryMethod; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; /** * @property Student|Prospect|null $author @@ -130,4 +131,11 @@ public function getStatus(): FormSubmissionStatus return FormSubmissionStatus::Requested; } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->tap(new LicensedToEducatable('author')); + }); + } } diff --git a/app-modules/form/src/Models/Submission.php b/app-modules/form/src/Models/Submission.php index 0e986b4082..0c2caa8918 100644 --- a/app-modules/form/src/Models/Submission.php +++ b/app-modules/form/src/Models/Submission.php @@ -38,12 +38,10 @@ use App\Models\BaseModel; use AdvisingApp\Prospect\Models\Prospect; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use AdvisingApp\StudentDataModel\Models\Student; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; -use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; use AdvisingApp\StudentDataModel\Models\Concerns\BelongsToEducatable; /** @@ -64,11 +62,4 @@ public function author(): BelongsTo return $this ->morphTo('author'); } - - protected static function booted(): void - { - static::addGlobalScope('licensed', function (Builder $builder) { - $builder->tap(new LicensedToEducatable('author')); - }); - } } diff --git a/app-modules/survey/src/Models/SurveySubmission.php b/app-modules/survey/src/Models/SurveySubmission.php index 99b639a4b3..1d19fdbd64 100644 --- a/app-modules/survey/src/Models/SurveySubmission.php +++ b/app-modules/survey/src/Models/SurveySubmission.php @@ -45,6 +45,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use AdvisingApp\Form\Enums\FormSubmissionRequestDeliveryMethod; +use AdvisingApp\StudentDataModel\Models\Scopes\LicensedToEducatable; /** * @property Student|Prospect|null $author @@ -131,4 +132,11 @@ public function getStatus(): FormSubmissionStatus return FormSubmissionStatus::Requested; } + + protected static function booted(): void + { + static::addGlobalScope('licensed', function (Builder $builder) { + $builder->tap(new LicensedToEducatable('author')); + }); + } } From 0fb4b49d6f63911aee88c3fd6a644efab2825290 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 14:37:15 -0500 Subject: [PATCH 142/152] Add AI section Signed-off-by: Kevin Ullyott --- .../src/Filament/Pages/PersonalAssistant.php | 4 +- .../src/Filament/Pages/PromptLibrary.php | 50 +++++++++++++++++++ app/Providers/Filament/AdminPanelProvider.php | 2 + 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 app-modules/assistant/src/Filament/Pages/PromptLibrary.php diff --git a/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php b/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php index 286e93fd51..8652410f22 100644 --- a/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php +++ b/app-modules/assistant/src/Filament/Pages/PersonalAssistant.php @@ -78,9 +78,9 @@ class PersonalAssistant extends Page protected static string $view = 'assistant::filament.pages.personal-assistant'; - protected static ?string $navigationGroup = 'Productivity Tools'; + protected static ?string $navigationGroup = 'Artificial Intelligence'; - protected static ?int $navigationSort = 1; + protected static ?int $navigationSort = 20; public Chat $chat; diff --git a/app-modules/assistant/src/Filament/Pages/PromptLibrary.php b/app-modules/assistant/src/Filament/Pages/PromptLibrary.php new file mode 100644 index 0000000000..01e6300e5b --- /dev/null +++ b/app-modules/assistant/src/Filament/Pages/PromptLibrary.php @@ -0,0 +1,50 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\Assistant\Filament\Pages; + +use Filament\Pages\Page; + +class PromptLibrary extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-building-library'; + + protected static string $view = 'filament.pages.coming-soon'; + + protected static ?string $navigationGroup = 'Artificial Intelligence'; + + protected static ?int $navigationSort = 10; +} diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 443eea533f..883072bfe7 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -115,6 +115,8 @@ public function panel(Panel $panel): Panel Authenticate::class, ]) ->navigationGroups([ + NavigationGroup::make() + ->label('Artificial Intelligence'), NavigationGroup::make() ->label('Record Management'), NavigationGroup::make() From cb0c6f468a6f1fb894e8f20a17a2b6b0703f80fc Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 14:58:40 -0500 Subject: [PATCH 143/152] Retention CRM Signed-off-by: Kevin Ullyott --- .../Filament/Pages/RetentionCrmDashboard.php | 52 +++++++++++++++++++ .../Filament/Resources/StudentResource.php | 4 +- .../src/StudentDataModelPlugin.php | 13 +++-- app/Providers/Filament/AdminPanelProvider.php | 2 + 4 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 app-modules/student-data-model/src/Filament/Pages/RetentionCrmDashboard.php diff --git a/app-modules/student-data-model/src/Filament/Pages/RetentionCrmDashboard.php b/app-modules/student-data-model/src/Filament/Pages/RetentionCrmDashboard.php new file mode 100644 index 0000000000..fe58882a2c --- /dev/null +++ b/app-modules/student-data-model/src/Filament/Pages/RetentionCrmDashboard.php @@ -0,0 +1,52 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace AdvisingApp\StudentDataModel\Filament\Pages; + +use Filament\Pages\Page; + +class RetentionCrmDashboard extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-home'; + + protected static string $view = 'filament.pages.coming-soon'; + + protected static ?string $navigationGroup = 'Retention CRM'; + + protected static ?int $navigationSort = 10; + + protected static ?string $title = 'Dashboard'; +} diff --git a/app-modules/student-data-model/src/Filament/Resources/StudentResource.php b/app-modules/student-data-model/src/Filament/Resources/StudentResource.php index 91f8a0a430..a6970c227b 100644 --- a/app-modules/student-data-model/src/Filament/Resources/StudentResource.php +++ b/app-modules/student-data-model/src/Filament/Resources/StudentResource.php @@ -61,9 +61,9 @@ class StudentResource extends Resource protected static ?string $navigationIcon = 'heroicon-m-users'; - protected static ?string $navigationGroup = 'Record Management'; + protected static ?string $navigationGroup = 'Retention CRM'; - protected static ?int $navigationSort = 1; + protected static ?int $navigationSort = 20; protected static ?string $recordTitleAttribute = 'full_name'; diff --git a/app-modules/student-data-model/src/StudentDataModelPlugin.php b/app-modules/student-data-model/src/StudentDataModelPlugin.php index bb1573d108..4a0158f129 100644 --- a/app-modules/student-data-model/src/StudentDataModelPlugin.php +++ b/app-modules/student-data-model/src/StudentDataModelPlugin.php @@ -48,10 +48,15 @@ public function getId(): string public function register(Panel $panel): void { - $panel->discoverResources( - in: __DIR__ . '/Filament/Resources', - for: 'AdvisingApp\\StudentDataModel\\Filament\\Resources' - ); + $panel + ->discoverResources( + in: __DIR__ . '/Filament/Resources', + for: 'AdvisingApp\\StudentDataModel\\Filament\\Resources' + ) + ->discoverPages( + in: __DIR__ . '/Filament/Pages', + for: 'AdvisingApp\\StudentDataModel\\Filament\\Pages' + ); } public function boot(Panel $panel): void {} diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 883072bfe7..de5be53ff6 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -117,6 +117,8 @@ public function panel(Panel $panel): Panel ->navigationGroups([ NavigationGroup::make() ->label('Artificial Intelligence'), + NavigationGroup::make() + ->label('Retention CRM'), NavigationGroup::make() ->label('Record Management'), NavigationGroup::make() From d4ca43cf6d10d9769d4d0282ed2f6097aec6f7c6 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 15:42:26 -0500 Subject: [PATCH 144/152] Engagement Features Signed-off-by: Kevin Ullyott --- .../src/Filament/Resources/AlertResource.php | 5 +- .../Filament/Resources/CampaignResource.php | 4 +- .../Filament/Resources/CaseloadResource.php | 18 ++++--- .../CaseloadResource/Pages/ListCaseloads.php | 2 + .../src/Filament/Pages/MessageCenter.php | 4 +- .../Resources/EngagementFileResource.php | 9 ++-- .../src/Filament/Pages/UserChat.php | 2 +- .../Resources/InteractionResource.php | 9 ++-- .../Resources/KnowledgeBaseItemResource.php | 2 +- .../Resources/CalendarEventResource.php | 8 +-- .../Pages/ListCalendarEvents.php | 2 +- .../Pages/RecruitmentCrmDashboard.php | 12 +++-- .../Filament/Resources/ProspectResource.php | 4 +- app-modules/prospect/src/ProspectPlugin.php | 13 +++-- .../src/Filament/Resources/TaskResource.php | 20 +++---- app/Filament/Pages/ServiceDashboard.php | 54 ------------------- app/Providers/Filament/AdminPanelProvider.php | 8 +-- 17 files changed, 61 insertions(+), 115 deletions(-) rename app/Filament/Pages/DataLakehouse.php => app-modules/prospect/src/Filament/Pages/RecruitmentCrmDashboard.php (84%) delete mode 100644 app/Filament/Pages/ServiceDashboard.php diff --git a/app-modules/alert/src/Filament/Resources/AlertResource.php b/app-modules/alert/src/Filament/Resources/AlertResource.php index 30447b2267..39f69889ff 100644 --- a/app-modules/alert/src/Filament/Resources/AlertResource.php +++ b/app-modules/alert/src/Filament/Resources/AlertResource.php @@ -44,7 +44,7 @@ class AlertResource extends Resource { protected static ?string $navigationIcon = 'heroicon-o-document-text'; - protected static ?string $navigationGroup = 'Productivity Tools'; + protected static ?string $navigationGroup = 'Engagement Features'; protected static ?int $navigationSort = 5; @@ -52,6 +52,9 @@ class AlertResource extends Resource protected static ?string $label = 'Proactive Alert'; + // TODO: Look into whether or not we should just delete this resource + protected static bool $shouldRegisterNavigation = false; + public static function getPages(): array { return [ diff --git a/app-modules/campaign/src/Filament/Resources/CampaignResource.php b/app-modules/campaign/src/Filament/Resources/CampaignResource.php index 5ae0e99e4e..510896752d 100644 --- a/app-modules/campaign/src/Filament/Resources/CampaignResource.php +++ b/app-modules/campaign/src/Filament/Resources/CampaignResource.php @@ -50,9 +50,9 @@ class CampaignResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-megaphone'; - protected static ?string $navigationGroup = 'Mass Engagement'; + protected static ?string $navigationGroup = 'Engagement Features'; - protected static ?int $navigationSort = 2; + protected static ?int $navigationSort = 30; public static function getRelations(): array { diff --git a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource.php b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource.php index 825e36730f..f7ad4466e6 100644 --- a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource.php +++ b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource.php @@ -65,9 +65,17 @@ class CaseloadResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-inbox-stack'; - protected static ?string $navigationGroup = 'Mass Engagement'; + protected static ?string $navigationGroup = 'Engagement Features'; - protected static ?int $navigationSort = 1; + protected static ?int $navigationSort = 20; + + protected static ?string $navigationLabel = 'Caseload Management'; + + protected static ?string $breadcrumb = 'Caseload Management'; + + protected static ?string $modelLabel = 'Caseload'; + + protected static ?string $pluralModelLabel = 'Caseloads'; public static function filters(CaseloadModel $subject): array { @@ -96,12 +104,6 @@ public static function actions(CaseloadModel $subject): array }; } - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php index 24b6b714cc..b61da9405f 100644 --- a/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php +++ b/app-modules/caseload-management/src/Filament/Resources/CaseloadResource/Pages/ListCaseloads.php @@ -50,6 +50,8 @@ class ListCaseloads extends ListRecords { + protected ?string $heading = 'Caseload Management'; + protected static string $resource = CaseloadResource::class; public function table(Table $table): Table diff --git a/app-modules/engagement/src/Filament/Pages/MessageCenter.php b/app-modules/engagement/src/Filament/Pages/MessageCenter.php index 950ad5b34d..562f3d4cfb 100644 --- a/app-modules/engagement/src/Filament/Pages/MessageCenter.php +++ b/app-modules/engagement/src/Filament/Pages/MessageCenter.php @@ -70,9 +70,9 @@ class MessageCenter extends Page protected static string $view = 'engagement::filament.pages.message-center'; - protected static ?string $navigationGroup = 'Productivity Tools'; + protected static ?string $navigationGroup = 'Engagement Features'; - protected static ?int $navigationSort = 3; + protected static ?int $navigationSort = 10; protected array $modelsToTimeline = [ Engagement::class, diff --git a/app-modules/engagement/src/Filament/Resources/EngagementFileResource.php b/app-modules/engagement/src/Filament/Resources/EngagementFileResource.php index 94dd465ba4..33eb726501 100644 --- a/app-modules/engagement/src/Filament/Resources/EngagementFileResource.php +++ b/app-modules/engagement/src/Filament/Resources/EngagementFileResource.php @@ -50,7 +50,7 @@ class EngagementFileResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-document-duplicate'; - protected static ?string $navigationGroup = 'Productivity Tools'; + protected static ?string $navigationGroup = 'Engagement Features'; protected static ?int $navigationSort = 7; @@ -62,11 +62,8 @@ class EngagementFileResource extends Resource protected static ?string $pluralModelLabel = 'Files or Documents'; - public static function getRelations(): array - { - return [ - ]; - } + // TODO: Look into whether or not we should just delete this resource + protected static bool $shouldRegisterNavigation = false; public static function form(Form $form): Form { diff --git a/app-modules/in-app-communication/src/Filament/Pages/UserChat.php b/app-modules/in-app-communication/src/Filament/Pages/UserChat.php index 5964205b76..fc5322ad29 100644 --- a/app-modules/in-app-communication/src/Filament/Pages/UserChat.php +++ b/app-modules/in-app-communication/src/Filament/Pages/UserChat.php @@ -72,7 +72,7 @@ class UserChat extends Page implements HasForms, HasActions public ?string $selectedConversation = null; - protected static ?string $navigationGroup = 'Productivity Tools'; + protected static ?string $navigationGroup = 'Engagement Features'; protected static ?int $navigationSort = 2; diff --git a/app-modules/interaction/src/Filament/Resources/InteractionResource.php b/app-modules/interaction/src/Filament/Resources/InteractionResource.php index 541fe51f63..62730011c3 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionResource.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionResource.php @@ -48,15 +48,12 @@ class InteractionResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-arrow-path-rounded-square'; - protected static ?string $navigationGroup = 'Productivity Tools'; + protected static ?string $navigationGroup = 'Engagement Features'; protected static ?int $navigationSort = 6; - public static function getRelations(): array - { - return [ - ]; - } + // TODO: Look into whether or not we should just delete this resource + protected static bool $shouldRegisterNavigation = false; public static function getPages(): array { diff --git a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource.php b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource.php index 913093a8f3..3530b8bcb6 100644 --- a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource.php +++ b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource.php @@ -53,7 +53,7 @@ class KnowledgeBaseItemResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-book-open'; - protected static ?string $navigationGroup = 'Productivity Tools'; + protected static ?string $navigationGroup = 'Engagement Features'; protected static ?int $navigationSort = 8; diff --git a/app-modules/meeting-center/src/Filament/Resources/CalendarEventResource.php b/app-modules/meeting-center/src/Filament/Resources/CalendarEventResource.php index df77f1ede2..5e99d98581 100644 --- a/app-modules/meeting-center/src/Filament/Resources/CalendarEventResource.php +++ b/app-modules/meeting-center/src/Filament/Resources/CalendarEventResource.php @@ -49,13 +49,13 @@ class CalendarEventResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Meeting Center'; + protected static ?string $navigationGroup = 'Engagement Features'; - protected static ?int $navigationSort = 10; + protected static ?int $navigationSort = 50; - protected static ?string $navigationLabel = 'Schedule'; + protected static ?string $navigationLabel = 'Schedule & Appointments'; - protected static ?string $breadcrumb = 'Schedule'; + protected static ?string $breadcrumb = 'Schedule & Appointments'; protected static ?string $modelLabel = 'appointment'; diff --git a/app-modules/meeting-center/src/Filament/Resources/CalendarEventResource/Pages/ListCalendarEvents.php b/app-modules/meeting-center/src/Filament/Resources/CalendarEventResource/Pages/ListCalendarEvents.php index 19c5637374..2a6ec959f5 100644 --- a/app-modules/meeting-center/src/Filament/Resources/CalendarEventResource/Pages/ListCalendarEvents.php +++ b/app-modules/meeting-center/src/Filament/Resources/CalendarEventResource/Pages/ListCalendarEvents.php @@ -61,7 +61,7 @@ class ListCalendarEvents extends ListRecords { protected static string $resource = CalendarEventResource::class; - protected ?string $heading = 'Schedule'; + protected ?string $heading = 'Schedule & Appointments'; protected static string $view = 'meeting-center::filament.pages.list-calendar-events'; diff --git a/app/Filament/Pages/DataLakehouse.php b/app-modules/prospect/src/Filament/Pages/RecruitmentCrmDashboard.php similarity index 84% rename from app/Filament/Pages/DataLakehouse.php rename to app-modules/prospect/src/Filament/Pages/RecruitmentCrmDashboard.php index 60a856466f..51fa2e3dc5 100644 --- a/app/Filament/Pages/DataLakehouse.php +++ b/app-modules/prospect/src/Filament/Pages/RecruitmentCrmDashboard.php @@ -34,17 +34,19 @@ */ -namespace App\Filament\Pages; +namespace AdvisingApp\Prospect\Filament\Pages; use Filament\Pages\Page; -class DataLakehouse extends Page +class RecruitmentCrmDashboard extends Page { - protected static ?string $navigationIcon = 'heroicon-o-circle-stack'; + protected static ?string $navigationIcon = 'heroicon-o-home'; protected static string $view = 'filament.pages.coming-soon'; - protected static ?string $navigationGroup = 'Data and Analytics'; + protected static ?string $navigationGroup = 'Recruitment CRM'; - protected static ?int $navigationSort = 2; + protected static ?int $navigationSort = 10; + + protected static ?string $title = 'Dashboard'; } diff --git a/app-modules/prospect/src/Filament/Resources/ProspectResource.php b/app-modules/prospect/src/Filament/Resources/ProspectResource.php index 16c454e10c..5ec059fca0 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectResource.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectResource.php @@ -62,9 +62,9 @@ class ProspectResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-users'; - protected static ?string $navigationGroup = 'Record Management'; + protected static ?string $navigationGroup = 'Recruitment CRM'; - protected static ?int $navigationSort = 2; + protected static ?int $navigationSort = 20; protected static ?string $recordTitleAttribute = 'full_name'; diff --git a/app-modules/prospect/src/ProspectPlugin.php b/app-modules/prospect/src/ProspectPlugin.php index 308bbd1e41..f4bab7a480 100644 --- a/app-modules/prospect/src/ProspectPlugin.php +++ b/app-modules/prospect/src/ProspectPlugin.php @@ -48,10 +48,15 @@ public function getId(): string public function register(Panel $panel): void { - $panel->discoverResources( - in: __DIR__ . '/Filament/Resources', - for: 'AdvisingApp\\Prospect\\Filament\\Resources' - ); + $panel + ->discoverResources( + in: __DIR__ . '/Filament/Resources', + for: 'AdvisingApp\\Prospect\\Filament\\Resources' + ) + ->discoverPages( + in: __DIR__ . '/Filament/Pages', + for: 'AdvisingApp\\Prospect\\Filament\\Pages' + ); } public function boot(Panel $panel): void {} diff --git a/app-modules/task/src/Filament/Resources/TaskResource.php b/app-modules/task/src/Filament/Resources/TaskResource.php index 9b2b5d66c3..705d1cc302 100644 --- a/app-modules/task/src/Filament/Resources/TaskResource.php +++ b/app-modules/task/src/Filament/Resources/TaskResource.php @@ -38,7 +38,9 @@ use Filament\Resources\Resource; use AdvisingApp\Task\Models\Task; -use AdvisingApp\Task\Filament\Resources\TaskResource\Pages; +use AdvisingApp\Task\Filament\Resources\TaskResource\Pages\EditTask; +use AdvisingApp\Task\Filament\Resources\TaskResource\Pages\ListTasks; +use AdvisingApp\Task\Filament\Resources\TaskResource\Pages\CreateTask; class TaskResource extends Resource { @@ -46,22 +48,16 @@ class TaskResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-clipboard-document-check'; - protected static ?string $navigationGroup = 'Productivity Tools'; + protected static ?string $navigationGroup = 'Engagement Features'; - protected static ?int $navigationSort = 9; - - public static function getRelations(): array - { - return [ - ]; - } + protected static ?int $navigationSort = 40; public static function getPages(): array { return [ - 'index' => Pages\ListTasks::route('/'), - 'create' => Pages\CreateTask::route('/create'), - 'edit' => Pages\EditTask::route('/{record}/edit'), + 'index' => ListTasks::route('/'), + 'create' => CreateTask::route('/create'), + 'edit' => EditTask::route('/{record}/edit'), ]; } } diff --git a/app/Filament/Pages/ServiceDashboard.php b/app/Filament/Pages/ServiceDashboard.php deleted file mode 100644 index e6ee54ab01..0000000000 --- a/app/Filament/Pages/ServiceDashboard.php +++ /dev/null @@ -1,54 +0,0 @@ - - - Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. - - Advising App™ is licensed under the Elastic License 2.0. For more details, - see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. - - Notice: - - - You may not provide the software to third parties as a hosted or managed - service, where the service provides users with access to any substantial set of - the features or functionality of the software. - - You may not move, change, disable, or circumvent the license key functionality - in the software, and you may not remove or obscure any functionality in the - software that is protected by the license key. - - You may not alter, remove, or obscure any licensing, copyright, or other notices - of the licensor in the software. Any use of the licensor’s trademarks is subject - to applicable law. - - Canyon GBS LLC respects the intellectual property rights of others and expects the - same in return. Canyon GBS™ and Advising App™ are registered trademarks of - Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks - vigorously. - - The software solution, including services, infrastructure, and code, is offered as a - Software as a Service (SaaS) by Canyon GBS LLC. - - Use of this software implies agreement to the license terms and conditions as stated - in the Elastic License 2.0. - - For more information or inquiries please visit our website at - https://www.canyongbs.com or contact us via email at legal@canyongbs.com. - - -*/ - -namespace App\Filament\Pages; - -use Filament\Pages\Page; - -class ServiceDashboard extends Page -{ - protected static ?string $navigationIcon = 'heroicon-o-document-text'; - - protected static ?string $navigationGroup = 'Service Management'; - - protected static ?int $navigationSort = 1; - - protected static ?string $navigationLabel = 'Dashboard'; - - protected ?string $heading = 'Dashboard'; - - protected static string $view = 'filament.pages.coming-soon'; -} diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index de5be53ff6..81fde42283 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -120,11 +120,9 @@ public function panel(Panel $panel): Panel NavigationGroup::make() ->label('Retention CRM'), NavigationGroup::make() - ->label('Record Management'), + ->label('Recruitment CRM'), NavigationGroup::make() - ->label('Productivity Tools'), - NavigationGroup::make() - ->label('Service Management'), + ->label('Engagement Features'), NavigationGroup::make() ->label('Meeting Center'), NavigationGroup::make() @@ -133,8 +131,6 @@ public function panel(Panel $panel): Panel ->label('Forms and Surveys'), NavigationGroup::make() ->label('Reporting'), - NavigationGroup::make() - ->label('Data and Analytics'), NavigationGroup::make() ->label('Users and Permissions'), NavigationGroup::make() From 80228076cf60e25b04265fb391cf81e0f57db65e Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 16:14:36 -0500 Subject: [PATCH 145/152] Premium Features Signed-off-by: Kevin Ullyott --- .../Resources/ApplicationResource.php | 12 +++-- .../Pages/ListApplications.php | 2 + .../src/Filament/Resources/FormResource.php | 12 +++-- .../FormResource/Pages/ListForms.php | 4 +- .../src/Filament/Pages/UserChat.php | 4 +- .../src/Filament/Resources/AssetResource.php | 3 ++ .../Resources/KnowledgeBaseItemResource.php | 16 +++--- .../Pages/ListKnowledgeBaseItems.php | 2 + .../src/Filament/Resources/EventResource.php | 15 +++--- .../EventResource/Pages/EditEvent.php | 3 ++ .../EventResource/Pages/ListEvents.php | 2 + .../Resources/ServiceRequestResource.php | 10 +++- .../Pages/ListServiceRequests.php | 2 + .../src/Filament/Resources/SurveyResource.php | 12 +++-- .../SurveyResource/Pages/ListSurveys.php | 2 + app/Filament/Pages/ChangeManagement.php | 50 ------------------- app/Providers/Filament/AdminPanelProvider.php | 6 +-- 17 files changed, 72 insertions(+), 85 deletions(-) delete mode 100644 app/Filament/Pages/ChangeManagement.php diff --git a/app-modules/application/src/Filament/Resources/ApplicationResource.php b/app-modules/application/src/Filament/Resources/ApplicationResource.php index e7f994446d..5c9a737ba5 100644 --- a/app-modules/application/src/Filament/Resources/ApplicationResource.php +++ b/app-modules/application/src/Filament/Resources/ApplicationResource.php @@ -51,11 +51,17 @@ class ApplicationResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Forms and Surveys'; + protected static ?string $navigationGroup = 'Premium Features'; - protected static ?int $navigationSort = 1; + protected static ?int $navigationSort = 50; - protected static ?string $navigationLabel = 'Manage Admissions'; + protected static ?string $navigationLabel = 'Online Admissions'; + + protected static ?string $breadcrumb = 'Online Admissions'; + + protected static ?string $modelLabel = 'Application'; + + protected static ?string $recordTitleAttribute = 'name'; public static function getEloquentQuery(): Builder { diff --git a/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/ListApplications.php b/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/ListApplications.php index 7b81e4a053..777581b959 100644 --- a/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/ListApplications.php +++ b/app-modules/application/src/Filament/Resources/ApplicationResource/Pages/ListApplications.php @@ -50,6 +50,8 @@ class ListApplications extends ListRecords { + protected ?string $heading = 'Online Admissions'; + protected static string $resource = ApplicationResource::class; public function table(Table $table): Table diff --git a/app-modules/form/src/Filament/Resources/FormResource.php b/app-modules/form/src/Filament/Resources/FormResource.php index e94bda0829..1a7c462d18 100644 --- a/app-modules/form/src/Filament/Resources/FormResource.php +++ b/app-modules/form/src/Filament/Resources/FormResource.php @@ -51,11 +51,17 @@ class FormResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Forms and Surveys'; + protected static ?string $navigationGroup = 'Premium Features'; - protected static ?int $navigationSort = 2; + protected static ?int $navigationSort = 60; - protected static ?string $navigationLabel = 'Manage Forms'; + protected static ?string $navigationLabel = 'Online Forms'; + + protected static ?string $breadcrumb = 'Online Forms'; + + protected static ?string $modelLabel = 'Form'; + + protected static ?string $recordTitleAttribute = 'name'; public static function getEloquentQuery(): Builder { diff --git a/app-modules/form/src/Filament/Resources/FormResource/Pages/ListForms.php b/app-modules/form/src/Filament/Resources/FormResource/Pages/ListForms.php index 83985b9b6b..0aaa6719bc 100644 --- a/app-modules/form/src/Filament/Resources/FormResource/Pages/ListForms.php +++ b/app-modules/form/src/Filament/Resources/FormResource/Pages/ListForms.php @@ -50,6 +50,8 @@ class ListForms extends ListRecords { + protected ?string $heading = 'Online Forms'; + protected static string $resource = FormResource::class; public function table(Table $table): Table @@ -59,8 +61,6 @@ public function table(Table $table): Table IdColumn::make(), TextColumn::make('name'), ]) - ->filters([ - ]) ->actions([ Action::make('Respond') ->url(fn (Form $form) => route('forms.show', ['form' => $form])) diff --git a/app-modules/in-app-communication/src/Filament/Pages/UserChat.php b/app-modules/in-app-communication/src/Filament/Pages/UserChat.php index fc5322ad29..4ce8db1a6e 100644 --- a/app-modules/in-app-communication/src/Filament/Pages/UserChat.php +++ b/app-modules/in-app-communication/src/Filament/Pages/UserChat.php @@ -72,9 +72,9 @@ class UserChat extends Page implements HasForms, HasActions public ?string $selectedConversation = null; - protected static ?string $navigationGroup = 'Engagement Features'; + protected static ?string $navigationGroup = 'Premium Features'; - protected static ?int $navigationSort = 2; + protected static ?int $navigationSort = 10; protected static ?string $navigationIcon = 'heroicon-o-chat-bubble-oval-left-ellipsis'; diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetResource.php b/app-modules/inventory-management/src/Filament/Resources/AssetResource.php index 9469f8fb81..d5337bb3b3 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetResource.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetResource.php @@ -53,6 +53,7 @@ use AdvisingApp\InventoryManagement\Filament\Resources\AssetResource\Pages\CreateAsset; use AdvisingApp\InventoryManagement\Filament\Resources\AssetResource\Pages\ManageAssetMaintenanceActivity; +// TODO: Can delete this and all underlying pages once we fork class AssetResource extends Resource { protected static ?string $model = Asset::class; @@ -67,6 +68,8 @@ class AssetResource extends Resource protected static ?string $breadcrumb = 'Asset Management'; + protected static bool $shouldRegisterNavigation = false; + public function getTitle(): string | Htmlable { return 'Manage Assets'; diff --git a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource.php b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource.php index 3530b8bcb6..7b208bcbb8 100644 --- a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource.php +++ b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource.php @@ -49,22 +49,20 @@ class KnowledgeBaseItemResource extends Resource { protected static ?string $model = KnowledgeBaseItem::class; - protected static ?string $navigationLabel = 'Knowledge Base'; + protected static ?string $navigationLabel = 'Knowledge Management'; + + protected static ?string $modelLabel = 'knowledge base item'; + + protected static ?string $breadcrumb = 'Knowledge Management'; protected static ?string $navigationIcon = 'heroicon-o-book-open'; - protected static ?string $navigationGroup = 'Engagement Features'; + protected static ?string $navigationGroup = 'Premium Features'; - protected static ?int $navigationSort = 8; + protected static ?int $navigationSort = 20; protected static ?string $recordTitleAttribute = 'question'; - public static function getRelations(): array - { - return [ - ]; - } - public static function getGloballySearchableAttributes(): array { return ['question', 'solution']; diff --git a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource/Pages/ListKnowledgeBaseItems.php b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource/Pages/ListKnowledgeBaseItems.php index 31439626c8..3de3efe4e4 100644 --- a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource/Pages/ListKnowledgeBaseItems.php +++ b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseItemResource/Pages/ListKnowledgeBaseItems.php @@ -51,6 +51,8 @@ class ListKnowledgeBaseItems extends ListRecords { + protected ?string $heading = 'Knowledge Management'; + protected static string $resource = KnowledgeBaseItemResource::class; public function table(Table $table): Table diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource.php b/app-modules/meeting-center/src/Filament/Resources/EventResource.php index 7f258955d0..3ca9495a75 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource.php @@ -51,14 +51,17 @@ class EventResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Meeting Center'; + protected static ?string $navigationGroup = 'Premium Features'; - protected static ?int $navigationSort = 20; + protected static ?int $navigationSort = 40; - public static function getRelations(): array - { - return []; - } + protected static ?string $navigationLabel = 'Event Management'; + + protected static ?string $breadcrumb = 'Event Management'; + + protected static ?string $modelLabel = 'Event'; + + protected static ?string $recordTitleAttribute = 'title'; public static function getRecordSubNavigation(Page $page): array { diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php index 7e8a652fdf..5820775b7a 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/EditEvent.php @@ -49,6 +49,9 @@ class EditEvent extends EditRecord protected static string $resource = EventResource::class; + // TODO: Automatically set from Filament + protected static ?string $navigationLabel = 'Edit'; + public function form(Form $form): Form { return $form->schema($this->fields()); diff --git a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ListEvents.php b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ListEvents.php index 5b66aec1fc..8785e1b04f 100644 --- a/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ListEvents.php +++ b/app-modules/meeting-center/src/Filament/Resources/EventResource/Pages/ListEvents.php @@ -53,6 +53,8 @@ class ListEvents extends ListRecords { + protected ?string $heading = 'Event Management'; + protected static string $resource = EventResource::class; protected static string $view = 'meeting-center::filament.pages.list-events'; diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource.php index 3ff6e9f438..8cd9130fc8 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource.php @@ -54,9 +54,15 @@ class ServiceRequestResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-briefcase'; - protected static ?string $navigationGroup = 'Service Management'; + protected static ?string $navigationGroup = 'Premium Features'; - protected static ?int $navigationSort = 10; + protected static ?int $navigationSort = 30; + + protected static ?string $navigationLabel = 'Service Management'; + + protected static ?string $modelLabel = 'Service Request'; + + protected static ?string $breadcrumb = 'Service Management'; public static function getRecordSubNavigation(Page $page): array { diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/ListServiceRequests.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/ListServiceRequests.php index d794f82cf6..bc0c0cff71 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/ListServiceRequests.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/ListServiceRequests.php @@ -55,6 +55,8 @@ class ListServiceRequests extends ListRecords { + protected ?string $heading = 'Service Management'; + protected static string $resource = ServiceRequestResource::class; public function table(Table $table): Table diff --git a/app-modules/survey/src/Filament/Resources/SurveyResource.php b/app-modules/survey/src/Filament/Resources/SurveyResource.php index 5cd6c5fc51..9fa349ce4f 100644 --- a/app-modules/survey/src/Filament/Resources/SurveyResource.php +++ b/app-modules/survey/src/Filament/Resources/SurveyResource.php @@ -51,11 +51,17 @@ class SurveyResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Forms and Surveys'; + protected static ?string $navigationGroup = 'Premium Features'; - protected static ?int $navigationSort = 2; + protected static ?int $navigationSort = 70; - protected static ?string $navigationLabel = 'Manage Surveys'; + protected static ?string $navigationLabel = 'Online Surveys'; + + protected static ?string $breadcrumb = 'Online Surveys'; + + protected static ?string $modelLabel = 'Survey'; + + protected static ?string $recordTitleAttribute = 'name'; public static function getEloquentQuery(): Builder { diff --git a/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/ListSurveys.php b/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/ListSurveys.php index 94a3edd711..81c13682d1 100644 --- a/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/ListSurveys.php +++ b/app-modules/survey/src/Filament/Resources/SurveyResource/Pages/ListSurveys.php @@ -50,6 +50,8 @@ class ListSurveys extends ListRecords { + protected ?string $heading = 'Online Surveys'; + protected static string $resource = SurveyResource::class; public function table(Table $table): Table diff --git a/app/Filament/Pages/ChangeManagement.php b/app/Filament/Pages/ChangeManagement.php deleted file mode 100644 index 38e19c63e9..0000000000 --- a/app/Filament/Pages/ChangeManagement.php +++ /dev/null @@ -1,50 +0,0 @@ - - - Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. - - Advising App™ is licensed under the Elastic License 2.0. For more details, - see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. - - Notice: - - - You may not provide the software to third parties as a hosted or managed - service, where the service provides users with access to any substantial set of - the features or functionality of the software. - - You may not move, change, disable, or circumvent the license key functionality - in the software, and you may not remove or obscure any functionality in the - software that is protected by the license key. - - You may not alter, remove, or obscure any licensing, copyright, or other notices - of the licensor in the software. Any use of the licensor’s trademarks is subject - to applicable law. - - Canyon GBS LLC respects the intellectual property rights of others and expects the - same in return. Canyon GBS™ and Advising App™ are registered trademarks of - Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks - vigorously. - - The software solution, including services, infrastructure, and code, is offered as a - Software as a Service (SaaS) by Canyon GBS LLC. - - Use of this software implies agreement to the license terms and conditions as stated - in the Elastic License 2.0. - - For more information or inquiries please visit our website at - https://www.canyongbs.com or contact us via email at legal@canyongbs.com. - - -*/ - -namespace App\Filament\Pages; - -use Filament\Pages\Page; - -class ChangeManagement extends Page -{ - protected static ?string $navigationIcon = 'heroicon-o-document-text'; - - protected static ?string $navigationGroup = 'Service Management'; - - protected static ?int $navigationSort = 20; - - protected static string $view = 'filament.pages.coming-soon'; -} diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 81fde42283..27bdf9c642 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -124,11 +124,7 @@ public function panel(Panel $panel): Panel NavigationGroup::make() ->label('Engagement Features'), NavigationGroup::make() - ->label('Meeting Center'), - NavigationGroup::make() - ->label('Mass Engagement'), - NavigationGroup::make() - ->label('Forms and Surveys'), + ->label('Premium Features'), NavigationGroup::make() ->label('Reporting'), NavigationGroup::make() From 8faa9773c4ca408d274271e548d4e6f961c1598f Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 16:50:11 -0500 Subject: [PATCH 146/152] Reporting Signed-off-by: Kevin Ullyott --- .../AssistantChatMessageLogResource.php | 12 ++-- .../src/Filament/Resources/AuditResource.php | 12 ++-- app/Filament/Pages/ProductHealth.php | 8 +-- app/Filament/Pages/Reports.php | 2 + app/Filament/Pages/UsageAuditing.php | 71 +++++++++++++++++++ 5 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 app/Filament/Pages/UsageAuditing.php diff --git a/app-modules/assistant/src/Filament/Resources/AssistantChatMessageLogResource.php b/app-modules/assistant/src/Filament/Resources/AssistantChatMessageLogResource.php index fbf30660fd..d8c4b67d56 100644 --- a/app-modules/assistant/src/Filament/Resources/AssistantChatMessageLogResource.php +++ b/app-modules/assistant/src/Filament/Resources/AssistantChatMessageLogResource.php @@ -56,15 +56,17 @@ class AssistantChatMessageLogResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-chat-bubble-left-ellipsis'; - protected static ?string $navigationLabel = 'Personal Assistant Audit'; + protected static ?string $navigationLabel = 'Personal Assistant'; - protected static ?string $navigationGroup = 'Product Administration'; + protected static ?string $navigationParentItem = 'Usage Auditing'; - protected static ?int $navigationSort = 50; + protected static ?string $navigationGroup = 'Reporting'; - protected static ?string $modelLabel = 'Personal Assistant Audit'; + protected static ?int $navigationSort = 30; - protected static ?string $pluralLabel = 'Personal Assistant Audit'; + protected static ?string $modelLabel = 'Personal Assistant'; + + protected static ?string $pluralLabel = 'Personal Assistant'; public static function infolist(Infolist $infolist): Infolist { diff --git a/app-modules/audit/src/Filament/Resources/AuditResource.php b/app-modules/audit/src/Filament/Resources/AuditResource.php index 34350e2932..86e6c814bc 100644 --- a/app-modules/audit/src/Filament/Resources/AuditResource.php +++ b/app-modules/audit/src/Filament/Resources/AuditResource.php @@ -44,19 +44,15 @@ class AuditResource extends Resource { protected static ?string $model = Audit::class; - protected static ?string $navigationLabel = 'Record Auditing'; + protected static ?string $navigationLabel = 'Other Records'; protected static ?string $navigationIcon = 'heroicon-o-shield-check'; - protected static ?string $navigationGroup = 'Product Administration'; + protected static ?string $navigationParentItem = 'Usage Auditing'; - protected static ?int $navigationSort = 100; + protected static ?string $navigationGroup = 'Reporting'; - public static function getRelations(): array - { - return [ - ]; - } + protected static ?int $navigationSort = 40; public static function getPages(): array { diff --git a/app/Filament/Pages/ProductHealth.php b/app/Filament/Pages/ProductHealth.php index ff51bc25a4..a7a72b88d8 100644 --- a/app/Filament/Pages/ProductHealth.php +++ b/app/Filament/Pages/ProductHealth.php @@ -46,22 +46,22 @@ class ProductHealth extends HealthCheckResults { public static function getNavigationLabel(): string { - return 'Health Dashboard'; + return 'Product Health'; } public function getHeading(): string | Htmlable { - return 'Health Dashboard'; + return 'Product Health'; } public static function getNavigationGroup(): ?string { - return 'Product Administration'; + return 'Reporting'; } public static function getNavigationSort(): ?int { - return 90; + return 20; } public static function getNavigationBadge(): ?string diff --git a/app/Filament/Pages/Reports.php b/app/Filament/Pages/Reports.php index f18fa04744..b5798d3fee 100644 --- a/app/Filament/Pages/Reports.php +++ b/app/Filament/Pages/Reports.php @@ -47,4 +47,6 @@ class Reports extends Page protected static ?int $navigationSort = 10; protected static string $view = 'filament.pages.coming-soon'; + + protected static ?string $title = 'Report Center'; } diff --git a/app/Filament/Pages/UsageAuditing.php b/app/Filament/Pages/UsageAuditing.php new file mode 100644 index 0000000000..63ad516481 --- /dev/null +++ b/app/Filament/Pages/UsageAuditing.php @@ -0,0 +1,71 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use AdvisingApp\Audit\Filament\Resources\AuditResource; +use AdvisingApp\Assistant\Filament\Resources\AssistantChatMessageLogResource; + +class UsageAuditing extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Reporting'; + + protected static ?int $navigationSort = 30; + + protected static ?string $title = 'Usage Auditing'; + + protected array $children = [ + AssistantChatMessageLogResource::class, + AuditResource::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + ray($child); + ray($child::shouldRegisterNavigation()); + + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} From 625fe2514b29342d1d0d4ea32319b59669948aff Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 17:29:19 -0500 Subject: [PATCH 147/152] Integrations Signed-off-by: Kevin Ullyott --- .../Filament/Pages/ManageAuditSettings.php | 8 +- .../Filament/Resources/PermissionResource.php | 2 +- .../Filament/Resources/RoleGroupResource.php | 2 +- .../src/Filament/Resources/RoleResource.php | 2 +- .../Filament/Resources/DivisionResource.php | 2 +- .../Filament/Pages/ManagePortalSettings.php | 8 +- .../src/Filament/Resources/TeamResource.php | 2 +- .../ManageBrandConfigurationSettings.php | 8 +- .../Resources/InboundWebhookResource.php | 4 +- app/Filament/Pages/EmailConfiguration.php | 6 +- app/Filament/Pages/GlobalSettings.php | 74 +++++++++++++++++++ app/Filament/Pages/ManageLicenseSettings.php | 4 +- ...figuration.php => ProductIntegrations.php} | 24 ++++-- app/Filament/Pages/UsageAuditing.php | 3 - app/Filament/Resources/SystemUserResource.php | 8 +- app/Filament/Resources/UserResource.php | 8 +- .../UserResource/Pages/ListUsers.php | 2 + 17 files changed, 136 insertions(+), 31 deletions(-) create mode 100644 app/Filament/Pages/GlobalSettings.php rename app/Filament/Pages/{SLAConfiguration.php => ProductIntegrations.php} (76%) diff --git a/app-modules/audit/src/Filament/Pages/ManageAuditSettings.php b/app-modules/audit/src/Filament/Pages/ManageAuditSettings.php index cf49d180ca..8b34cc1f6b 100644 --- a/app-modules/audit/src/Filament/Pages/ManageAuditSettings.php +++ b/app-modules/audit/src/Filament/Pages/ManageAuditSettings.php @@ -48,15 +48,17 @@ class ManageAuditSettings extends SettingsPage { protected static ?string $navigationIcon = 'heroicon-o-cog-6-tooth'; - protected static ?string $navigationLabel = 'Audit Configuration'; + protected static ?string $navigationLabel = 'Auditing'; protected static ?string $navigationGroup = 'Product Administration'; - protected static ?int $navigationSort = 30; + protected static ?string $navigationParentItem = 'Global Settings'; + + protected static ?int $navigationSort = 20; protected static string $settings = AuditSettings::class; - protected static ?string $title = 'Audit Configuration'; + protected static ?string $title = 'Auditing'; public static function shouldRegisterNavigation(): bool { diff --git a/app-modules/authorization/src/Filament/Resources/PermissionResource.php b/app-modules/authorization/src/Filament/Resources/PermissionResource.php index dffb0a190d..4c12bfe58d 100644 --- a/app-modules/authorization/src/Filament/Resources/PermissionResource.php +++ b/app-modules/authorization/src/Filament/Resources/PermissionResource.php @@ -56,7 +56,7 @@ class PermissionResource extends Resource protected static ?string $navigationGroup = 'Users and Permissions'; - protected static ?int $navigationSort = 6; + protected static ?int $navigationSort = 70; public static function form(Form $form): Form { diff --git a/app-modules/authorization/src/Filament/Resources/RoleGroupResource.php b/app-modules/authorization/src/Filament/Resources/RoleGroupResource.php index 78a42c8fd3..974f6cc72e 100644 --- a/app-modules/authorization/src/Filament/Resources/RoleGroupResource.php +++ b/app-modules/authorization/src/Filament/Resources/RoleGroupResource.php @@ -58,7 +58,7 @@ class RoleGroupResource extends Resource protected static ?string $navigationGroup = 'Users and Permissions'; - protected static ?int $navigationSort = 4; + protected static ?int $navigationSort = 50; public static function getRelations(): array { diff --git a/app-modules/authorization/src/Filament/Resources/RoleResource.php b/app-modules/authorization/src/Filament/Resources/RoleResource.php index 8d2e04c085..f22af54a49 100644 --- a/app-modules/authorization/src/Filament/Resources/RoleResource.php +++ b/app-modules/authorization/src/Filament/Resources/RoleResource.php @@ -59,7 +59,7 @@ class RoleResource extends Resource protected static ?string $navigationGroup = 'Users and Permissions'; - protected static ?int $navigationSort = 5; + protected static ?int $navigationSort = 60; public static function form(Form $form): Form { diff --git a/app-modules/division/src/Filament/Resources/DivisionResource.php b/app-modules/division/src/Filament/Resources/DivisionResource.php index 8b59ece66c..69bddff7c8 100644 --- a/app-modules/division/src/Filament/Resources/DivisionResource.php +++ b/app-modules/division/src/Filament/Resources/DivisionResource.php @@ -52,7 +52,7 @@ class DivisionResource extends Resource protected static ?string $navigationGroup = 'Users and Permissions'; - protected static ?int $navigationSort = 2; + protected static ?int $navigationSort = 10; public static function getRelations(): array { diff --git a/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php b/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php index ae234b0eab..d6283ac2fe 100644 --- a/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php +++ b/app-modules/portal/src/Filament/Pages/ManagePortalSettings.php @@ -54,15 +54,17 @@ class ManagePortalSettings extends SettingsPage { protected static ?string $navigationIcon = 'heroicon-o-cog-6-tooth'; - protected static ?string $navigationLabel = 'Portal Settings'; + protected static ?string $navigationLabel = 'Portals'; protected static ?string $navigationGroup = 'Product Administration'; - protected static ?int $navigationSort = 120; + protected static ?string $navigationParentItem = 'Global Settings'; + + protected static ?int $navigationSort = 60; protected static string $settings = PortalSettings::class; - protected static ?string $title = 'Portal Settings'; + protected static ?string $title = 'Portals'; public static function shouldRegisterNavigation(): bool { diff --git a/app-modules/team/src/Filament/Resources/TeamResource.php b/app-modules/team/src/Filament/Resources/TeamResource.php index 02d9ca43f2..216e282b64 100644 --- a/app-modules/team/src/Filament/Resources/TeamResource.php +++ b/app-modules/team/src/Filament/Resources/TeamResource.php @@ -52,7 +52,7 @@ class TeamResource extends Resource protected static ?string $navigationGroup = 'Users and Permissions'; - protected static ?int $navigationSort = 3; + protected static ?int $navigationSort = 20; public static function getRelations(): array { diff --git a/app-modules/theme/src/Filament/Pages/ManageBrandConfigurationSettings.php b/app-modules/theme/src/Filament/Pages/ManageBrandConfigurationSettings.php index 1e18a54d79..43fa51e379 100644 --- a/app-modules/theme/src/Filament/Pages/ManageBrandConfigurationSettings.php +++ b/app-modules/theme/src/Filament/Pages/ManageBrandConfigurationSettings.php @@ -51,15 +51,17 @@ class ManageBrandConfigurationSettings extends SettingsPage { protected static ?string $navigationIcon = 'heroicon-o-paint-brush'; - protected static ?string $navigationLabel = 'Brand Configuration'; + protected static ?string $navigationLabel = 'Branding'; protected static ?string $navigationGroup = 'Product Administration'; - protected static ?int $navigationSort = 40; + protected static ?string $navigationParentItem = 'Global Settings'; + + protected static ?int $navigationSort = 30; protected static string $settings = ThemeSettings::class; - protected static ?string $title = 'Brand Configuration'; + protected static ?string $title = 'Branding'; public static function shouldRegisterNavigation(): bool { diff --git a/app-modules/webhook/src/Filament/Resources/InboundWebhookResource.php b/app-modules/webhook/src/Filament/Resources/InboundWebhookResource.php index 3cc528ded4..0de5a6b4b3 100644 --- a/app-modules/webhook/src/Filament/Resources/InboundWebhookResource.php +++ b/app-modules/webhook/src/Filament/Resources/InboundWebhookResource.php @@ -49,7 +49,9 @@ class InboundWebhookResource extends Resource protected static ?string $navigationGroup = 'Product Administration'; - protected static ?int $navigationSort = 70; + protected static ?string $navigationParentItem = 'Global Settings'; + + protected static ?int $navigationSort = 40; public static function getPages(): array { diff --git a/app/Filament/Pages/EmailConfiguration.php b/app/Filament/Pages/EmailConfiguration.php index 73aa66cd49..4e62453cd5 100644 --- a/app/Filament/Pages/EmailConfiguration.php +++ b/app/Filament/Pages/EmailConfiguration.php @@ -51,7 +51,11 @@ class EmailConfiguration extends Page protected static ?string $navigationGroup = 'Product Administration'; - protected static ?int $navigationSort = 110; + protected static ?string $navigationParentItem = 'Global Settings'; + + protected static ?int $navigationSort = 50; + + protected static ?string $title = 'Communication'; protected static string $view = 'filament.pages.email-configuration'; diff --git a/app/Filament/Pages/GlobalSettings.php b/app/Filament/Pages/GlobalSettings.php new file mode 100644 index 0000000000..da8c482733 --- /dev/null +++ b/app/Filament/Pages/GlobalSettings.php @@ -0,0 +1,74 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use AdvisingApp\Audit\Filament\Pages\ManageAuditSettings; +use AdvisingApp\Portal\Filament\Pages\ManagePortalSettings; +use AdvisingApp\Webhook\Filament\Resources\InboundWebhookResource; +use AdvisingApp\Theme\Filament\Pages\ManageBrandConfigurationSettings; + +class GlobalSettings extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?int $navigationSort = 1; + + protected static ?string $title = 'Global Settings'; + + protected array $children = [ + ManageLicenseSettings::class, + ManageAuditSettings::class, + ManageBrandConfigurationSettings::class, + InboundWebhookResource::class, + EmailConfiguration::class, + ManagePortalSettings::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} diff --git a/app/Filament/Pages/ManageLicenseSettings.php b/app/Filament/Pages/ManageLicenseSettings.php index 60ac1625a5..949b319c7b 100644 --- a/app/Filament/Pages/ManageLicenseSettings.php +++ b/app/Filament/Pages/ManageLicenseSettings.php @@ -49,10 +49,12 @@ class ManageLicenseSettings extends SettingsPage { protected static ?string $navigationIcon = 'heroicon-o-key'; - protected static ?string $navigationLabel = 'Subscription Management'; + protected static ?string $navigationLabel = 'Subscription'; protected static ?string $navigationGroup = 'Product Administration'; + protected static ?string $navigationParentItem = 'Global Settings'; + protected static ?int $navigationSort = 10; protected static string $settings = LicenseSettings::class; diff --git a/app/Filament/Pages/SLAConfiguration.php b/app/Filament/Pages/ProductIntegrations.php similarity index 76% rename from app/Filament/Pages/SLAConfiguration.php rename to app/Filament/Pages/ProductIntegrations.php index e4f75d6dd5..ba470a7764 100644 --- a/app/Filament/Pages/SLAConfiguration.php +++ b/app/Filament/Pages/ProductIntegrations.php @@ -37,18 +37,30 @@ namespace App\Filament\Pages; use Filament\Pages\Page; +use AdvisingApp\IntegrationGoogleAnalytics\Filament\Pages\ManageGoogleAnalyticsSettings; -class SLAConfiguration extends Page +class ProductIntegrations extends Page { protected static ?string $navigationIcon = 'heroicon-o-document-text'; - protected static ?string $navigationLabel = 'SLA Configuration'; - protected static ?string $navigationGroup = 'Product Administration'; - protected static ?int $navigationSort = 120; + protected static ?int $navigationSort = 2; + + protected static ?string $title = 'Product Integrations'; + + protected array $children = [ + ManageGoogleAnalyticsSettings::class, + ]; - protected ?string $heading = 'SLA Configuration'; + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } - protected static string $view = 'filament.pages.coming-soon'; + abort(404); + } } diff --git a/app/Filament/Pages/UsageAuditing.php b/app/Filament/Pages/UsageAuditing.php index 63ad516481..131f8ddcec 100644 --- a/app/Filament/Pages/UsageAuditing.php +++ b/app/Filament/Pages/UsageAuditing.php @@ -58,9 +58,6 @@ class UsageAuditing extends Page public function mount() { foreach ($this->children as $child) { - ray($child); - ray($child::shouldRegisterNavigation()); - if ($child::shouldRegisterNavigation()) { return redirect($child::getUrl()); } diff --git a/app/Filament/Resources/SystemUserResource.php b/app/Filament/Resources/SystemUserResource.php index 58061c333f..9e62c3dfe3 100644 --- a/app/Filament/Resources/SystemUserResource.php +++ b/app/Filament/Resources/SystemUserResource.php @@ -51,13 +51,13 @@ class SystemUserResource extends Resource protected static ?string $navigationGroup = 'Users and Permissions'; - protected static ?string $navigationLabel = 'Programmatic (API) Users'; + protected static ?string $navigationLabel = 'Programmatic Users'; - protected static ?string $modelLabel = 'Programmatic (API) User'; + protected static ?string $modelLabel = 'Programmatic User'; - protected static ?string $breadcrumb = 'Programmatic (API) Users'; + protected static ?string $breadcrumb = 'Programmatic Users'; - protected static ?int $navigationSort = 7; + protected static ?int $navigationSort = 40; public static function getRelations(): array { diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php index e799e88286..90a6ee5835 100644 --- a/app/Filament/Resources/UserResource.php +++ b/app/Filament/Resources/UserResource.php @@ -67,7 +67,13 @@ class UserResource extends Resource protected static ?string $navigationGroup = 'Users and Permissions'; - protected static ?int $navigationSort = 1; + protected static ?int $navigationSort = 30; + + protected static ?string $navigationLabel = 'Product Users'; + + protected static ?string $breadcrumb = 'Product Users'; + + protected static ?string $modelLabel = 'User'; public static function form(Form $form): Form { diff --git a/app/Filament/Resources/UserResource/Pages/ListUsers.php b/app/Filament/Resources/UserResource/Pages/ListUsers.php index 3edd59677c..63ddeccc44 100644 --- a/app/Filament/Resources/UserResource/Pages/ListUsers.php +++ b/app/Filament/Resources/UserResource/Pages/ListUsers.php @@ -45,6 +45,8 @@ class ListUsers extends ListRecords { protected static string $resource = UserResource::class; + protected ?string $heading = 'Product Users'; + public function getSubheading(): string | Htmlable | null { // TODO: Either remove or change to show all possible seats From 1063bed7b4c4cd503727e27111173fd76b68ef73 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 19:22:14 -0500 Subject: [PATCH 148/152] Product Integrations Signed-off-by: Kevin Ullyott --- .../src/Filament/Pages/ManageAmazonSesSettings.php | 4 +++- .../src/Filament/Pages/ManageGoogleAnalyticsSettings.php | 4 +++- .../src/Filament/Pages/ManageGoogleRecaptchaSettings.php | 6 ++++-- .../src/Filament/Pages/ManageMicrosoftClaritySettings.php | 4 +++- .../src/Filament/Pages/ManageTwilioSettings.php | 4 +++- app/Filament/Pages/ProductIntegrations.php | 6 ++++++ 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app-modules/integration-aws-ses-event-handling/src/Filament/Pages/ManageAmazonSesSettings.php b/app-modules/integration-aws-ses-event-handling/src/Filament/Pages/ManageAmazonSesSettings.php index 678110d074..540852448a 100644 --- a/app-modules/integration-aws-ses-event-handling/src/Filament/Pages/ManageAmazonSesSettings.php +++ b/app-modules/integration-aws-ses-event-handling/src/Filament/Pages/ManageAmazonSesSettings.php @@ -53,7 +53,9 @@ class ManageAmazonSesSettings extends SettingsPage protected static ?string $navigationLabel = 'Amazon SES'; - protected static ?string $navigationGroup = 'Integrations'; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationParentItem = 'Product Integrations'; protected static ?int $navigationSort = 50; diff --git a/app-modules/integration-google-analytics/src/Filament/Pages/ManageGoogleAnalyticsSettings.php b/app-modules/integration-google-analytics/src/Filament/Pages/ManageGoogleAnalyticsSettings.php index b99112539c..1298aee632 100644 --- a/app-modules/integration-google-analytics/src/Filament/Pages/ManageGoogleAnalyticsSettings.php +++ b/app-modules/integration-google-analytics/src/Filament/Pages/ManageGoogleAnalyticsSettings.php @@ -54,7 +54,9 @@ class ManageGoogleAnalyticsSettings extends SettingsPage protected static ?string $navigationLabel = 'Google Analytics'; - protected static ?string $navigationGroup = 'Integrations'; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationParentItem = 'Product Integrations'; protected static ?int $navigationSort = 10; diff --git a/app-modules/integration-google-recaptcha/src/Filament/Pages/ManageGoogleRecaptchaSettings.php b/app-modules/integration-google-recaptcha/src/Filament/Pages/ManageGoogleRecaptchaSettings.php index 57804b926e..a5965d4e0e 100644 --- a/app-modules/integration-google-recaptcha/src/Filament/Pages/ManageGoogleRecaptchaSettings.php +++ b/app-modules/integration-google-recaptcha/src/Filament/Pages/ManageGoogleRecaptchaSettings.php @@ -52,9 +52,11 @@ class ManageGoogleRecaptchaSettings extends SettingsPage protected static ?string $title = 'Google reCAPTCHA Settings'; - protected static ?string $navigationLabel = 'Google reCAPTCHA'; + protected static ?string $navigationLabel = 'Google ReCAPTCHA'; - protected static ?string $navigationGroup = 'Integrations'; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationParentItem = 'Product Integrations'; protected static ?int $navigationSort = 20; diff --git a/app-modules/integration-microsoft-clarity/src/Filament/Pages/ManageMicrosoftClaritySettings.php b/app-modules/integration-microsoft-clarity/src/Filament/Pages/ManageMicrosoftClaritySettings.php index e9b00aea42..0b593e4234 100644 --- a/app-modules/integration-microsoft-clarity/src/Filament/Pages/ManageMicrosoftClaritySettings.php +++ b/app-modules/integration-microsoft-clarity/src/Filament/Pages/ManageMicrosoftClaritySettings.php @@ -54,7 +54,9 @@ class ManageMicrosoftClaritySettings extends SettingsPage protected static ?string $navigationLabel = 'Microsoft Clarity'; - protected static ?string $navigationGroup = 'Integrations'; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationParentItem = 'Product Integrations'; protected static ?int $navigationSort = 30; diff --git a/app-modules/integration-twilio/src/Filament/Pages/ManageTwilioSettings.php b/app-modules/integration-twilio/src/Filament/Pages/ManageTwilioSettings.php index ddbf257a29..7a7b79680d 100644 --- a/app-modules/integration-twilio/src/Filament/Pages/ManageTwilioSettings.php +++ b/app-modules/integration-twilio/src/Filament/Pages/ManageTwilioSettings.php @@ -55,7 +55,9 @@ class ManageTwilioSettings extends SettingsPage protected static ?string $navigationLabel = 'Twilio'; - protected static ?string $navigationGroup = 'Integrations'; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationParentItem = 'Product Integrations'; protected static ?int $navigationSort = 40; diff --git a/app/Filament/Pages/ProductIntegrations.php b/app/Filament/Pages/ProductIntegrations.php index ba470a7764..6c4dbb3bfe 100644 --- a/app/Filament/Pages/ProductIntegrations.php +++ b/app/Filament/Pages/ProductIntegrations.php @@ -37,7 +37,10 @@ namespace App\Filament\Pages; use Filament\Pages\Page; +use AdvisingApp\IntegrationTwilio\Filament\Pages\ManageTwilioSettings; use AdvisingApp\IntegrationGoogleAnalytics\Filament\Pages\ManageGoogleAnalyticsSettings; +use AdvisingApp\IntegrationGoogleRecaptcha\Filament\Pages\ManageGoogleRecaptchaSettings; +use AdvisingApp\IntegrationMicrosoftClarity\Filament\Pages\ManageMicrosoftClaritySettings; class ProductIntegrations extends Page { @@ -51,6 +54,9 @@ class ProductIntegrations extends Page protected array $children = [ ManageGoogleAnalyticsSettings::class, + ManageGoogleRecaptchaSettings::class, + ManageMicrosoftClaritySettings::class, + ManageTwilioSettings::class, ]; public function mount() From 5bb92b20252e8203473f5533ba1eca687dcfae89 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 19:57:58 -0500 Subject: [PATCH 149/152] Last product settings Signed-off-by: Kevin Ullyott --- .../ApplicationSubmissionStateResource.php | 8 +- .../Pages/ListApplicationSubmissionStates.php | 2 +- .../Filament/Pages/AssistantConfiguration.php | 6 +- .../src/Filament/Pages/ManageAiSettings.php | 2 + .../Resources/InteractionCampaignResource.php | 14 ++-- .../Resources/InteractionDriverResource.php | 14 ++-- .../Resources/InteractionOutcomeResource.php | 14 ++-- .../Resources/InteractionRelationResource.php | 14 ++-- .../Resources/InteractionStatusResource.php | 14 ++-- .../Resources/InteractionTypeResource.php | 14 ++-- .../Resources/AssetLocationResource.php | 8 +- .../Resources/AssetStatusResource.php | 8 +- .../Filament/Resources/AssetTypeResource.php | 8 +- .../KnowledgeBaseCategoryResource.php | 25 +++--- .../KnowledgeBaseQualityResource.php | 25 +++--- .../Resources/KnowledgeBaseStatusResource.php | 25 +++--- .../Resources/ProspectSourceResource.php | 8 +- .../Resources/ProspectStatusResource.php | 8 +- .../ServiceRequestPriorityResource.php | 12 ++- .../ServiceRequestStatusResource.php | 12 ++- .../Resources/ServiceRequestTypeResource.php | 12 ++- app/Filament/Pages/ArtificialIntelligence.php | 66 ++++++++++++++++ app/Filament/Pages/AssetManagement.php | 72 +++++++++++++++++ app/Filament/Pages/InteractionManagement.php | 78 +++++++++++++++++++ app/Filament/Pages/KnowledgeManagement.php | 72 +++++++++++++++++ app/Filament/Pages/OnlineAdmissions.php | 68 ++++++++++++++++ app/Filament/Pages/ProductIntegrations.php | 2 + app/Filament/Pages/ProfileManagement.php | 68 ++++++++++++++++ app/Filament/Pages/RecruitmentCrm.php | 70 +++++++++++++++++ app/Filament/Pages/ServiceManagement.php | 72 +++++++++++++++++ app/Filament/Resources/PronounsResource.php | 34 ++++---- 31 files changed, 723 insertions(+), 132 deletions(-) create mode 100644 app/Filament/Pages/ArtificialIntelligence.php create mode 100644 app/Filament/Pages/AssetManagement.php create mode 100644 app/Filament/Pages/InteractionManagement.php create mode 100644 app/Filament/Pages/KnowledgeManagement.php create mode 100644 app/Filament/Pages/OnlineAdmissions.php create mode 100644 app/Filament/Pages/ProfileManagement.php create mode 100644 app/Filament/Pages/RecruitmentCrm.php create mode 100644 app/Filament/Pages/ServiceManagement.php diff --git a/app-modules/application/src/Filament/Resources/ApplicationSubmissionStateResource.php b/app-modules/application/src/Filament/Resources/ApplicationSubmissionStateResource.php index 914f555d27..2a0563ac3b 100644 --- a/app-modules/application/src/Filament/Resources/ApplicationSubmissionStateResource.php +++ b/app-modules/application/src/Filament/Resources/ApplicationSubmissionStateResource.php @@ -49,9 +49,13 @@ class ApplicationSubmissionStateResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Online Admissions'; - protected static ?int $navigationSort = 18; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Application States'; + + protected static ?int $navigationSort = 1; public static function getPages(): array { diff --git a/app-modules/application/src/Filament/Resources/ApplicationSubmissionStateResource/Pages/ListApplicationSubmissionStates.php b/app-modules/application/src/Filament/Resources/ApplicationSubmissionStateResource/Pages/ListApplicationSubmissionStates.php index 906c6745cc..3964cc4a11 100644 --- a/app-modules/application/src/Filament/Resources/ApplicationSubmissionStateResource/Pages/ListApplicationSubmissionStates.php +++ b/app-modules/application/src/Filament/Resources/ApplicationSubmissionStateResource/Pages/ListApplicationSubmissionStates.php @@ -71,7 +71,7 @@ public function table(Table $table): Table ->color(fn (ApplicationSubmissionState $applicationState) => $applicationState->color->value), TextColumn::make('applications_count') ->label('# of Applications') - ->counts('applications') + ->counts('submissions') ->sortable(), ]) ->filters([ diff --git a/app-modules/assistant/src/Filament/Pages/AssistantConfiguration.php b/app-modules/assistant/src/Filament/Pages/AssistantConfiguration.php index f200beefac..0eb6c9e1a3 100644 --- a/app-modules/assistant/src/Filament/Pages/AssistantConfiguration.php +++ b/app-modules/assistant/src/Filament/Pages/AssistantConfiguration.php @@ -46,11 +46,11 @@ class AssistantConfiguration extends Page protected static ?string $navigationIcon = 'heroicon-o-shield-exclamation'; - protected static ?string $navigationLabel = 'Artificial Intelligence'; + protected static ?string $navigationParentItem = 'Product Integrations'; - protected static ?string $navigationGroup = 'Product Administration'; + protected static ?string $navigationLabel = 'AI Settings'; - protected static ?int $navigationSort = 20; + protected static ?int $navigationSort = 10; protected static ?string $modelLabel = 'Artificial Intelligence'; diff --git a/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php b/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php index 5297dc5be9..87eff8d6c1 100644 --- a/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php +++ b/app-modules/assistant/src/Filament/Pages/ManageAiSettings.php @@ -49,6 +49,8 @@ class ManageAiSettings extends SettingsPage protected static ?string $title = 'Manage AI Settings'; + protected static ?string $navigationGroup = 'Product Administration'; + // We don't want to register the navigation as we will be using the navigation item in a different page. public static function registerNavigationItems(): void {} diff --git a/app-modules/interaction/src/Filament/Resources/InteractionCampaignResource.php b/app-modules/interaction/src/Filament/Resources/InteractionCampaignResource.php index 82fb354787..883a2fb1ff 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionCampaignResource.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionCampaignResource.php @@ -50,9 +50,13 @@ class InteractionCampaignResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-megaphone'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Interaction Management'; - protected static ?int $navigationSort = 10; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Campaigns'; + + protected static ?int $navigationSort = 1; public static function form(Form $form): Form { @@ -66,12 +70,6 @@ public static function form(Form $form): Form ]); } - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/interaction/src/Filament/Resources/InteractionDriverResource.php b/app-modules/interaction/src/Filament/Resources/InteractionDriverResource.php index 6b4027dbb3..71bac3244b 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionDriverResource.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionDriverResource.php @@ -50,9 +50,13 @@ class InteractionDriverResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-cursor-arrow-ripple'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Interaction Management'; - protected static ?int $navigationSort = 11; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Drivers'; + + protected static ?int $navigationSort = 2; public static function form(Form $form): Form { @@ -66,12 +70,6 @@ public static function form(Form $form): Form ]); } - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/interaction/src/Filament/Resources/InteractionOutcomeResource.php b/app-modules/interaction/src/Filament/Resources/InteractionOutcomeResource.php index e9ce7081b9..3d784a8836 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionOutcomeResource.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionOutcomeResource.php @@ -50,9 +50,13 @@ class InteractionOutcomeResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-map'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Interaction Management'; - protected static ?int $navigationSort = 13; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Outcomes'; + + protected static ?int $navigationSort = 3; public static function form(Form $form): Form { @@ -66,12 +70,6 @@ public static function form(Form $form): Form ]); } - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/interaction/src/Filament/Resources/InteractionRelationResource.php b/app-modules/interaction/src/Filament/Resources/InteractionRelationResource.php index 5d9966202d..9bf6dc1e81 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionRelationResource.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionRelationResource.php @@ -50,9 +50,13 @@ class InteractionRelationResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-arrows-right-left'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Interaction Management'; - protected static ?int $navigationSort = 14; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Relations'; + + protected static ?int $navigationSort = 4; public static function form(Form $form): Form { @@ -66,12 +70,6 @@ public static function form(Form $form): Form ]); } - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/interaction/src/Filament/Resources/InteractionStatusResource.php b/app-modules/interaction/src/Filament/Resources/InteractionStatusResource.php index e5d3ff7262..757ef5a190 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionStatusResource.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionStatusResource.php @@ -52,9 +52,13 @@ class InteractionStatusResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-tag'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Interaction Management'; - protected static ?int $navigationSort = 15; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Statuses'; + + protected static ?int $navigationSort = 5; public static function form(Form $form): Form { @@ -75,12 +79,6 @@ public static function form(Form $form): Form ]); } - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/interaction/src/Filament/Resources/InteractionTypeResource.php b/app-modules/interaction/src/Filament/Resources/InteractionTypeResource.php index a8b78b4cb5..4bbf7fa4a8 100644 --- a/app-modules/interaction/src/Filament/Resources/InteractionTypeResource.php +++ b/app-modules/interaction/src/Filament/Resources/InteractionTypeResource.php @@ -50,9 +50,13 @@ class InteractionTypeResource extends Resource protected static ?string $navigationIcon = 'heroicon-m-rectangle-stack'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Interaction Management'; - protected static ?int $navigationSort = 16; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Types'; + + protected static ?int $navigationSort = 6; public static function form(Form $form): Form { @@ -66,12 +70,6 @@ public static function form(Form $form): Form ]); } - public static function getRelations(): array - { - return [ - ]; - } - public static function getPages(): array { return [ diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetLocationResource.php b/app-modules/inventory-management/src/Filament/Resources/AssetLocationResource.php index acfc816249..adc0a611a5 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetLocationResource.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetLocationResource.php @@ -50,7 +50,13 @@ class AssetLocationResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-map-pin'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Asset Management'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Locations'; + + protected static ?int $navigationSort = 1; public static function form(Form $form): Form { diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource.php b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource.php index db2a5b8c86..27fb478ec5 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetStatusResource.php @@ -50,7 +50,13 @@ class AssetStatusResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-tag'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Asset Management'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Statuses'; + + protected static ?int $navigationSort = 2; public static function form(Form $form): Form { diff --git a/app-modules/inventory-management/src/Filament/Resources/AssetTypeResource.php b/app-modules/inventory-management/src/Filament/Resources/AssetTypeResource.php index bb112d1ae2..e8f40207aa 100644 --- a/app-modules/inventory-management/src/Filament/Resources/AssetTypeResource.php +++ b/app-modules/inventory-management/src/Filament/Resources/AssetTypeResource.php @@ -50,7 +50,13 @@ class AssetTypeResource extends Resource protected static ?string $navigationIcon = 'heroicon-m-rectangle-stack'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Asset Management'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Types'; + + protected static ?int $navigationSort = 3; public static function form(Form $form): Form { diff --git a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseCategoryResource.php b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseCategoryResource.php index 8947613735..c49b5c77bf 100644 --- a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseCategoryResource.php +++ b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseCategoryResource.php @@ -38,7 +38,10 @@ use Filament\Resources\Resource; use AdvisingApp\KnowledgeBase\Models\KnowledgeBaseCategory; -use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseCategoryResource\Pages; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseCategoryResource\Pages\EditKnowledgeBaseCategory; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseCategoryResource\Pages\ViewKnowledgeBaseCategory; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseCategoryResource\Pages\CreateKnowledgeBaseCategory; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseCategoryResource\Pages\ListKnowledgeBaseCategories; class KnowledgeBaseCategoryResource extends Resource { @@ -46,23 +49,21 @@ class KnowledgeBaseCategoryResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Knowledge Management'; - protected static ?int $navigationSort = 7; + protected static ?string $navigationGroup = 'Product Administration'; - public static function getRelations(): array - { - return [ - ]; - } + protected static ?string $navigationLabel = 'Categories'; + + protected static ?int $navigationSort = 1; public static function getPages(): array { return [ - 'index' => Pages\ListKnowledgeBaseCategories::route('/'), - 'create' => Pages\CreateKnowledgeBaseCategory::route('/create'), - 'view' => Pages\ViewKnowledgeBaseCategory::route('/{record}'), - 'edit' => Pages\EditKnowledgeBaseCategory::route('/{record}/edit'), + 'index' => ListKnowledgeBaseCategories::route('/'), + 'create' => CreateKnowledgeBaseCategory::route('/create'), + 'view' => ViewKnowledgeBaseCategory::route('/{record}'), + 'edit' => EditKnowledgeBaseCategory::route('/{record}/edit'), ]; } } diff --git a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseQualityResource.php b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseQualityResource.php index 92050000e4..73d203d1b3 100644 --- a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseQualityResource.php +++ b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseQualityResource.php @@ -38,7 +38,10 @@ use Filament\Resources\Resource; use AdvisingApp\KnowledgeBase\Models\KnowledgeBaseQuality; -use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseQualityResource\Pages; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseQualityResource\Pages\EditKnowledgeBaseQuality; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseQualityResource\Pages\ViewKnowledgeBaseQuality; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseQualityResource\Pages\CreateKnowledgeBaseQuality; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseQualityResource\Pages\ListKnowledgeBaseQualities; class KnowledgeBaseQualityResource extends Resource { @@ -46,23 +49,21 @@ class KnowledgeBaseQualityResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Knowledge Management'; - protected static ?int $navigationSort = 8; + protected static ?string $navigationGroup = 'Product Administration'; - public static function getRelations(): array - { - return [ - ]; - } + protected static ?string $navigationLabel = 'Qualities'; + + protected static ?int $navigationSort = 2; public static function getPages(): array { return [ - 'index' => Pages\ListKnowledgeBaseQualities::route('/'), - 'create' => Pages\CreateKnowledgeBaseQuality::route('/create'), - 'view' => Pages\ViewKnowledgeBaseQuality::route('/{record}'), - 'edit' => Pages\EditKnowledgeBaseQuality::route('/{record}/edit'), + 'index' => ListKnowledgeBaseQualities::route('/'), + 'create' => CreateKnowledgeBaseQuality::route('/create'), + 'view' => ViewKnowledgeBaseQuality::route('/{record}'), + 'edit' => EditKnowledgeBaseQuality::route('/{record}/edit'), ]; } } diff --git a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseStatusResource.php b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseStatusResource.php index 3655b8f467..427d981b7e 100644 --- a/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseStatusResource.php +++ b/app-modules/knowledge-base/src/Filament/Resources/KnowledgeBaseStatusResource.php @@ -38,7 +38,10 @@ use Filament\Resources\Resource; use AdvisingApp\KnowledgeBase\Models\KnowledgeBaseStatus; -use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseStatusResource\Pages; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseStatusResource\Pages\EditKnowledgeBaseStatus; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseStatusResource\Pages\ViewKnowledgeBaseStatus; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseStatusResource\Pages\CreateKnowledgeBaseStatus; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseStatusResource\Pages\ListKnowledgeBaseStatuses; class KnowledgeBaseStatusResource extends Resource { @@ -46,23 +49,21 @@ class KnowledgeBaseStatusResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-tag'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Knowledge Management'; - protected static ?int $navigationSort = 9; + protected static ?string $navigationGroup = 'Product Administration'; - public static function getRelations(): array - { - return [ - ]; - } + protected static ?string $navigationLabel = 'Statuses'; + + protected static ?int $navigationSort = 3; public static function getPages(): array { return [ - 'index' => Pages\ListKnowledgeBaseStatuses::route('/'), - 'create' => Pages\CreateKnowledgeBaseStatus::route('/create'), - 'view' => Pages\ViewKnowledgeBaseStatus::route('/{record}'), - 'edit' => Pages\EditKnowledgeBaseStatus::route('/{record}/edit'), + 'index' => ListKnowledgeBaseStatuses::route('/'), + 'create' => CreateKnowledgeBaseStatus::route('/create'), + 'view' => ViewKnowledgeBaseStatus::route('/{record}'), + 'edit' => EditKnowledgeBaseStatus::route('/{record}/edit'), ]; } } diff --git a/app-modules/prospect/src/Filament/Resources/ProspectSourceResource.php b/app-modules/prospect/src/Filament/Resources/ProspectSourceResource.php index 27e6e177f7..ba7a550de9 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectSourceResource.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectSourceResource.php @@ -46,9 +46,13 @@ class ProspectSourceResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-viewfinder-circle'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Recruitment CRM'; - protected static ?int $navigationSort = 3; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Sources'; + + protected static ?int $navigationSort = 2; public static function getRelations(): array { diff --git a/app-modules/prospect/src/Filament/Resources/ProspectStatusResource.php b/app-modules/prospect/src/Filament/Resources/ProspectStatusResource.php index aee8070574..d1f1d02ba3 100644 --- a/app-modules/prospect/src/Filament/Resources/ProspectStatusResource.php +++ b/app-modules/prospect/src/Filament/Resources/ProspectStatusResource.php @@ -47,9 +47,13 @@ class ProspectStatusResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-tag'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Recruitment CRM'; - protected static ?int $navigationSort = 2; + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Statuses'; + + protected static ?int $navigationSort = 1; public static function form(Form $form): Form { diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestPriorityResource.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestPriorityResource.php index d871f8a241..e9d2c9f14a 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestPriorityResource.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestPriorityResource.php @@ -49,15 +49,13 @@ class ServiceRequestPriorityResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-arrows-up-down'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Service Management'; - protected static ?int $navigationSort = 4; + protected static ?string $navigationGroup = 'Product Administration'; - public static function getRelations(): array - { - return [ - ]; - } + protected static ?string $navigationLabel = 'Priorities'; + + protected static ?int $navigationSort = 1; public static function getPages(): array { diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestStatusResource.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestStatusResource.php index 6693a5b055..f6f03de6b9 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestStatusResource.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestStatusResource.php @@ -49,15 +49,13 @@ class ServiceRequestStatusResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-tag'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Service Management'; - protected static ?int $navigationSort = 5; + protected static ?string $navigationGroup = 'Product Administration'; - public static function getRelations(): array - { - return [ - ]; - } + protected static ?string $navigationLabel = 'Statuses'; + + protected static ?int $navigationSort = 2; public static function getPages(): array { diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestTypeResource.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestTypeResource.php index cbd7dad3c3..1074c10cc9 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestTypeResource.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestTypeResource.php @@ -49,15 +49,13 @@ class ServiceRequestTypeResource extends Resource protected static ?string $navigationIcon = 'heroicon-m-rectangle-stack'; - protected static ?string $navigationGroup = 'Product Settings'; + protected static ?string $navigationParentItem = 'Service Management'; - protected static ?int $navigationSort = 6; + protected static ?string $navigationGroup = 'Product Administration'; - public static function getRelations(): array - { - return [ - ]; - } + protected static ?string $navigationLabel = 'Types'; + + protected static ?int $navigationSort = 3; public static function getPages(): array { diff --git a/app/Filament/Pages/ArtificialIntelligence.php b/app/Filament/Pages/ArtificialIntelligence.php new file mode 100644 index 0000000000..295639fa25 --- /dev/null +++ b/app/Filament/Pages/ArtificialIntelligence.php @@ -0,0 +1,66 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use AdvisingApp\Assistant\Filament\Pages\AssistantConfiguration; + +class ArtificialIntelligence extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?int $navigationSort = 3; + + protected static ?string $title = 'Artificial Intelligence'; + + protected array $children = [ + AssistantConfiguration::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} diff --git a/app/Filament/Pages/AssetManagement.php b/app/Filament/Pages/AssetManagement.php new file mode 100644 index 0000000000..2e8b578682 --- /dev/null +++ b/app/Filament/Pages/AssetManagement.php @@ -0,0 +1,72 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use AdvisingApp\InventoryManagement\Filament\Resources\AssetTypeResource; +use AdvisingApp\InventoryManagement\Filament\Resources\AssetStatusResource; +use AdvisingApp\InventoryManagement\Filament\Resources\AssetLocationResource; + +class AssetManagement extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?int $navigationSort = 5; + + protected static ?string $title = 'Asset Management'; + + protected static ?string $breadcrumb = 'Asset Management'; + + protected array $children = [ + AssetLocationResource::class, + AssetStatusResource::class, + AssetTypeResource::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} diff --git a/app/Filament/Pages/InteractionManagement.php b/app/Filament/Pages/InteractionManagement.php new file mode 100644 index 0000000000..df9a9a7f20 --- /dev/null +++ b/app/Filament/Pages/InteractionManagement.php @@ -0,0 +1,78 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use AdvisingApp\Interaction\Filament\Resources\InteractionTypeResource; +use AdvisingApp\Interaction\Filament\Resources\InteractionDriverResource; +use AdvisingApp\Interaction\Filament\Resources\InteractionStatusResource; +use AdvisingApp\Interaction\Filament\Resources\InteractionOutcomeResource; +use AdvisingApp\Interaction\Filament\Resources\InteractionCampaignResource; +use AdvisingApp\Interaction\Filament\Resources\InteractionRelationResource; + +class InteractionManagement extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?int $navigationSort = 8; + + protected static ?string $title = 'Interaction Management'; + + protected static ?string $breadcrumb = 'Interaction Management'; + + protected array $children = [ + InteractionCampaignResource::class, + InteractionDriverResource::class, + InteractionOutcomeResource::class, + InteractionRelationResource::class, + InteractionStatusResource::class, + InteractionTypeResource::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} diff --git a/app/Filament/Pages/KnowledgeManagement.php b/app/Filament/Pages/KnowledgeManagement.php new file mode 100644 index 0000000000..32f277251d --- /dev/null +++ b/app/Filament/Pages/KnowledgeManagement.php @@ -0,0 +1,72 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseStatusResource; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseQualityResource; +use AdvisingApp\KnowledgeBase\Filament\Resources\KnowledgeBaseCategoryResource; + +class KnowledgeManagement extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?int $navigationSort = 7; + + protected static ?string $title = 'Knowledge Management'; + + protected static ?string $breadcrumb = 'Knowledge Management'; + + protected array $children = [ + KnowledgeBaseCategoryResource::class, + KnowledgeBaseQualityResource::class, + KnowledgeBaseStatusResource::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} diff --git a/app/Filament/Pages/OnlineAdmissions.php b/app/Filament/Pages/OnlineAdmissions.php new file mode 100644 index 0000000000..58d2218cec --- /dev/null +++ b/app/Filament/Pages/OnlineAdmissions.php @@ -0,0 +1,68 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use AdvisingApp\Application\Filament\Resources\ApplicationSubmissionStateResource; + +class OnlineAdmissions extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?int $navigationSort = 10; + + protected static ?string $title = 'Online Admissions'; + + protected static ?string $breadcrumb = 'Online Admissions'; + + protected array $children = [ + ApplicationSubmissionStateResource::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} diff --git a/app/Filament/Pages/ProductIntegrations.php b/app/Filament/Pages/ProductIntegrations.php index 6c4dbb3bfe..5c332d6ba5 100644 --- a/app/Filament/Pages/ProductIntegrations.php +++ b/app/Filament/Pages/ProductIntegrations.php @@ -38,6 +38,7 @@ use Filament\Pages\Page; use AdvisingApp\IntegrationTwilio\Filament\Pages\ManageTwilioSettings; +use AdvisingApp\IntegrationAwsSesEventHandling\Filament\Pages\ManageAmazonSesSettings; use AdvisingApp\IntegrationGoogleAnalytics\Filament\Pages\ManageGoogleAnalyticsSettings; use AdvisingApp\IntegrationGoogleRecaptcha\Filament\Pages\ManageGoogleRecaptchaSettings; use AdvisingApp\IntegrationMicrosoftClarity\Filament\Pages\ManageMicrosoftClaritySettings; @@ -57,6 +58,7 @@ class ProductIntegrations extends Page ManageGoogleRecaptchaSettings::class, ManageMicrosoftClaritySettings::class, ManageTwilioSettings::class, + ManageAmazonSesSettings::class, ]; public function mount() diff --git a/app/Filament/Pages/ProfileManagement.php b/app/Filament/Pages/ProfileManagement.php new file mode 100644 index 0000000000..e4bcfd601d --- /dev/null +++ b/app/Filament/Pages/ProfileManagement.php @@ -0,0 +1,68 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use App\Filament\Resources\PronounsResource; + +class ProfileManagement extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?int $navigationSort = 9; + + protected static ?string $title = 'Profile Management'; + + protected static ?string $breadcrumb = 'Profile Management'; + + protected array $children = [ + PronounsResource::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} diff --git a/app/Filament/Pages/RecruitmentCrm.php b/app/Filament/Pages/RecruitmentCrm.php new file mode 100644 index 0000000000..d8e47473e2 --- /dev/null +++ b/app/Filament/Pages/RecruitmentCrm.php @@ -0,0 +1,70 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use AdvisingApp\Prospect\Filament\Resources\ProspectSourceResource; +use AdvisingApp\Prospect\Filament\Resources\ProspectStatusResource; + +class RecruitmentCrm extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?int $navigationSort = 4; + + protected static ?string $title = 'Recruitment CRM'; + + protected static ?string $breadcrumb = 'Recruitment CRM'; + + protected array $children = [ + ProspectStatusResource::class, + ProspectSourceResource::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} diff --git a/app/Filament/Pages/ServiceManagement.php b/app/Filament/Pages/ServiceManagement.php new file mode 100644 index 0000000000..f498185581 --- /dev/null +++ b/app/Filament/Pages/ServiceManagement.php @@ -0,0 +1,72 @@ + + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + +namespace App\Filament\Pages; + +use Filament\Pages\Page; +use AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestTypeResource; +use AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestStatusResource; +use AdvisingApp\ServiceManagement\Filament\Resources\ServiceRequestPriorityResource; + +class ServiceManagement extends Page +{ + protected static ?string $navigationIcon = 'heroicon-o-document-text'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?int $navigationSort = 6; + + protected static ?string $title = 'Service Management'; + + protected static ?string $breadcrumb = 'Service Management'; + + protected array $children = [ + ServiceRequestPriorityResource::class, + ServiceRequestStatusResource::class, + ServiceRequestTypeResource::class, + ]; + + public function mount() + { + foreach ($this->children as $child) { + if ($child::shouldRegisterNavigation()) { + return redirect($child::getUrl()); + } + } + + abort(404); + } +} diff --git a/app/Filament/Resources/PronounsResource.php b/app/Filament/Resources/PronounsResource.php index e47099b7b8..260a03d571 100644 --- a/app/Filament/Resources/PronounsResource.php +++ b/app/Filament/Resources/PronounsResource.php @@ -36,13 +36,17 @@ namespace App\Filament\Resources; -use Filament\Forms; -use Filament\Tables; use App\Models\Pronouns; use Filament\Forms\Form; use Filament\Tables\Table; use Filament\Resources\Resource; -use App\Filament\Resources\PronounsResource\Pages; +use Filament\Tables\Actions\EditAction; +use Filament\Tables\Columns\TextColumn; +use Filament\Forms\Components\TextInput; +use Filament\Tables\Actions\DeleteAction; +use Filament\Tables\Actions\BulkActionGroup; +use Filament\Tables\Actions\DeleteBulkAction; +use App\Filament\Resources\PronounsResource\Pages\ManagePronouns; class PronounsResource extends Resource { @@ -50,19 +54,21 @@ class PronounsResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-user-group'; - protected static ?string $navigationGroup = 'Product Settings'; - protected static ?string $label = 'User Profile Pronoun'; - protected static ?string $pluralLabel = 'User Profile Pronouns'; + protected static ?string $navigationParentItem = 'Profile Management'; + + protected static ?string $navigationGroup = 'Product Administration'; + + protected static ?string $navigationLabel = 'Personal Pronouns'; - protected static ?int $navigationSort = 17; + protected static ?int $navigationSort = 1; public static function form(Form $form): Form { return $form ->schema([ - Forms\Components\TextInput::make('label') + TextInput::make('label') ->placeholder('She/Her') ->required() ->maxLength(255), @@ -74,16 +80,16 @@ public static function table(Table $table): Table { return $table ->columns([ - Tables\Columns\TextColumn::make('label'), + TextColumn::make('label'), ]) ->actions([ - Tables\Actions\EditAction::make() + EditAction::make() ->modalWidth('md'), - Tables\Actions\DeleteAction::make(), + DeleteAction::make(), ]) ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make(), + BulkActionGroup::make([ + DeleteBulkAction::make(), ]), ]); } @@ -91,7 +97,7 @@ public static function table(Table $table): Table public static function getPages(): array { return [ - 'index' => Pages\ManagePronouns::route('/'), + 'index' => ManagePronouns::route('/'), ]; } } From acc77c2ed62baf01707c77fb54a52a0201036987 Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 19:59:54 -0500 Subject: [PATCH 150/152] Generate files Signed-off-by: Kevin Ullyott --- _ide_helper_models.php | 168 ++++++++++++++---- .../src/Models/AssetCheckIn.php | 3 + .../src/Models/AssetCheckOut.php | 3 + 3 files changed, 140 insertions(+), 34 deletions(-) diff --git a/_ide_helper_models.php b/_ide_helper_models.php index a231283c0b..e004d5c352 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -1,39 +1,5 @@ - - Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. - - Advising App™ is licensed under the Elastic License 2.0. For more details, - see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. - - Notice: - - - You may not provide the software to third parties as a hosted or managed - service, where the service provides users with access to any substantial set of - the features or functionality of the software. - - You may not move, change, disable, or circumvent the license key functionality - in the software, and you may not remove or obscure any functionality in the - software that is protected by the license key. - - You may not alter, remove, or obscure any licensing, copyright, or other notices - of the licensor in the software. Any use of the licensor’s trademarks is subject - to applicable law. - - Canyon GBS LLC respects the intellectual property rights of others and expects the - same in return. Canyon GBS™ and Advising App™ are registered trademarks of - Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks - vigorously. - - The software solution, including services, infrastructure, and code, is offered as a - Software as a Service (SaaS) by Canyon GBS LLC. - - Use of this software implies agreement to the license terms and conditions as stated - in the Elastic License 2.0. - - For more information or inquiries please visit our website at - https://www.canyongbs.com or contact us via email at legal@canyongbs.com. - - -*/ - // @formatter:off /** * A helper file for your Eloquent Models @@ -2039,8 +2005,15 @@ class IdeHelperInteractionType {} * @property string $purchase_date * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at * @property-read \Illuminate\Database\Eloquent\Collection $audits * @property-read int|null $audits_count + * @property-read \Illuminate\Database\Eloquent\Collection $checkIns + * @property-read int|null $check_ins_count + * @property-read \Illuminate\Database\Eloquent\Collection $checkOuts + * @property-read int|null $check_outs_count + * @property-read \AdvisingApp\InventoryManagement\Models\AssetCheckIn|null $latestCheckIn + * @property-read \AdvisingApp\InventoryManagement\Models\AssetCheckOut|null $latestCheckOut * @property-read \AdvisingApp\InventoryManagement\Models\AssetLocation $location * @property-read \Illuminate\Database\Eloquent\Collection $maintenanceActivities * @property-read int|null $maintenance_activities_count @@ -2049,8 +2022,10 @@ class IdeHelperInteractionType {} * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|Asset newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Asset newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Asset onlyTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Asset query() * @method static \Illuminate\Database\Eloquent\Builder|Asset whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset whereDeletedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|Asset whereDescription($value) * @method static \Illuminate\Database\Eloquent\Builder|Asset whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|Asset whereLocationId($value) @@ -2060,12 +2035,108 @@ class IdeHelperInteractionType {} * @method static \Illuminate\Database\Eloquent\Builder|Asset whereStatusId($value) * @method static \Illuminate\Database\Eloquent\Builder|Asset whereTypeId($value) * @method static \Illuminate\Database\Eloquent\Builder|Asset whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Asset withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|Asset withoutTrashed() * @mixin \Eloquent */ #[\AllowDynamicProperties] class IdeHelperAsset {} } +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\AssetCheckIn + * + * @property string $id + * @property string $asset_id + * @property string|null $checked_in_by_type + * @property string|null $checked_in_by_id + * @property string $checked_in_from_type + * @property string $checked_in_from_id + * @property \Illuminate\Support\Carbon $checked_in_at + * @property string|null $notes + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at + * @property-read \AdvisingApp\InventoryManagement\Models\Asset $asset + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @property-read \AdvisingApp\InventoryManagement\Models\AssetCheckOut|null $checkOut + * @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $checkedInBy + * @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $checkedInFrom + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetCheckInFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn onlyTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn query() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereAssetId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereCheckedInAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereCheckedInById($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereCheckedInByType($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereCheckedInFromId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereCheckedInFromType($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereDeletedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereNotes($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckIn withoutTrashed() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAssetCheckIn {} +} + +namespace AdvisingApp\InventoryManagement\Models{ +/** + * AdvisingApp\InventoryManagement\Models\AssetCheckOut + * + * @property string $id + * @property string $asset_id + * @property string|null $asset_check_in_id + * @property string|null $checked_out_by_type + * @property string|null $checked_out_by_id + * @property string $checked_out_to_type + * @property string $checked_out_to_id + * @property \Illuminate\Support\Carbon $checked_out_at + * @property \Illuminate\Support\Carbon|null $expected_check_in_at + * @property string|null $notes + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at + * @property-read \AdvisingApp\InventoryManagement\Models\Asset $asset + * @property-read \Illuminate\Database\Eloquent\Collection $audits + * @property-read int|null $audits_count + * @property-read \AdvisingApp\InventoryManagement\Models\AssetCheckIn|null $checkIn + * @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $checkedOutBy + * @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $checkedOutTo + * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetCheckOutFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut onlyTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut query() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereAssetCheckInId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereAssetId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereCheckedOutAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereCheckedOutById($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereCheckedOutByType($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereCheckedOutToId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereCheckedOutToType($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereDeletedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereExpectedCheckInAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereNotes($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|AssetCheckOut withoutTrashed() + * @mixin \Eloquent + */ + #[\AllowDynamicProperties] + class IdeHelperAssetCheckOut {} +} + namespace AdvisingApp\InventoryManagement\Models{ /** * AdvisingApp\InventoryManagement\Models\AssetLocation @@ -2074,6 +2145,7 @@ class IdeHelperAsset {} * @property string $name * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at * @property-read \Illuminate\Database\Eloquent\Collection $assets * @property-read int|null $assets_count * @property-read \Illuminate\Database\Eloquent\Collection $audits @@ -2081,11 +2153,15 @@ class IdeHelperAsset {} * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetLocationFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation onlyTrashed() * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation query() * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereDeletedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereName($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|AssetLocation withoutTrashed() * @mixin \Eloquent */ #[\AllowDynamicProperties] @@ -2097,21 +2173,30 @@ class IdeHelperAssetLocation {} * AdvisingApp\InventoryManagement\Models\AssetStatus * * @property string $id + * @property \AdvisingApp\InventoryManagement\Enums\SystemAssetStatusClassification $classification * @property string $name * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at * @property-read \Illuminate\Database\Eloquent\Collection $assets * @property-read int|null $assets_count * @property-read \Illuminate\Database\Eloquent\Collection $audits * @property-read int|null $audits_count + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus available() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus checkedOut() * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetStatusFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus onlyTrashed() * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus query() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereClassification($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereDeletedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereName($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|AssetStatus withoutTrashed() * @mixin \Eloquent */ #[\AllowDynamicProperties] @@ -2126,6 +2211,7 @@ class IdeHelperAssetStatus {} * @property string $name * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at * @property-read \Illuminate\Database\Eloquent\Collection $assets * @property-read int|null $assets_count * @property-read \Illuminate\Database\Eloquent\Collection $audits @@ -2133,11 +2219,15 @@ class IdeHelperAssetStatus {} * @method static \AdvisingApp\InventoryManagement\Database\Factories\AssetTypeFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|AssetType newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|AssetType newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AssetType onlyTrashed() * @method static \Illuminate\Database\Eloquent\Builder|AssetType query() * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereDeletedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereName($value) * @method static \Illuminate\Database\Eloquent\Builder|AssetType whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AssetType withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|AssetType withoutTrashed() * @mixin \Eloquent */ #[\AllowDynamicProperties] @@ -2158,6 +2248,7 @@ class IdeHelperAssetType {} * @property string|null $notes * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at * @property-read \AdvisingApp\InventoryManagement\Models\Asset $asset * @property-read \Illuminate\Database\Eloquent\Collection $audits * @property-read int|null $audits_count @@ -2165,10 +2256,12 @@ class IdeHelperAssetType {} * @method static \AdvisingApp\InventoryManagement\Database\Factories\MaintenanceActivityFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity onlyTrashed() * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity query() * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereAssetId($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereCompletedDate($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereDeletedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereDetails($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereMaintenanceProviderId($value) @@ -2176,6 +2269,8 @@ class IdeHelperAssetType {} * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereScheduledDate($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereStatus($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceActivity withoutTrashed() * @mixin \Eloquent */ #[\AllowDynamicProperties] @@ -2190,6 +2285,7 @@ class IdeHelperMaintenanceActivity {} * @property string $name * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at * @property-read \Illuminate\Database\Eloquent\Collection $audits * @property-read int|null $audits_count * @property-read \Illuminate\Database\Eloquent\Collection $maintenanceActivities @@ -2197,11 +2293,15 @@ class IdeHelperMaintenanceActivity {} * @method static \AdvisingApp\InventoryManagement\Database\Factories\MaintenanceProviderFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider onlyTrashed() * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider query() * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereDeletedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereName($value) * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|MaintenanceProvider withoutTrashed() * @mixin \Eloquent */ #[\AllowDynamicProperties] diff --git a/app-modules/inventory-management/src/Models/AssetCheckIn.php b/app-modules/inventory-management/src/Models/AssetCheckIn.php index cef99b06aa..0224b826f4 100644 --- a/app-modules/inventory-management/src/Models/AssetCheckIn.php +++ b/app-modules/inventory-management/src/Models/AssetCheckIn.php @@ -44,6 +44,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAssetCheckIn + */ class AssetCheckIn extends BaseModel implements Auditable { use AuditableTrait; diff --git a/app-modules/inventory-management/src/Models/AssetCheckOut.php b/app-modules/inventory-management/src/Models/AssetCheckOut.php index 121c9de71b..6c4bb5e391 100644 --- a/app-modules/inventory-management/src/Models/AssetCheckOut.php +++ b/app-modules/inventory-management/src/Models/AssetCheckOut.php @@ -43,6 +43,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use AdvisingApp\Audit\Models\Concerns\Auditable as AuditableTrait; +/** + * @mixin IdeHelperAssetCheckOut + */ class AssetCheckOut extends BaseModel implements Auditable { use AuditableTrait; From 7208904c44de321fd5a155d46124a93ccf082890 Mon Sep 17 00:00:00 2001 From: Orrison Date: Fri, 5 Jan 2024 01:04:33 +0000 Subject: [PATCH 151/152] chore: fix enforcement of copyright on all files --- _ide_helper_models.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/_ide_helper_models.php b/_ide_helper_models.php index e004d5c352..0f4634ec8a 100644 --- a/_ide_helper_models.php +++ b/_ide_helper_models.php @@ -1,5 +1,39 @@ + + Copyright © 2022-2023, Canyon GBS LLC. All rights reserved. + + Advising App™ is licensed under the Elastic License 2.0. For more details, + see https://github.com/canyongbs/advisingapp/blob/main/LICENSE. + + Notice: + + - You may not provide the software to third parties as a hosted or managed + service, where the service provides users with access to any substantial set of + the features or functionality of the software. + - You may not move, change, disable, or circumvent the license key functionality + in the software, and you may not remove or obscure any functionality in the + software that is protected by the license key. + - You may not alter, remove, or obscure any licensing, copyright, or other notices + of the licensor in the software. Any use of the licensor’s trademarks is subject + to applicable law. + - Canyon GBS LLC respects the intellectual property rights of others and expects the + same in return. Canyon GBS™ and Advising App™ are registered trademarks of + Canyon GBS LLC, and we are committed to enforcing and protecting our trademarks + vigorously. + - The software solution, including services, infrastructure, and code, is offered as a + Software as a Service (SaaS) by Canyon GBS LLC. + - Use of this software implies agreement to the license terms and conditions as stated + in the Elastic License 2.0. + + For more information or inquiries please visit our website at + https://www.canyongbs.com or contact us via email at legal@canyongbs.com. + + +*/ + // @formatter:off /** * A helper file for your Eloquent Models From d636dc4a3570765d1d59bc865239a699a7eb51aa Mon Sep 17 00:00:00 2001 From: Kevin Ullyott Date: Thu, 4 Jan 2024 20:18:13 -0500 Subject: [PATCH 152/152] Remove API reference Signed-off-by: Kevin Ullyott --- .../Resources/SystemUserResource/Pages/ListSystemUsers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Filament/Resources/SystemUserResource/Pages/ListSystemUsers.php b/app/Filament/Resources/SystemUserResource/Pages/ListSystemUsers.php index 3078c02f09..472c811b61 100644 --- a/app/Filament/Resources/SystemUserResource/Pages/ListSystemUsers.php +++ b/app/Filament/Resources/SystemUserResource/Pages/ListSystemUsers.php @@ -50,7 +50,7 @@ class ListSystemUsers extends ListRecords { protected static string $resource = SystemUserResource::class; - protected ?string $heading = 'Programmatic (API) Users'; + protected ?string $heading = 'Programmatic Users'; public function table(Table $table): Table {