Skip to content

Commit 721a568

Browse files
authored
Merge pull request #7433 from ProcessMaker/feature/FOUR-18629
feature/FOUR-18629: BE: The API needs to consider save the collapse pero user and feature
2 parents 6b04f3d + b2832ca commit 721a568

File tree

5 files changed

+276
-0
lines changed

5 files changed

+276
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace ProcessMaker\Http\Controllers\Api;
4+
5+
use Exception;
6+
use Illuminate\Http\Request;
7+
use Illuminate\Support\Facades\Auth;
8+
use ProcessMaker\Http\Controllers\Controller;
9+
use ProcessMaker\Http\Resources\ApiResource;
10+
use ProcessMaker\Models\User;
11+
use ProcessMaker\Models\UserConfiguration;
12+
13+
class UserConfigurationController extends Controller
14+
{
15+
const DEFAULT_USER_CONFIGURATION = [
16+
'launchpad' => [
17+
'isMenuCollapse' => true,
18+
],
19+
'cases' => [
20+
'isMenuCollapse' => true,
21+
],
22+
'requests' => [
23+
'isMenuCollapse' => true,
24+
],
25+
'tasks' => [
26+
'isMenuCollapse' => true,
27+
],
28+
];
29+
30+
public function index()
31+
{
32+
$user = Auth::user();
33+
$query = UserConfiguration::select('user_id', 'ui_configuration');
34+
$query->userConfiguration($user->id);
35+
$response = $query->first();
36+
37+
if (empty($response)) {
38+
$response = [
39+
'user_id' => $user->id,
40+
'ui_configuration' => json_encode(self::DEFAULT_USER_CONFIGURATION),
41+
]; // return default
42+
}
43+
44+
return new ApiResource($response);
45+
}
46+
47+
public function store(Request $request)
48+
{
49+
$user = Auth::user();
50+
$userConf = new UserConfiguration();
51+
$request->validate([
52+
'ui_configuration' => 'required|array',
53+
'ui_configuration.launchpad' => 'required|array',
54+
'ui_configuration.cases' => 'required|array',
55+
'ui_configuration.requests' => 'required|array',
56+
'ui_configuration.tasks' => 'required|array',
57+
]);
58+
$uiConfiguration = json_encode($request->input('ui_configuration'));
59+
60+
try {
61+
// Store the user configuration
62+
$userConf->updateOrCreate([
63+
'user_id' => $user->id,
64+
], [
65+
'ui_configuration' => $uiConfiguration,
66+
]);
67+
} catch (Exception $e) {
68+
return response()->json(['error' => $e->getMessage()], 400);
69+
}
70+
71+
return new ApiResource($userConf->refresh());
72+
}
73+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace ProcessMaker\Models;
4+
5+
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use ProcessMaker\Traits\Exportable;
7+
use ProcessMaker\Traits\HasUuids;
8+
9+
class UserConfiguration extends ProcessMakerModel
10+
{
11+
use HasFactory;
12+
13+
protected $connection = 'processmaker';
14+
15+
protected $table = 'user_configuration';
16+
17+
/**
18+
* The attributes that aren't mass assignable.
19+
*
20+
* @var array
21+
*/
22+
protected $guarded = [
23+
'id',
24+
'created_at',
25+
'updated_at',
26+
];
27+
28+
/**
29+
* The attributes that are mass assignable.
30+
*
31+
* @var array
32+
*/
33+
protected $fillable = [
34+
'user_id',
35+
'ui_configuration',
36+
];
37+
38+
public static function rules(): array
39+
{
40+
return [
41+
'user_id' => 'required',
42+
];
43+
}
44+
45+
public function user()
46+
{
47+
return $this->belongsTo(User::class, 'user_id');
48+
}
49+
50+
/**
51+
* Get the launchpad related
52+
*/
53+
public function scopeUserConfiguration($query, $userId)
54+
{
55+
return $query->where('user_id', $userId);
56+
}
57+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
/**
9+
* Run the migrations.
10+
*/
11+
public function up(): void
12+
{
13+
Schema::create('user_configuration', function (Blueprint $table) {
14+
$table->id();
15+
$table->unsignedInteger('user_id');
16+
$table->json('ui_configuration');
17+
$table->timestamps();
18+
19+
// Indexes
20+
$table->index('user_id');
21+
22+
// Foreign keys
23+
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
24+
});
25+
}
26+
27+
/**
28+
* Reverse the migrations.
29+
*/
30+
public function down(): void
31+
{
32+
Schema::dropIfExists('user_configuration');
33+
}
34+
};

routes/api.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
use ProcessMaker\Http\Controllers\Api\TaskController;
3636
use ProcessMaker\Http\Controllers\Api\TaskDraftController;
3737
use ProcessMaker\Http\Controllers\Api\TemplateController;
38+
use ProcessMaker\Http\Controllers\Api\UserConfigurationController;
3839
use ProcessMaker\Http\Controllers\Api\UserController;
3940
use ProcessMaker\Http\Controllers\Api\UserTokenController;
4041
use ProcessMaker\Http\Controllers\Api\WizardTemplateController;
@@ -62,6 +63,9 @@
6263
Route::get('users/{user}/tokens/{tokenId}', [UserTokenController::class, 'show'])->name('users.tokens.show'); // Permissions handled in the controller
6364
Route::post('users/{user}/tokens', [UserTokenController::class, 'store'])->name('users.tokens.store'); // Permissions handled in the controller
6465
Route::delete('users/{user}/tokens/{tokenId}', [UserTokenController::class, 'destroy'])->name('users.tokens.destroy'); // Permissions handled in the controller
66+
// User Configuration
67+
Route::get('users/configuration', [UserConfigurationController::class, 'index'])->name('users.configuration.index');
68+
Route::put('users/configuration', [UserConfigurationController::class, 'store'])->name('users.configuration.store');
6569

6670
// Groups//Permissions policy
6771
Route::get('groups', [GroupController::class, 'index'])->name('groups.index'); // Permissions handled in the controller
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
namespace Tests\Feature\Api;
4+
5+
use ProcessMaker\Http\Controllers\Api\UserConfigurationController;
6+
use ProcessMaker\Models\Process;
7+
use ProcessMaker\Models\ProcessLaunchpad;
8+
use Tests\Feature\Shared\RequestHelper;
9+
use Tests\TestCase;
10+
11+
class UserConfigurationTest extends TestCase
12+
{
13+
use RequestHelper;
14+
15+
const API_TEST_URL = '/users/configuration';
16+
17+
const STRUCTURE = [
18+
'user_id',
19+
'ui_configuration',
20+
];
21+
22+
/**
23+
* Test get deafult user configuration
24+
*/
25+
public function testGetDefaultUserConfiguration()
26+
{
27+
// Call the api GET
28+
$response = $this->apiCall('GET', self::API_TEST_URL);
29+
// Validate the header status code
30+
$response->assertStatus(200);
31+
$this->assertNotEmpty($response);
32+
// Verify structure
33+
$response->assertJsonStructure(self::STRUCTURE);
34+
// Verify default values
35+
$defaultValues = json_encode(UserConfigurationController::DEFAULT_USER_CONFIGURATION);
36+
$this->assertEquals($response->json()['ui_configuration'], $defaultValues);
37+
}
38+
39+
/**
40+
* Test store user configuration and get the new values
41+
*/
42+
public function testStoreUserConfigurationAndGetNewValues()
43+
{
44+
// Call the api PUT
45+
$values = [
46+
'launchpad' => [
47+
'isMenuCollapse' => false,
48+
],
49+
'cases' => [
50+
'isMenuCollapse' => false,
51+
],
52+
'requests' => [
53+
'isMenuCollapse' => false,
54+
],
55+
'tasks' => [
56+
'isMenuCollapse' => false,
57+
],
58+
];
59+
60+
$response = $this->apiCall('PUT', self::API_TEST_URL, ['ui_configuration' => $values]);
61+
// Validate the header status code
62+
$response->assertStatus(200);
63+
64+
// Call the api GET
65+
$response = $this->apiCall('GET', self::API_TEST_URL);
66+
// Validate the header status code
67+
$response->assertStatus(200);
68+
$this->assertNotEmpty($response);
69+
// Verify structure
70+
$response->assertJsonStructure(self::STRUCTURE);
71+
// Verify default values
72+
$uiConfig = json_decode($response->json()['ui_configuration']);
73+
$this->assertEquals($uiConfig->launchpad->isMenuCollapse, $values['launchpad']['isMenuCollapse']);
74+
$this->assertEquals($uiConfig->cases->isMenuCollapse, $values['cases']['isMenuCollapse']);
75+
$this->assertEquals($uiConfig->requests->isMenuCollapse, $values['requests']['isMenuCollapse']);
76+
$this->assertEquals($uiConfig->tasks->isMenuCollapse, $values['tasks']['isMenuCollapse']);
77+
}
78+
79+
/**
80+
* Test store user configuration with invalid values
81+
*/
82+
public function testStoreUserConfigurationWithInvalidValues()
83+
{
84+
// With no values
85+
$response = $this->apiCall('PUT', self::API_TEST_URL);
86+
87+
// Validate the header status code
88+
$response->assertStatus(422);
89+
$this->assertEquals('The Ui configuration field is required. (and 4 more errors)', $response->json()['message']);
90+
91+
// An incomplete ui_configuration
92+
$values = [
93+
'cases' => [
94+
'isMenuCollapse' => false,
95+
],
96+
'requests' => [
97+
'isMenuCollapse' => false,
98+
],
99+
'tasks' => [
100+
'isMenuCollapse' => false,
101+
],
102+
];
103+
$response = $this->apiCall('PUT', self::API_TEST_URL, ['ui_configuration' => $values]);
104+
// Validate the header status code
105+
$response->assertStatus(422);
106+
$this->assertEquals('The Ui configuration.launchpad field is required.', $response->json()['message']);
107+
}
108+
}

0 commit comments

Comments
 (0)