Skip to content

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

  1. 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)
  2. 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:

  1. Attachments.vue fieldset component

    • Used in both ObjectiveForm and ProjectForm
    • Handles conditional attachment creation based on model state
  2. Database Model: OpttAttachment

    • Uses polymorphic relationships via attachable_type and attachable_id
    • Supports multiple OPTT model types

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