Appearance
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 ​
- Tag Definitions: Workspace-level tag definitions with colors and metadata
- Tag Assignments: Tags assigned to assets (many-to-many relationship)
- Tag Management: UI for creating, editing, and managing tags
- Asset Integration: Components for adding/removing tags from assets
- Search Integration: Tag-based filtering and search capabilities
- 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
addTagmethod - Tag management functionality
- Tag display in uploaded assets list
- Tag filtering options
- Contains
Tag Search & Filtering ​
JavaScript Files (.js) ​
mixins/search-common-functions.js- Search common functions mixin- Contains
buildTagFilterfunction - Constructs tag filter queries
- Integrates with search API
- Handles multiple tag filters
- Contains
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 tagsnot_in- Assets without any of the specified tagsall- 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 inputAdd 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 dialogSearch 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 filterRemove 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 detailsComponent 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>Using Tags in Search ​
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>Related Documentation ​
- Tags and Custom Fields System - Combined tags and custom fields overview
- Custom Fields System - Custom fields documentation
- Advanced Search Filters - Search filtering including tags
- Global Search Functionality - Search system integration
- Typesense Search Integration - Search backend integration