License Server
Analytics
Licenses
Components
Edit Component
Update the component metadata, code, and availability.
View Component
Back
Component Name
Component name cannot be changed after creation.
Display Name
*
Version
*
Active
Description
Allow users to submit feature requests for the platform
Controller Code (Optional)
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; class FeatureRequestController extends Controller { /** * Display the feature request form. */ public function index() { return view('components.feature-request.index'); } /** * Handle feature request submission. */ public function submit(Request $request) { $validated = $request->validate([ 'title' => 'required|string|max:255', 'description' => 'required|string|max:5000', 'category' => 'required|string|in:enhancement,bug-fix,new-feature,ui-ux,performance,other', 'priority' => 'nullable|string|in:low,medium,high,critical', 'email' => 'nullable|email|max:255', ]); // Get current user if authenticated $user = auth()->user(); // Log the feature request Log::info('Feature Request Submitted', [ 'user_id' => $user?->id, 'user_email' => $user?->email ?? $validated['email'] ?? 'anonymous', 'title' => $validated['title'], 'category' => $validated['category'], 'priority' => $validated['priority'] ?? 'medium', ]); // TODO: Save to database (create a feature_requests table if needed) // FeatureRequest::create([...]); // TODO: Send email notification (optional) // Mail::to('admin@example.com')->send(new FeatureRequestNotification($validated)); return response()->json([ 'success' => true, 'message' => 'Thank you! Your feature request has been submitted successfully.', ]); } }
PHP code for the component controller.
Routes Code (Optional)
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\FeatureRequestController; Route::middleware(['auth', 'component.visible'])->group(function () { Route::get('/feature-request', [FeatureRequestController::class, 'index'])->name('dashboard.feature-request'); Route::post('/feature-request/submit', [FeatureRequestController::class, 'submit'])->name('feature-request.submit'); });
Route definitions for the component.
Views (Optional - JSON)
{ "index.blade.php": "@extends('layouts.app')\n\n@section('title', 'Feature Request - Matomo Tools')\n\n@section('styles')\n@include('dashboard._floating_container_styles')\n<style>\n.feature-form-card {\n max-width: 800px;\n margin: 0 auto;\n}\n\n.form-section {\n margin-bottom: 2rem;\n}\n\n.form-section-title {\n font-size: 1.1rem;\n font-weight: 600;\n color: var(--text-light);\n margin-bottom: 1rem;\n padding-bottom: 0.5rem;\n border-bottom: 2px solid var(--border-color);\n}\n\n.priority-badge {\n display: inline-block;\n padding: 0.25rem 0.75rem;\n border-radius: 12px;\n font-size: 0.85rem;\n font-weight: 600;\n}\n\n.priority-low { background: rgba(59, 130, 246, 0.2); color: #3B82F6; }\n.priority-medium { background: rgba(245, 158, 11, 0.2); color: #F59E0B; }\n.priority-high { background: rgba(239, 68, 68, 0.2); color: #EF4444; }\n.priority-critical { background: rgba(139, 92, 246, 0.2); color: #8B5CF6; }\n<\/style>\n@endsection\n\n@section('content')\n<div class=\"floating-container\">\n <div class=\"row\">\n <!-- Header -->\n <div class=\"col-12 mb-4\">\n <div class=\"card\">\n <div class=\"card-header\">\n <h5 class=\"card-title mb-0\">\n <i class=\"fas fa-lightbulb me-2\"><\/i>Feature Request Form\n <\/h5>\n <\/div>\n <div class=\"card-body\">\n <p class=\"text-muted mb-0\">\n Have an idea for a new feature or improvement? We'd love to hear from you! \n Please fill out the form below to submit your feature request.\n <\/p>\n <\/div>\n <\/div>\n <\/div>\n\n <!-- Feature Request Form -->\n <div class=\"col-12\">\n <div class=\"card feature-form-card\">\n <div class=\"card-body\">\n <form id=\"featureRequestForm\">\n @csrf\n\n <!-- Title -->\n <div class=\"form-section\">\n <label for=\"title\" class=\"form-label\">\n <i class=\"fas fa-heading me-1\"><\/i>Feature Title <span class=\"text-danger\">*<\/span>\n <\/label>\n <input \n type=\"text\" \n class=\"form-control\" \n id=\"title\" \n name=\"title\" \n required \n placeholder=\"e.g., Add dark mode toggle\"\n maxlength=\"255\"\n >\n <small class=\"text-muted\">A brief, descriptive title for your feature request<\/small>\n <\/div>\n\n <!-- Category -->\n <div class=\"form-section\">\n <label for=\"category\" class=\"form-label\">\n <i class=\"fas fa-tags me-1\"><\/i>Category <span class=\"text-danger\">*<\/span>\n <\/label>\n <select class=\"form-select\" id=\"category\" name=\"category\" required>\n <option value=\"\">Select a category...<\/option>\n <option value=\"enhancement\">Enhancement (improve existing feature)<\/option>\n <option value=\"bug-fix\">Bug Fix<\/option>\n <option value=\"new-feature\">New Feature<\/option>\n <option value=\"ui-ux\">UI\/UX Improvement<\/option>\n <option value=\"performance\">Performance Optimization<\/option>\n <option value=\"other\">Other<\/option>\n <\/select>\n <\/div>\n\n <!-- Priority -->\n <div class=\"form-section\">\n <label for=\"priority\" class=\"form-label\">\n <i class=\"fas fa-exclamation-circle me-1\"><\/i>Priority\n <\/label>\n <select class=\"form-select\" id=\"priority\" name=\"priority\">\n <option value=\"medium\">Medium (default)<\/option>\n <option value=\"low\">Low<\/option>\n <option value=\"high\">High<\/option>\n <option value=\"critical\">Critical<\/option>\n <\/select>\n <small class=\"text-muted\">How important is this feature to you?<\/small>\n <\/div>\n\n <!-- Description -->\n <div class=\"form-section\">\n <label for=\"description\" class=\"form-label\">\n <i class=\"fas fa-align-left me-1\"><\/i>Description <span class=\"text-danger\">*<\/span>\n <\/label>\n <textarea \n class=\"form-control\" \n id=\"description\" \n name=\"description\" \n rows=\"8\" \n required \n placeholder=\"Please describe your feature request in detail. Include:\n- What problem does it solve?\n- How would it work?\n- Any examples or mockups?\n- Why is it important?\"\n maxlength=\"5000\"\n ><\/textarea>\n <small class=\"text-muted\">\n <span id=\"charCount\">0<\/span> \/ 5000 characters\n <\/small>\n <\/div>\n\n <!-- Email (optional, if not authenticated) -->\n @if(!auth()->check())\n <div class=\"form-section\">\n <label for=\"email\" class=\"form-label\">\n <i class=\"fas fa-envelope me-1\"><\/i>Email (Optional)\n <\/label>\n <input \n type=\"email\" \n class=\"form-control\" \n id=\"email\" \n name=\"email\" \n placeholder=\"your.email@example.com\"\n maxlength=\"255\"\n >\n <small class=\"text-muted\">We'll use this to follow up on your request<\/small>\n <\/div>\n @endif\n\n <!-- Submit Button -->\n <div class=\"d-flex justify-content-between align-items-center mt-4\">\n <button type=\"button\" class=\"btn btn-outline-secondary\" onclick=\"clearForm()\">\n <i class=\"fas fa-eraser me-1\"><\/i>Clear Form\n <\/button>\n <button type=\"submit\" class=\"btn btn-primary\" id=\"submitBtn\">\n <i class=\"fas fa-paper-plane me-1\"><\/i>Submit Feature Request\n <\/button>\n <\/div>\n <\/form>\n <\/div>\n <\/div>\n <\/div>\n <\/div>\n<\/div>\n\n<!-- Success\/Error Messages -->\n<div id=\"messageAlert\" class=\"alert d-none mt-3\" role=\"alert\"><\/div>\n\n<script>\n\/\/ Character counter\nconst descriptionTextarea = document.getElementById('description');\nconst charCount = document.getElementById('charCount');\n\nif (descriptionTextarea && charCount) {\n descriptionTextarea.addEventListener('input', function() {\n charCount.textContent = this.value.length;\n });\n}\n\n\/\/ Form submission\nconst form = document.getElementById('featureRequestForm');\nconst submitBtn = document.getElementById('submitBtn');\nconst messageAlert = document.getElementById('messageAlert');\n\nif (form) {\n form.addEventListener('submit', async function(e) {\n e.preventDefault();\n \n \/\/ Disable submit button\n submitBtn.disabled = true;\n submitBtn.innerHTML = '<div class=\"spinner-border spinner-border-sm me-1\"><\/div> Submitting...';\n \n \/\/ Hide previous messages\n messageAlert.classList.add('d-none');\n \n \/\/ Get form data\n const formData = new FormData(form);\n \n try {\n const response = await fetch('{{ route(\"feature-request.submit\") }}', {\n method: 'POST',\n headers: {\n 'X-CSRF-TOKEN': '{{ csrf_token() }}',\n 'Accept': 'application\/json'\n },\n body: formData\n });\n \n const data = await response.json();\n \n if (data.success) {\n \/\/ Show success message\n messageAlert.className = 'alert alert-success mt-3';\n messageAlert.innerHTML = '<i class=\"fas fa-check-circle me-2\"><\/i>' + data.message;\n messageAlert.classList.remove('d-none');\n \n \/\/ Clear form\n form.reset();\n if (charCount) charCount.textContent = '0';\n \n \/\/ Scroll to message\n messageAlert.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n } else {\n \/\/ Show error message\n messageAlert.className = 'alert alert-danger mt-3';\n messageAlert.innerHTML = '<i class=\"fas fa-exclamation-circle me-2\"><\/i>' + (data.message || 'An error occurred. Please try again.');\n messageAlert.classList.remove('d-none');\n \n \/\/ Scroll to message\n messageAlert.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }\n } catch (error) {\n console.error('Error submitting feature request:', error);\n messageAlert.className = 'alert alert-danger mt-3';\n messageAlert.innerHTML = '<i class=\"fas fa-exclamation-circle me-2\"><\/i>Network error. Please check your connection and try again.';\n messageAlert.classList.remove('d-none');\n } finally {\n \/\/ Re-enable submit button\n submitBtn.disabled = false;\n submitBtn.innerHTML = '<i class=\"fas fa-paper-plane me-1\"><\/i>Submit Feature Request';\n }\n });\n}\n\n\/\/ Clear form function\nfunction clearForm() {\n if (confirm('Are you sure you want to clear the form? All entered data will be lost.')) {\n document.getElementById('featureRequestForm').reset();\n if (charCount) charCount.textContent = '0';\n messageAlert.classList.add('d-none');\n }\n}\n<\/script>\n@endsection\n" }
JSON object with view file paths or inline content.
Assets (Optional - JSON)
[]
JSON array of asset file paths.
Update Component
Delete Component