diff --git a/ProcessMaker/Http/Controllers/Api/V1_1/ClipboardController.php b/ProcessMaker/Http/Controllers/Api/V1_1/ClipboardController.php new file mode 100644 index 0000000000..96a62cb40a --- /dev/null +++ b/ProcessMaker/Http/Controllers/Api/V1_1/ClipboardController.php @@ -0,0 +1,106 @@ +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.'); + } + } +} diff --git a/ProcessMaker/Http/Resources/V1_1/ClipboardResource.php b/ProcessMaker/Http/Resources/V1_1/ClipboardResource.php new file mode 100644 index 0000000000..bbbfafd892 --- /dev/null +++ b/ProcessMaker/Http/Resources/V1_1/ClipboardResource.php @@ -0,0 +1,9 @@ +belongsTo(User::class); + } +} diff --git a/database/factories/ProcessMaker/Models/ClipboardFactory.php b/database/factories/ProcessMaker/Models/ClipboardFactory.php new file mode 100644 index 0000000000..c37175dfa9 --- /dev/null +++ b/database/factories/ProcessMaker/Models/ClipboardFactory.php @@ -0,0 +1,25 @@ + + */ +class ClipboardFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'config' => null, + 'user_id' => 1, + 'type' => 'FORM', + ]; + } +} diff --git a/database/migrations/2024_09_12_163218_create_clipboard_table.php b/database/migrations/2024_09_12_163218_create_clipboard_table.php new file mode 100644 index 0000000000..7814e5d8f2 --- /dev/null +++ b/database/migrations/2024_09_12_163218_create_clipboard_table.php @@ -0,0 +1,31 @@ +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'); + } +}; diff --git a/resources/js/processes/screen-builder/screen.vue b/resources/js/processes/screen-builder/screen.vue index 11d6a96274..072553bbbc 100644 --- a/resources/js/processes/screen-builder/screen.vue +++ b/resources/js/processes/screen-builder/screen.vue @@ -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" }), diff --git a/resources/views/processes/screen-builder/screen.blade.php b/resources/views/processes/screen-builder/screen.blade.php index 2fb337ab88..1ad18e10d9 100644 --- a/resources/views/processes/screen-builder/screen.blade.php +++ b/resources/views/processes/screen-builder/screen.blade.php @@ -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); diff --git a/routes/v1_1/api.php b/routes/v1_1/api.php index fe1b6a01c7..d645fc10a5 100644 --- a/routes/v1_1/api.php +++ b/routes/v1_1/api.php @@ -1,6 +1,7 @@ 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']) @@ -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'); + }); });