From 41471033f7e7682079a331e1c5a147430692946c Mon Sep 17 00:00:00 2001 From: luNunezProcessmaker Date: Fri, 27 Sep 2024 16:40:08 -0400 Subject: [PATCH 1/4] feature/FOUR-18629 --- .../Api/UserConfigurationController.php | 75 ++++++++++++ ProcessMaker/Models/UserConfiguration.php | 57 +++++++++ ...09_26_131232_create_user_configuration.php | 35 ++++++ routes/api.php | 4 + tests/Feature/Api/UserConfigurationTest.php | 108 ++++++++++++++++++ 5 files changed, 279 insertions(+) create mode 100644 ProcessMaker/Http/Controllers/Api/UserConfigurationController.php create mode 100644 ProcessMaker/Models/UserConfiguration.php create mode 100644 database/migrations/2024_09_26_131232_create_user_configuration.php create mode 100644 tests/Feature/Api/UserConfigurationTest.php diff --git a/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php b/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php new file mode 100644 index 0000000000..333fb37ce3 --- /dev/null +++ b/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php @@ -0,0 +1,75 @@ + [ + "isMenuCollapse" => true + ], + "cases" => [ + "isMenuCollapse" => true + ], + "requests" => [ + "isMenuCollapse" => true + ], + "tasks" => [ + "isMenuCollapse" => true + ] + ]; + + public function index() + { + $user = Auth::user(); + $query = UserConfiguration::select('user_id', 'ui_configuration'); + $query->userConfiguration($user->id); + $response = $query->first(); + + if (empty($response)) { + $response = [ + 'user_id' => $user->id, + 'ui_configuration' => + json_encode(self::DEFAULT_USER_CONFIGURATION) + ]; // return default + } + + return new ApiResource($response); + } + + public function store(Request $request) + { + $user = Auth::user(); + $userConf = new UserConfiguration(); + $request->validate([ + 'ui_configuration' => 'required|array', + 'ui_configuration.launchpad' => 'required|array', + 'ui_configuration.cases' => 'required|array', + 'ui_configuration.requests' => 'required|array', + 'ui_configuration.tasks' => 'required|array', + ]); + $uiConfiguration = json_encode($request->input('ui_configuration')); + + try { + // Store the user configuration + $userConf->updateOrCreate([ + 'user_id' => $user->id, + ], [ + 'ui_configuration' => $uiConfiguration, + ]); + + } catch (\Exception $e) { + return response()->json(['error' => $e->getMessage()], 400); + } + + return new ApiResource($userConf->refresh()); + } +} diff --git a/ProcessMaker/Models/UserConfiguration.php b/ProcessMaker/Models/UserConfiguration.php new file mode 100644 index 0000000000..13e6b8842d --- /dev/null +++ b/ProcessMaker/Models/UserConfiguration.php @@ -0,0 +1,57 @@ + 'required', + ]; + } + + public function user() + { + return $this->belongsTo(User::class, 'user_id'); + } + + /** + * Get the launchpad related + */ + public function scopeUserConfiguration($query, $userId) + { + return $query->where('user_id', $userId); + } +} diff --git a/database/migrations/2024_09_26_131232_create_user_configuration.php b/database/migrations/2024_09_26_131232_create_user_configuration.php new file mode 100644 index 0000000000..58edd5ab62 --- /dev/null +++ b/database/migrations/2024_09_26_131232_create_user_configuration.php @@ -0,0 +1,35 @@ +id(); + $table->unsignedInteger('user_id'); + $table->json('ui_configuration'); + $table->timestamps(); + + // Indexes + $table->index('user_id'); + + // Foreign keys + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('user_configuration'); + } +}; diff --git a/routes/api.php b/routes/api.php index fcd2e070d6..6d1a8c6575 100644 --- a/routes/api.php +++ b/routes/api.php @@ -35,6 +35,7 @@ use ProcessMaker\Http\Controllers\Api\TaskController; use ProcessMaker\Http\Controllers\Api\TaskDraftController; use ProcessMaker\Http\Controllers\Api\TemplateController; +use ProcessMaker\Http\Controllers\Api\UserConfigurationController; use ProcessMaker\Http\Controllers\Api\UserController; use ProcessMaker\Http\Controllers\Api\UserTokenController; use ProcessMaker\Http\Controllers\Api\WizardTemplateController; @@ -62,6 +63,9 @@ Route::get('users/{user}/tokens/{tokenId}', [UserTokenController::class, 'show'])->name('users.tokens.show'); // Permissions handled in the controller Route::post('users/{user}/tokens', [UserTokenController::class, 'store'])->name('users.tokens.store'); // Permissions handled in the controller Route::delete('users/{user}/tokens/{tokenId}', [UserTokenController::class, 'destroy'])->name('users.tokens.destroy'); // Permissions handled in the controller + // User Configuration + Route::get('users/configuration', [UserConfigurationController::class, 'index'])->name('users.configuration.show'); + Route::put('users/configuration', [UserConfigurationController::class, 'store'])->name('users.configuration.update'); // Groups//Permissions policy Route::get('groups', [GroupController::class, 'index'])->name('groups.index'); // Permissions handled in the controller diff --git a/tests/Feature/Api/UserConfigurationTest.php b/tests/Feature/Api/UserConfigurationTest.php new file mode 100644 index 0000000000..b5c2f409cf --- /dev/null +++ b/tests/Feature/Api/UserConfigurationTest.php @@ -0,0 +1,108 @@ +apiCall('GET', self::API_TEST_URL); + // Validate the header status code + $response->assertStatus(200); + $this->assertNotEmpty($response); + // Verify structure + $response->assertJsonStructure(self::STRUCTURE); + // Verify default values + $defaultValues = json_encode(UserConfigurationController::DEFAULT_USER_CONFIGURATION); + $this->assertEquals($response->json()['ui_configuration'], $defaultValues); + } + + /** + * Test store user configuration and get the new values + */ + public function testStoreUserConfigurationAndGetNewValues() + { + // Call the api PUT + $values = [ + "launchpad" => [ + "isMenuCollapse" => false + ], + "cases" => [ + "isMenuCollapse" => false + ], + "requests" => [ + "isMenuCollapse" => false + ], + "tasks" => [ + "isMenuCollapse" => false + ] + ]; + + $response = $this->apiCall('PUT', self::API_TEST_URL, ['ui_configuration' => $values]); + // Validate the header status code + $response->assertStatus(200); + + // Call the api GET + $response = $this->apiCall('GET', self::API_TEST_URL); + // Validate the header status code + $response->assertStatus(200); + $this->assertNotEmpty($response); + // Verify structure + $response->assertJsonStructure(self::STRUCTURE); + // Verify default values + $uiConfig = json_decode($response->json()['ui_configuration']); + $this->assertEquals($uiConfig->launchpad->isMenuCollapse, $values['launchpad']['isMenuCollapse']); + $this->assertEquals($uiConfig->cases->isMenuCollapse, $values['cases']['isMenuCollapse']); + $this->assertEquals($uiConfig->requests->isMenuCollapse, $values['requests']['isMenuCollapse']); + $this->assertEquals($uiConfig->tasks->isMenuCollapse, $values['tasks']['isMenuCollapse']); + } + + /** + * Test store user configuration with invalid values + */ + public function testStoreUserConfigurationWithInvalidValues() + { + // With no values + $response = $this->apiCall('PUT', self::API_TEST_URL); + + // Validate the header status code + $response->assertStatus(422); + $this->assertEquals('The Ui configuration field is required. (and 4 more errors)', $response->json()['message']); + + // An incomplete ui_configuration + $values = [ + "cases" => [ + "isMenuCollapse" => false + ], + "requests" => [ + "isMenuCollapse" => false + ], + "tasks" => [ + "isMenuCollapse" => false + ] + ]; + $response = $this->apiCall('PUT', self::API_TEST_URL, ['ui_configuration' => $values]); + // Validate the header status code + $response->assertStatus(422); + $this->assertEquals('The Ui configuration.launchpad field is required.', $response->json()['message']); + } +} From 1e3b7cbc0639a1fd0400ba364ba80b803b02959c Mon Sep 17 00:00:00 2001 From: luNunezProcessmaker Date: Fri, 27 Sep 2024 16:43:05 -0400 Subject: [PATCH 2/4] feature/FOUR-18629 --- routes/api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routes/api.php b/routes/api.php index 6d1a8c6575..c9d00de70d 100644 --- a/routes/api.php +++ b/routes/api.php @@ -64,8 +64,8 @@ Route::post('users/{user}/tokens', [UserTokenController::class, 'store'])->name('users.tokens.store'); // Permissions handled in the controller Route::delete('users/{user}/tokens/{tokenId}', [UserTokenController::class, 'destroy'])->name('users.tokens.destroy'); // Permissions handled in the controller // User Configuration - Route::get('users/configuration', [UserConfigurationController::class, 'index'])->name('users.configuration.show'); - Route::put('users/configuration', [UserConfigurationController::class, 'store'])->name('users.configuration.update'); + Route::get('users/configuration', [UserConfigurationController::class, 'index'])->name('users.configuration.index'); + Route::put('users/configuration', [UserConfigurationController::class, 'store'])->name('users.configuration.store'); // Groups//Permissions policy Route::get('groups', [GroupController::class, 'index'])->name('groups.index'); // Permissions handled in the controller From e9f3fb0e89b09bc6940b1a109e63d54d9542fab5 Mon Sep 17 00:00:00 2001 From: luNunezProcessmaker Date: Mon, 30 Sep 2024 08:38:31 -0400 Subject: [PATCH 3/4] feature/FOUR-18629 --- .../Api/UserConfigurationController.php | 29 +++++++--------- ProcessMaker/Models/UserConfiguration.php | 2 +- ...09_26_131232_create_user_configuration.php | 3 +- tests/Feature/Api/UserConfigurationTest.php | 34 +++++++++---------- 4 files changed, 32 insertions(+), 36 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php b/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php index 333fb37ce3..3e63b65d95 100644 --- a/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php +++ b/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php @@ -2,7 +2,6 @@ namespace ProcessMaker\Http\Controllers\Api; - use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use ProcessMaker\Http\Controllers\Controller; @@ -13,18 +12,18 @@ class UserConfigurationController extends Controller { const DEFAULT_USER_CONFIGURATION = [ - "launchpad" => [ - "isMenuCollapse" => true + 'launchpad' => [ + 'isMenuCollapse' => true, + ], + 'cases' => [ + 'isMenuCollapse' => true, ], - "cases" => [ - "isMenuCollapse" => true + 'requests' => [ + 'isMenuCollapse' => true, ], - "requests" => [ - "isMenuCollapse" => true + 'tasks' => [ + 'isMenuCollapse' => true, ], - "tasks" => [ - "isMenuCollapse" => true - ] ]; public function index() @@ -36,12 +35,11 @@ public function index() if (empty($response)) { $response = [ - 'user_id' => $user->id, - 'ui_configuration' => - json_encode(self::DEFAULT_USER_CONFIGURATION) + 'user_id' => $user->id, + 'ui_configuration' => json_encode(self::DEFAULT_USER_CONFIGURATION), ]; // return default } - + return new ApiResource($response); } @@ -56,7 +54,7 @@ public function store(Request $request) 'ui_configuration.requests' => 'required|array', 'ui_configuration.tasks' => 'required|array', ]); - $uiConfiguration = json_encode($request->input('ui_configuration')); + $uiConfiguration = json_encode($request->input('ui_configuration')); try { // Store the user configuration @@ -65,7 +63,6 @@ public function store(Request $request) ], [ 'ui_configuration' => $uiConfiguration, ]); - } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 400); } diff --git a/ProcessMaker/Models/UserConfiguration.php b/ProcessMaker/Models/UserConfiguration.php index 13e6b8842d..d060858695 100644 --- a/ProcessMaker/Models/UserConfiguration.php +++ b/ProcessMaker/Models/UserConfiguration.php @@ -3,8 +3,8 @@ namespace ProcessMaker\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; -use ProcessMaker\Traits\HasUuids; use ProcessMaker\Traits\Exportable; +use ProcessMaker\Traits\HasUuids; class UserConfiguration extends ProcessMakerModel { diff --git a/database/migrations/2024_09_26_131232_create_user_configuration.php b/database/migrations/2024_09_26_131232_create_user_configuration.php index 58edd5ab62..5e2ba57f4e 100644 --- a/database/migrations/2024_09_26_131232_create_user_configuration.php +++ b/database/migrations/2024_09_26_131232_create_user_configuration.php @@ -4,8 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class extends Migration { /** * Run the migrations. */ diff --git a/tests/Feature/Api/UserConfigurationTest.php b/tests/Feature/Api/UserConfigurationTest.php index b5c2f409cf..0a2b4a0c8d 100644 --- a/tests/Feature/Api/UserConfigurationTest.php +++ b/tests/Feature/Api/UserConfigurationTest.php @@ -16,7 +16,7 @@ class UserConfigurationTest extends TestCase const STRUCTURE = [ 'user_id', - 'ui_configuration' + 'ui_configuration', ]; /** @@ -43,18 +43,18 @@ public function testStoreUserConfigurationAndGetNewValues() { // Call the api PUT $values = [ - "launchpad" => [ - "isMenuCollapse" => false + 'launchpad' => [ + 'isMenuCollapse' => false, ], - "cases" => [ - "isMenuCollapse" => false + 'cases' => [ + 'isMenuCollapse' => false, ], - "requests" => [ - "isMenuCollapse" => false + 'requests' => [ + 'isMenuCollapse' => false, + ], + 'tasks' => [ + 'isMenuCollapse' => false, ], - "tasks" => [ - "isMenuCollapse" => false - ] ]; $response = $this->apiCall('PUT', self::API_TEST_URL, ['ui_configuration' => $values]); @@ -90,15 +90,15 @@ public function testStoreUserConfigurationWithInvalidValues() // An incomplete ui_configuration $values = [ - "cases" => [ - "isMenuCollapse" => false + 'cases' => [ + 'isMenuCollapse' => false, + ], + 'requests' => [ + 'isMenuCollapse' => false, ], - "requests" => [ - "isMenuCollapse" => false + 'tasks' => [ + 'isMenuCollapse' => false, ], - "tasks" => [ - "isMenuCollapse" => false - ] ]; $response = $this->apiCall('PUT', self::API_TEST_URL, ['ui_configuration' => $values]); // Validate the header status code From b2832ca518e85dc1a431d7d952a7dc8280198381 Mon Sep 17 00:00:00 2001 From: luNunezProcessmaker Date: Mon, 30 Sep 2024 08:41:37 -0400 Subject: [PATCH 4/4] feature/FOUR-18629 --- .../Http/Controllers/Api/UserConfigurationController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php b/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php index 3e63b65d95..b8027af09c 100644 --- a/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php +++ b/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php @@ -2,6 +2,7 @@ namespace ProcessMaker\Http\Controllers\Api; +use Exception; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use ProcessMaker\Http\Controllers\Controller; @@ -63,7 +64,7 @@ public function store(Request $request) ], [ 'ui_configuration' => $uiConfiguration, ]); - } catch (\Exception $e) { + } catch (Exception $e) { return response()->json(['error' => $e->getMessage()], 400); }