Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions ProcessMaker/Http/Controllers/Api/V1_1/ClipboardController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

declare(strict_types=1);

namespace ProcessMaker\Http\Controllers\Api\V1_1;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use ProcessMaker\Http\Controllers\Controller;
use ProcessMaker\Http\Resources\V1_1\ClipboardResource as Resource;
use ProcessMaker\Models\Clipboard;

class ClipboardController extends Controller
{
protected $defaultFields = ['id', 'config'];

/**
* Show a specific clipboard by ID
*/
public function show(int $clipboardId): Resource
{
$clipboard = $this->findClipboardOrFail($clipboardId);

return new Resource($clipboard);
}

/**
* Show clipboard for the authenticated user
*/
public function showByUserId(): Resource
{
$userId = Auth::id();
$clipboard = Clipboard::where('user_id', $userId)->firstOrFail();

return new Resource($clipboard);
}

public function createOrUpdateForUser(Request $request): \Illuminate\Http\Response
{
$userId = Auth::id();
$data = $request->all();
$data['user_id'] = $userId;
// Check if a clipboard already exists for the user
$clipboard = Clipboard::where('user_id', $userId)->first();

if ($clipboard) {
$clipboard->fill($data);
} else {
$clipboard = new Clipboard($data);
$clipboard->fill($data);
}

// Save the clipboard (either newly created or updated)
$clipboard->saveOrFail();

return response(new Resource($clipboard), 201);
}

/**
* Update an existing clipboard for the authenticated user
*/
public function update(int $clipboardId, Request $request): \Illuminate\Http\Response
{
$clipboard = $this->findClipboardOrFail($clipboardId);
$this->authorizeUser($clipboard);

$data = $request->all();
$data['user_id'] = Auth::id();

$clipboard->fill($data);
$clipboard->saveOrFail();

return response([], 204);
}

/**
* Delete a clipboard for the authenticated user
*/
public function destroy(int $clipboardId): \Illuminate\Http\Response
{
$clipboard = $this->findClipboardOrFail($clipboardId);
$this->authorizeUser($clipboard);

$clipboard->delete();

return response([], 204);
}

/**
* Helper method to find a clipboard by ID or fail
*/
protected function findClipboardOrFail(int $clipboardId): Clipboard
{
return Clipboard::findOrFail($clipboardId);
}

/**
* Helper method to authorize a user for clipboard actions
*/
protected function authorizeUser(Clipboard $clipboard): void
{
if ($clipboard->user_id !== Auth::id()) {
abort(403, 'Unauthorized action.');
}
}
}
9 changes: 9 additions & 0 deletions ProcessMaker/Http/Resources/V1_1/ClipboardResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace ProcessMaker\Http\Resources\V1_1;

use ProcessMaker\Http\Resources\ApiResource;

class ClipboardResource extends ApiResource
{
}
33 changes: 33 additions & 0 deletions ProcessMaker/Models/Clipboard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace ProcessMaker\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use ProcessMaker\Models\ProcessMakerModel;

class Clipboard extends ProcessMakerModel
{
use HasFactory;

protected $fillable = [
'config',
'user_id',
'type',
];

/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = [
'id',
'created_at',
'updated_at',
];

public function user()
{
return $this->belongsTo(User::class);
}
}
25 changes: 25 additions & 0 deletions database/factories/ProcessMaker/Models/ClipboardFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Database\Factories\ProcessMaker\Models;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\ProcessMaker\Models\Model>
*/
class ClipboardFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'config' => null,
'user_id' => 1,
'type' => 'FORM',
];
}
}
31 changes: 31 additions & 0 deletions database/migrations/2024_09_12_163218_create_clipboard_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('clipboards', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('user_id')->nullable();
$table->mediumText('config');
$table->string('type', 20)->default('FORM');
$table->timestamps();
// Foreign keys
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('clipboard');
}
};
9 changes: 9 additions & 0 deletions resources/js/processes/screen-builder/screen.vue
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,15 @@ export default {
ProcessMaker.EventBus.$on("show-create-template-modal", () => {
this.$refs["create-template-modal"].show();
});
ProcessMaker.EventBus.$on(
"save-clipboard",
(items) => {
console.log('save-clipboard',items);
ProcessMaker.apiClient.post('/api/1.1/clipboard/create_or_update', {
config: JSON.stringify(items),
});
},
);
},
methods: {
...mapMutations("globalErrorsModule", { setStoreMode: "setMode" }),
Expand Down
50 changes: 50 additions & 0 deletions resources/views/processes/screen-builder/screen.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,56 @@ class="border-0 bg-white p-0"
console.warn("Screen builder version does not have watchers");
}
});
window.ProcessMaker.EventBus.$on("screen-renderer-init", (screen) => {
const savedClipboard = localStorage.getItem("savedClipboard");

if (savedClipboard) {
addClipboardToStore(savedClipboard);
return;
}

ProcessMaker.apiClient.get('/api/1.1/clipboard/get_by_user')
.then(handleClipboardResponse)
.catch(handleClipboardError);

/**
* Helper function to add clipboard data to the store
* @param {string|object} clipboardData
*/
function addClipboardToStore(clipboardData) {
try {
const parsedData = typeof clipboardData === 'string' ? JSON.parse(clipboardData) : clipboardData;
if (parsedData && typeof parsedData === 'object') {
screen.$store.dispatch("clipboardModule/addToClipboard", parsedData);
} else {
console.error("Clipboard data is not in the expected format.");
}
} catch (error) {
console.error("Failed to parse clipboard data: ", error);
}
}

/**
* Handle clipboard API response
* @param {object} response
*/
function handleClipboardResponse(response) {
if (response && response.data && response.data.config) {
addClipboardToStore(response.data.config);
} else {
console.error("No valid clipboard config data in response.");
}
}

/**
* Handle clipboard API error
* @param {Error} error
*/
function handleClipboardError(error) {
console.error("Error fetching clipboard data: ", error);
}
});

window.Processmaker.user = @json($currentUser);
</script>
<script src="{{mix('js/leave-warning.js')}}"></script>
Expand Down
15 changes: 14 additions & 1 deletion routes/v1_1/api.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Illuminate\Support\Facades\Route;
use ProcessMaker\Http\Controllers\Api\V1_1\ClipboardController;
use ProcessMaker\Http\Controllers\Api\V1_1\TaskController;

// Define the prefix and name for version 1.1 of the API routes
Expand All @@ -16,7 +17,7 @@
// Route to show a task
Route::get('/{task}', [TaskController::class, 'show'])
->name('show')
->middleware(['bindings','can:view,task']);
->middleware(['bindings', 'can:view,task']);

// Route to show the screen of a task
Route::get('/{taskId}/screen', [TaskController::class, 'showScreen'])
Expand All @@ -26,4 +27,16 @@
Route::get('/{taskId}/interstitial', [TaskController::class, 'showInterstitial'])
->name('show.interstitial');
});
// Clipboard Endpoints
Route::name('clipboard.')->prefix('clipboard')->group(function () {
// Get clipboard by user
Route::get('/get_by_user', [ClipboardController::class, 'showByUserId'])
->name('user');

Route::get('/{clipboard}', [ClipboardController::class, 'show'])
->name('show');

Route::post('/create_or_update', [ClipboardController::class, 'createOrUpdateForUser'])
->name('clipboard.createOrUpdateForUser');
});
});