Skip to content

Tag Management

Overview

The Tags System provides flexible categorization and organization for digital assets using simple key-value tags. Tags enable users to quickly label, group, and search assets with custom keywords. The system supports tag creation, management, bulk operations, search filtering, and asset integration.

Architecture

System Components

  1. Tag Definitions: Workspace-level tag definitions with colors and metadata
  2. Tag Assignments: Tags assigned to assets (many-to-many relationship)
  3. Tag Management: UI for creating, editing, and managing tags
  4. Asset Integration: Components for adding/removing tags from assets
  5. Search Integration: Tag-based filtering and search capabilities
  6. Bulk Operations: Apply/remove tags from multiple assets simultaneously

File Structure

Core Tag Components

Vue Component Files (.vue)

  • components/dam/FileTagInput.vue - Tag input component

    • Add/remove tags from files
    • Tag autocomplete/suggestions
    • Tag creation on-the-fly
    • Tag display with colors
    • Tag validation
  • components/dam/Dialogs/AddTags/TagsBox.vue - Tags box dialog component

    • Tag selection interface
    • Available tags display
    • Tag search/filter
    • Tag creation
    • Tag assignment to assets
  • components/dam/AssetList/AddTags.vue - Add tags component for asset list

    • Tag management in asset list context
    • Quick tag addition
    • Tag removal
    • Tag display in list view
  • components/dam/Dialogs/AddTags/AddMultipleTags.vue - Dialog for adding multiple tags

    • Bulk tag assignment
    • Multiple asset selection
    • Tag selection interface
    • Batch tag operations

SVG Icon Components

  • components/svg/CollageTagsIcon.vue - Tags icon
    • Used in navigation and UI elements
    • Consistent iconography for tags

Tag Display & Asset Integration

Vue Component Files (.vue)

  • pages/_workspace_id/dam/uploaded.vue - Uploaded assets page
    • Contains addTag method
    • Tag management functionality
    • Tag display in uploaded assets list
    • Tag filtering options

Tag Search & Filtering

JavaScript Files (.js)

  • mixins/search-common-functions.js - Search common functions mixin
    • Contains buildTagFilter function
    • Constructs tag filter queries
    • Integrates with search API
    • Handles multiple tag filters

Vue Component Files (.vue)

  • components/dam/SearchAssets.vue - Search assets component

    • Includes tag search functionality
    • Tag filter application
    • Tag-based result filtering
  • components/dam/SearchBarTypeSense.vue - Search bar component

    • Includes tag search
    • Tag autocomplete in search
    • Tag suggestions
  • components/dam/Search/SearchFilter.vue - Search filter component

    • Includes tag filters
    • Tag selection interface
    • Multiple tag filter support
    • Tag filter removal
  • components/dam/Search/ListLevelThree.vue - Search list level three

    • Includes tag filter options
    • Nested tag filter display
    • Tag-specific filter UI
  • components/dam/Search/AddedFilterOption.vue - Added filter option component

    • Displays active tag filters
    • Tag filter removal functionality
    • Tag filter value display
    • Tag filter editing
  • pages/_workspace_id/dam/search.vue - Search page

    • Includes tag search
    • Tag filter integration
    • Tag-based search results

Tag Bulk Actions

Vue Component Files (.vue)

  • components/dam/SearchBulkActions.vue - Bulk actions component
    • Tag bulk operations
    • Apply tags to multiple assets
    • Remove tags from multiple assets
    • Bulk tag management interface

Supporting Files

JavaScript Files (.js)

  • plugins/helper.js - Helper functions plugin
    • Tag utilities
    • Tag management functions
    • Tag formatting helpers
    • Tag validation functions

Tag Structure

Tag Object

javascript
{
  id: 1,
  workspace_id: 123,
  name: "marketing",
  color: "#FF5722",
  usage_count: 45,
  created_at: "2024-01-15T10:00:00Z",
  updated_at: "2024-01-20T14:30:00Z"
}

Tag Assignment Object

javascript
{
  id: 1,
  asset_id: 456,
  tag_id: 1,
  tag: {
    id: 1,
    name: "marketing",
    color: "#FF5722"
  },
  created_at: "2024-01-15T10:00:00Z"
}

Component Implementation

File Tag Input Component

File: components/dam/FileTagInput.vue

Tag input component for adding and removing tags from files.

Props

javascript
{
  value: {
    type: Array,
    default: () => []
    // Array of tag objects or tag IDs
  },
  assetId: {
    type: [String, Number],
    default: null
  },
  multiple: {
    type: Boolean,
    default: true
  },
  creatable: {
    type: Boolean,
    default: true
  },
  workspaceId: {
    type: [String, Number],
    required: true
  }
}

Methods

javascript
// Add tag
addTag(tag) {
  // Validate tag
  // Add to selected tags
  // Emit update event
  // Call API to save if assetId provided
}

// Remove tag
removeTag(tagId) {
  // Remove from selected tags
  // Emit update event
  // Call API to remove if assetId provided
}

// Create new tag
createTag(tagName, color) {
  // Validate tag name
  // Call API to create tag
  // Add to selected tags
  // Emit tag-created event
}

// Search tags
searchTags(query) {
  // Filter available tags
  // Return matching tags
}

Events

javascript
{
  'input': (tags) => {},        // Tags changed
  'tag-added': (tag) => {},      // Tag added
  'tag-removed': (tagId) => {},  // Tag removed
  'tag-created': (tag) => {}     // New tag created
}

Usage

vue
<template>
  <FileTagInput
    v-model="selectedTags"
    :asset-id="assetId"
    :workspace-id="workspaceId"
    :creatable="true"
    @tag-added="handleTagAdded"
    @tag-removed="handleTagRemoved"
  />
</template>

<script>
import FileTagInput from '~/components/dam/FileTagInput.vue'

export default {
  components: {
    FileTagInput
  },
  data() {
    return {
      assetId: 456,
      workspaceId: this.$route.params.workspace_id,
      selectedTags: []
    }
  }
}
</script>

Tags Box Dialog Component

File: components/dam/Dialogs/AddTags/TagsBox.vue

Dialog component for tag management and assignment.

Features

  • Display available tags
  • Tag search and filtering
  • Tag selection interface
  • Create new tags
  • Assign tags to assets
  • Remove tags from assets

Props

javascript
{
  dialog: {
    type: Boolean,
    default: false
  },
  assetIds: {
    type: Array,
    default: () => []
    // Array of asset IDs for bulk operations
  },
  currentTags: {
    type: Array,
    default: () => []
    // Currently assigned tags
  },
  workspaceId: {
    type: [String, Number],
    required: true
  }
}

Methods

javascript
// Load available tags
async loadTags() {
  // Fetch all tags for workspace
  // Filter and format tags
}

// Search tags
searchTags(query) {
  // Filter tags by name
  // Return matching tags
}

// Select tag
selectTag(tag) {
  // Add to selected tags
  // Update UI
}

// Create tag
async createTag(name, color) {
  // Validate tag name
  // Call API to create
  // Add to available tags
  // Select new tag
}

// Apply tags
async applyTags() {
  // Validate selection
  // Call API to assign tags
  // Handle success/error
}

// Remove tags
async removeTags(tagIds) {
  // Call API to remove tags
  // Update local state
}

Add Tags Component

File: components/dam/AssetList/AddTags.vue

Component for adding tags in asset list context.

Features

  • Quick tag addition
  • Tag display in list
  • Tag removal
  • Tag management for list items

Props

javascript
{
  asset: {
    type: Object,
    required: true
  },
  tags: {
    type: Array,
    default: () => []
  },
  editable: {
    type: Boolean,
    default: true
  }
}

Add Multiple Tags Dialog

File: components/dam/Dialogs/AddTags/AddMultipleTags.vue

Dialog for adding multiple tags to multiple assets.

Features

  • Bulk tag assignment
  • Multiple asset selection
  • Tag selection interface
  • Batch operations
  • Progress tracking

Props

javascript
{
  dialog: {
    type: Boolean,
    default: false
  },
  assetIds: {
    type: Array,
    required: true
    // Array of selected asset IDs
  },
  workspaceId: {
    type: [String, Number],
    required: true
  }
}

Methods

javascript
// Load available tags
async loadAvailableTags() {
  // Fetch all workspace tags
}

// Apply tags to selected assets
async applyTagsToAssets(tagIds) {
  // Validate inputs
  // Call bulk API
  // Track progress
  // Handle success/error
}

// Remove tags from selected assets
async removeTagsFromAssets(tagIds) {
  // Call bulk remove API
  // Update UI
}

Tag Search & Filtering

Build Tag Filter Function

File: mixins/search-common-functions.js

The buildTagFilter function constructs filter queries for tags.

Function Signature

javascript
buildTagFilter(tagIds, operator = 'in') {
  // Build filter object for tags
  // Return filter query object
}

Supported Operators

  • in - Assets with any of the specified tags
  • not_in - Assets without any of the specified tags
  • all - Assets with all of the specified tags

Usage

javascript
// In search component
import searchCommonFunctions from '~/mixins/search-common-functions'

export default {
  mixins: [searchCommonFunctions],
  methods: {
    applyTagFilter(tagIds) {
      const filter = this.buildTagFilter(tagIds, 'in')
      this.addFilter(filter)
    }
  }
}

Search Filter Component

File: components/dam/Search/SearchFilter.vue

Includes tag filters in the search interface.

Features

  • Tag filter selection
  • Multiple tag selection
  • Tag search within filters
  • Filter application
  • Filter removal

Added Filter Option Component

File: components/dam/Search/AddedFilterOption.vue

Displays active tag filters.

Features

  • Shows active tag filters with tag names and colors
  • Remove filter functionality
  • Edit filter value

Tag Bulk Actions

Search Bulk Actions Component

File: components/dam/SearchBulkActions.vue

Bulk actions component including tag operations.

Features

  • Apply tags to multiple selected assets
  • Remove tags from multiple selected assets
  • Bulk tag management
  • Progress tracking for bulk operations

Methods

javascript
// Apply tags to selected assets
async applyTagsToSelected(tagIds) {
  // Get selected asset IDs
  // Call bulk API
  // Show progress
  // Handle success/error
}

// Remove tags from selected assets
async removeTagsFromSelected(tagIds) {
  // Get selected asset IDs
  // Call bulk remove API
  // Update UI
}

Helper Functions

Tag Utilities

File: plugins/helper.js

Helper functions for tag management.

Functions

javascript
// Format tag for display
formatTag(tag) {
  // Format tag object
  // Return formatted tag
}

// Validate tag name
validateTagName(name) {
  // Check length
  // Check characters
  // Return validation result
}

// Generate tag color
generateTagColor(name) {
  // Generate color from tag name
  // Return hex color
}

// Sort tags
sortTags(tags, sortBy = 'name') {
  // Sort tags by specified field
  // Return sorted array
}

API Integration

Tag API Endpoints

List Tags

Endpoint: GET /api/workspaces/:workspace_id/tags

Response:

json
{
  "tags": [
    {
      "id": 1,
      "workspace_id": 123,
      "name": "marketing",
      "color": "#FF5722",
      "usage_count": 45,
      "created_at": "2024-01-15T10:00:00Z",
      "updated_at": "2024-01-20T14:30:00Z"
    }
  ]
}

Create Tag

Endpoint: POST /api/workspaces/:workspace_id/tags

Request Body:

json
{
  "name": "marketing",
  "color": "#FF5722"
}

Response:

json
{
  "tag": {
    "id": 1,
    "workspace_id": 123,
    "name": "marketing",
    "color": "#FF5722",
    "usage_count": 0,
    "created_at": "2024-01-15T10:00:00Z"
  }
}

Update Tag

Endpoint: PUT /api/workspaces/:workspace_id/tags/:tag_id

Request Body:

json
{
  "name": "Marketing Campaign",
  "color": "#E91E63"
}

Response:

json
{
  "tag": {
    "id": 1,
    "name": "Marketing Campaign",
    "color": "#E91E63",
    "updated_at": "2024-01-20T14:30:00Z"
  }
}

Delete Tag

Endpoint: DELETE /api/workspaces/:workspace_id/tags/:tag_id

Response:

json
{
  "success": true,
  "message": "Tag deleted successfully"
}

Assign Tags to Asset

Endpoint: POST /api/digital-assets/:asset_id/tags

Request Body:

json
{
  "tag_ids": [1, 2, 3]
}

Response:

json
{
  "success": true,
  "asset": {
    "id": 456,
    "tags": [
      { "id": 1, "name": "marketing", "color": "#FF5722" },
      { "id": 2, "name": "campaign", "color": "#2196F3" },
      { "id": 3, "name": "2024", "color": "#4CAF50" }
    ]
  }
}

Remove Tags from Asset

Endpoint: DELETE /api/digital-assets/:asset_id/tags

Request Body:

json
{
  "tag_ids": [1, 2]
}

Response:

json
{
  "success": true,
  "message": "Tags removed successfully"
}

Bulk Assign Tags

Endpoint: POST /api/digital-assets/bulk-tags

Request Body:

json
{
  "asset_ids": [456, 457, 458],
  "tag_ids": [1, 2, 3],
  "action": "add" // or "remove"
}

Response:

json
{
  "success": true,
  "updated_assets": 3,
  "message": "Tags applied to 3 assets"
}

Get Asset Tags

Endpoint: GET /api/digital-assets/:asset_id/tags

Response:

json
{
  "tags": [
    {
      "id": 1,
      "name": "marketing",
      "color": "#FF5722",
      "created_at": "2024-01-15T10:00:00Z"
    }
  ]
}

Workflows

Create Tag

1. User navigates to tag management
   - Asset details page OR
   - Tag input component

2. User enters tag name
   Component: FileTagInput.vue or TagsBox.vue
   - Type tag name
   - Optional: Select color

3. Create tag
   - If tag doesn't exist → Create new
   - If tag exists → Use existing

4. Call API
   API: POST /api/workspaces/:workspace_id/tags
   Body: { name, color }

5. Tag created
   - Tag added to workspace
   - Available for use
   - Auto-selected if in input component

6. Update UI
   - Add tag to available tags list
   - Show success message
   - Update tag input

Add Tags to Asset

1. User navigates to asset details
   Route: /:workspace_id/dam/assets/:asset_id

2. Open tag management
   Component: FileTagInput.vue or TagsBox.vue
   - Click tag input/button
   - Or open Add Tags dialog

3. Select tags
   - Search/select from available tags
   - Or create new tags
   - Multiple selection supported

4. Apply tags
   API: POST /api/digital-assets/:asset_id/tags
   Body: { tag_ids: [1, 2, 3] }

5. Tags assigned
   - Tags added to asset
   - Displayed in asset details
   - Available for search/filtering

6. Update UI
   - Refresh tag display
   - Show success message
   - Close dialog (if applicable)

Bulk Tag Assignment

1. User selects multiple assets
   - Use multi-select in asset list
   - Or select from search results

2. Open bulk actions
   Component: SearchBulkActions.vue
   - Click "Add Tags" or similar

3. Open Add Multiple Tags dialog
   Component: AddMultipleTags.vue
   Props: assetIds: [456, 457, 458]

4. Select tags
   - Choose tags to apply
   - Multiple selection supported

5. Apply tags
   API: POST /api/digital-assets/bulk-tags
   Body: {
     asset_ids: [456, 457, 458],
     tag_ids: [1, 2, 3],
     action: "add"
   }

6. Tags applied
   - All selected assets updated
   - Progress tracking
   - Success/error handling

7. Update UI
   - Refresh asset lists
   - Show success message
   - Close dialog

Search with Tag Filter

1. Navigate to search page
   Route: /:workspace_id/dam/search

2. Open search filters
   Component: SearchFilter.vue

3. Select tag filter
   - Choose "Tags" filter option
   - Tag selection interface appears

4. Select tags
   - Search/select tags
   - Multiple tags can be selected
   - Operator selection (in, not_in, all)

5. Apply filter
   Mixin: buildTagFilter()
   - Constructs tag filter query
   - Adds to search filters

6. Execute search
   API: Search with tag filter
   - Filter applied to search query
   - Results filtered by tags

7. Display results
   - Assets matching tag filter
   - Filter shown in AddedFilterOption component
   - Can remove or edit filter

Remove Tags from Asset

1. User navigates to asset details
   Route: /:workspace_id/dam/assets/:asset_id

2. View current tags
   Component: FileTagInput.vue or TagsBox.vue
   - Tags displayed with remove buttons

3. Remove tag
   - Click remove button on tag
   - Or deselect in tag input

4. Call API
   API: DELETE /api/digital-assets/:asset_id/tags
   Body: { tag_ids: [1] }

5. Tag removed
   - Tag removed from asset
   - Updated in database

6. Update UI
   - Remove tag from display
   - Show success message
   - Refresh asset details

Component Integration

Using Tags in Asset Details

vue
<template>
  <div>
    <!-- Tag Input -->
    <FileTagInput
      v-model="assetTags"
      :asset-id="assetId"
      :workspace-id="workspaceId"
      :creatable="true"
      @tag-added="handleTagAdded"
      @tag-removed="handleTagRemoved"
    />
    
    <!-- Or use Tags Box Dialog -->
    <v-btn @click="openTagsDialog">Manage Tags</v-btn>
    
    <TagsBox
      :dialog="tagsDialogOpen"
      :asset-ids="[assetId]"
      :current-tags="assetTags"
      :workspace-id="workspaceId"
      @close="closeTagsDialog"
      @tags-applied="handleTagsApplied"
    />
  </div>
</template>

<script>
import FileTagInput from '~/components/dam/FileTagInput.vue'
import TagsBox from '~/components/dam/Dialogs/AddTags/TagsBox.vue'

export default {
  components: {
    FileTagInput,
    TagsBox
  },
  data() {
    return {
      assetId: this.$route.params.asset_id,
      workspaceId: this.$route.params.workspace_id,
      assetTags: [],
      tagsDialogOpen: false
    }
  },
  async mounted() {
    await this.loadAssetTags()
  },
  methods: {
    async loadAssetTags() {
      const response = await this.$axios.get(
        `/api/digital-assets/${this.assetId}/tags`
      )
      this.assetTags = response.data.tags
    },
    handleTagAdded(tag) {
      // Tag added via input
      this.assetTags.push(tag)
    },
    handleTagRemoved(tagId) {
      // Tag removed via input
      this.assetTags = this.assetTags.filter(t => t.id !== tagId)
    },
    openTagsDialog() {
      this.tagsDialogOpen = true
    },
    closeTagsDialog() {
      this.tagsDialogOpen = false
    },
    handleTagsApplied(tags) {
      // Tags applied via dialog
      this.assetTags = tags
      this.closeTagsDialog()
    }
  }
}
</script>
vue
<template>
  <div>
    <SearchFilter
      :tags="availableTags"
      @tag-filter-applied="applyTagFilter"
    />
    
    <AddedFilterOption
      v-for="filter in activeTagFilters"
      :key="filter.id"
      :filter="filter"
      @remove="removeTagFilter"
    />
  </div>
</template>

<script>
import SearchFilter from '~/components/dam/Search/SearchFilter.vue'
import AddedFilterOption from '~/components/dam/Search/AddedFilterOption.vue'
import searchCommonFunctions from '~/mixins/search-common-functions'

export default {
  components: {
    SearchFilter,
    AddedFilterOption
  },
  mixins: [searchCommonFunctions],
  data() {
    return {
      availableTags: [],
      activeTagFilters: []
    }
  },
  methods: {
    applyTagFilter(tagIds, operator = 'in') {
      const filter = this.buildTagFilter(tagIds, operator)
      this.activeTagFilters.push(filter)
      this.executeSearch()
    },
    removeTagFilter(filterId) {
      this.activeTagFilters = this.activeTagFilters.filter(f => f.id !== filterId)
      this.executeSearch()
    }
  }
}
</script>

Using Bulk Tag Operations

vue
<template>
  <div>
    <SearchBulkActions
      v-if="selectedAssets.length > 0"
      :selected-assets="selectedAssets"
      @bulk-add-tags="handleBulkAddTags"
      @bulk-remove-tags="handleBulkRemoveTags"
    />
    
    <AddMultipleTags
      :dialog="bulkTagsDialogOpen"
      :asset-ids="selectedAssetIds"
      :workspace-id="workspaceId"
      @close="closeBulkTagsDialog"
      @tags-applied="handleBulkTagsApplied"
    />
  </div>
</template>

<script>
import SearchBulkActions from '~/components/dam/SearchBulkActions.vue'
import AddMultipleTags from '~/components/dam/Dialogs/AddTags/AddMultipleTags.vue'

export default {
  components: {
    SearchBulkActions,
    AddMultipleTags
  },
  data() {
    return {
      selectedAssets: [],
      bulkTagsDialogOpen: false,
      workspaceId: this.$route.params.workspace_id
    }
  },
  computed: {
    selectedAssetIds() {
      return this.selectedAssets.map(a => a.id)
    }
  },
  methods: {
    handleBulkAddTags() {
      this.bulkTagsDialogOpen = true
    },
    handleBulkRemoveTags() {
      // Open remove tags dialog
    },
    closeBulkTagsDialog() {
      this.bulkTagsDialogOpen = false
    },
    handleBulkTagsApplied() {
      // Refresh asset list
      this.closeBulkTagsDialog()
    }
  }
}
</script>