OPTT Attachments System
Overview
The OPTT (Objectives, Projects, Tasks, Targets) attachments system provides a unified way to handle file uploads and links across different OPTT models. It uses shared components for consistency and handles both immediate and deferred attachment creation depending on the model's state.
Key Components
Shared Components
-
UploadForm.vue- Reusable form component for both file uploads and link creation
- Supports two modes: "Upload" and "Link"
- Fields:
- URL (file upload path or external link)
- Title
- Type (upload/link)
-
UploadsList.vue- Displays grid of attachments
- Supports download/view and delete actions
- Shows file/link icons and last updated time
Model Integration
The attachments system is integrated into both Objectives and Projects through:
-
Attachments.vuefieldset component- Used in both ObjectiveForm and ProjectForm
- Handles conditional attachment creation based on model state
-
Database Model:
OpttAttachment- Uses polymorphic relationships via
attachable_typeandattachable_id - Supports multiple OPTT model types
- Uses polymorphic relationships via
Attachment Creation Flows
1. Existing Model
When the OPTT model (Objective/Project) already exists:
// Direct API creation via OpttAttachmentController
public function store(StoreOpttAttachmentRequest $request): JsonResponse
{
$attachment = OpttAttachment::create([
'url' => $request->input('url'),
'title' => $request->input('title'),
'type' => $request->input('type'),
'attachable_type' => $request->input('attachable_type'),
'attachable_id' => $request->input('attachable_id'),
]);
}
2. New Model Creation
When creating a new OPTT model:
// Handled within the model's store method
if (!empty($data['attachments'])) {
foreach ($data['attachments'] as $att) {
OpttAttachment::create([
'url' => $att['url'],
'title' => $att['title'],
'type' => $att['type'],
'attachable_type' => Objective::class, // or Project::class
'attachable_id' => $model->id,
]);
}
}
Form Validation
Both Objective and Project store requests validate attachments:
'attachments' => 'array|sometimes',
'attachments.*.url' => 'required|string',
'attachments.*.title' => 'required|string',
'attachments.*.type' => 'required|string',
Frontend Implementation
Component Usage
<attachments
v-model:form="form"
:existingAttachments="form.attachments"
:attachable-type="attachableType"
:attachable-id="modelId"
/>
State Management
- For existing models: Attachments are created immediately via API
- For new models: Attachments are stored in form state and created after model creation
- Deletion handled through API endpoint for both cases
Key Features
- Unified upload/link interface
- Polymorphic relationships for flexibility
- Shared components for consistency
- Conditional creation flows based on model state
- Immediate or deferred attachment creation
- Consistent validation across OPTT models
File Structure
app/
Models/
OpttAttachment.php
Http/
Controllers/
Api/
OpttAttachmentController.php
Requests/
StoreOpttAttachmentRequest.php
resources/
ts/
Components/
Common/
Forms/
UploadForm.vue
UploadsList.vue
Fieldsets/
Attachments.vue