Skip to content

Asset Sharing

Overview

The Share System provides comprehensive sharing functionality for digital assets, folders, and collages. It enables users to create share links and embed codes with advanced settings including password protection, expiration dates, download restrictions, and access controls. The system supports both public sharing and brand-specific shared links.

Architecture

System Components

  1. Share Dialog: Create and manage share links with settings
  2. Share Management: List, update, and revoke share links
  3. Embed Codes: Generate and manage embed codes for assets
  4. Public Share View: Display shared assets to external users
  5. Share Integration: Share functionality integrated into asset/folder components
  6. Share Store: State management for share operations

File Structure

Core Share Components

Vue Component Files (.vue)

  • components/dam/Dialogs/ShareAssetDialog/index.vue - Main share asset dialog

    • Share link generation
    • Embed code generation
    • Share settings configuration
    • Copy share link/embed code
    • Share preview
  • components/dam/Dialogs/ShareAssetDialog/SharePreviewItem.vue - Share preview item component

    • Preview shared asset
    • Asset thumbnail display
    • Asset information
  • components/dam/Dialogs/AdvanceShareDialog.vue - Advanced share settings dialog

    • Password protection
    • Expiration date setting
    • Hide download option
    • Access restrictions
    • Advanced permissions

Share Listing & Management

Vue Component Files (.vue)

  • components/dam/table/shareLinkListTable.vue - Share link list table component

    • Display share links
    • Share link management
    • Sorting and filtering
    • Bulk actions
  • components/dam/table/shareTableHeader.vue - Share table header component

    • Table column headers
    • Sorting controls
    • View mode toggle
  • components/dam/table/shareTableListItem.vue - Share table list item component

    • Individual share link display
    • Share link actions (edit, copy, delete)
    • Share link status
  • components/dam/table/embedTableListItem.vue - Embed table list item component

    • Embed code display
    • Embed code actions (copy, delete)
    • Embed code preview
  • components/dam/ShareListing/ShareAssetsPasswordProtected.vue - Password protected share assets component

    • Password input interface
    • Password validation
    • Access control
  • components/dam/AssetList/ShareLinkHeader.vue - Share link header component

    • Share link information display
    • Share link actions

Share Pages

Vue Page Files (.vue)

  • pages/_workspace_id/dam/sharing/index.vue - Main sharing page
    • Manages shares and embeds
    • Share link list
    • Embed code list
    • Share settings

Route: /:workspace_id/dam/sharing

  • pages/shared-assets/_type.vue - Shared assets page
    • Public-facing shared link view
    • Display shared assets
    • Download shared assets
    • Password protection interface

Route: /shared-assets/:type

  • pages/_brand_name/shared-assets/_type.vue - Brand-specific shared assets page
    • Brand-specific shared link view
    • Branded sharing interface
    • Custom branding display

Route: /:brand_name/shared-assets/:type

Share Integration in Asset/Folder Components

Vue Component Files (.vue)

  • components/dam/Folders/FolderCard.vue - Folder card component

    • Includes share functionality
    • Share folder action
    • Share link display
  • components/dam/Collage/FileListingCard.vue - File listing card

    • Includes share functionality
    • Share asset action
    • Quick share options
  • components/dam/Collage/NonVideoHoverContent.vue - Non-video hover content

    • Includes share actions
    • Share button on hover
    • Quick share menu
  • components/dam/Collage/VideoHoverContent.vue - Video hover content

    • Includes share actions
    • Share button on hover
    • Video-specific share options
  • components/dam/Dialogs/QuickViewDialog.vue - Quick view dialog

    • Includes share functionality
    • Share from quick view
    • Share link generation

Share Mixins & Utilities

JavaScript Files (.js)

  • mixins/damShareUrl.js - Share URL mixin
    • Normalized URL filters
    • Share URL utilities
    • URL generation helpers
    • Share link formatting

Share SVG Icons

Vue Component Files (.vue)

  • components/svg/CollageShareIcon.vue - Share icon

    • Standard share icon
    • Used in share buttons
  • components/svg/CollageShareAltIcon.vue - Share alternate icon

    • Alternate share icon variant
    • Used in different contexts
  • components/svg/CollageRevokeShareIcon.vue - Revoke share icon

    • Revoke/unshare icon
    • Used in share management

Share Store & State Management

JavaScript Files (.js)

  • store/dam.js - DAM store
    • Share-related state
    • downloadMultipleSharedFiles action
    • Share link state management
    • Embed code state management

Share Structure

javascript
{
  id: 1,
  workspace_id: 123,
  asset_id: 456, // or folder_id, collage_id
  asset_type: "asset", // "asset", "folder", "collage"
  share_token: "abc123xyz",
  share_url: "https://app.collage.inc/shared-assets/abc123xyz",
  password: null, // Hashed password if password protected
  is_password_protected: false,
  expires_at: null, // Expiration date if set
  hide_download: false,
  allow_download: true,
  access_count: 0,
  created_by: 789,
  created_at: "2024-01-15T10:00:00Z",
  updated_at: "2024-01-20T14:30:00Z"
}

Embed Code Object

javascript
{
  id: 1,
  workspace_id: 123,
  asset_id: 456,
  embed_token: "embed123xyz",
  embed_code: "<iframe src='...'></iframe>",
  width: 800,
  height: 600,
  allow_fullscreen: true,
  created_by: 789,
  created_at: "2024-01-15T10:00:00Z",
  updated_at: "2024-01-20T14:30:00Z"
}

Component Implementation

Share Asset Dialog

File: components/dam/Dialogs/ShareAssetDialog/index.vue

Main dialog for creating and managing share links and embed codes.

Features

  • Generate share link
  • Generate embed code
  • Copy share link/embed code
  • Share preview
  • Basic share settings
  • Link to advanced settings

Props

javascript
{
  dialog: {
    type: Boolean,
    default: false
  },
  asset: {
    type: Object,
    required: true
    // Asset, folder, or collage object
  },
  assetType: {
    type: String,
    default: 'asset'
    // 'asset', 'folder', 'collage'
  },
  workspaceId: {
    type: [String, Number],
    required: true
  }
}

Data

javascript
data() {
  return {
    shareLink: null,
    embedCode: null,
    shareUrl: '',
    embedCodeHtml: '',
    loading: false,
    activeTab: 'link' // 'link' or 'embed'
  }
}

Methods

javascript
// Generate share link
async generateShareLink() {
  this.loading = true
  try {
    const response = await this.$axios.post(
      '/digital-assets/dashboard/generate-share-assets-url',
      {
        workspace_id: this.workspaceId,
        asset_id: this.asset.id,
        asset_type: this.assetType
      }
    )
    this.shareLink = response.data.share_link
    this.shareUrl = response.data.share_url
  } catch (error) {
    this.$toast.error('Failed to generate share link')
  } finally {
    this.loading = false
  }
}

// Generate embed code
async generateEmbedCode() {
  this.loading = true
  try {
    const response = await this.$axios.post(
      '/digital-assets/embed-code/generate',
      {
        workspace_id: this.workspaceId,
        asset_id: this.asset.id
      }
    )
    this.embedCode = response.data.embed_code
    this.embedCodeHtml = response.data.embed_code_html
  } catch (error) {
    this.$toast.error('Failed to generate embed code')
  } finally {
    this.loading = false
  }
}

// Copy share link
copyShareLink() {
  navigator.clipboard.writeText(this.shareUrl)
  this.$toast.success('Share link copied to clipboard')
}

// Copy embed code
copyEmbedCode() {
  navigator.clipboard.writeText(this.embedCodeHtml)
  this.$toast.success('Embed code copied to clipboard')
}

// Open advanced settings
openAdvancedSettings() {
  this.$emit('open-advanced', this.shareLink)
}

Usage

vue
<template>
  <ShareAssetDialog
    :dialog="shareDialogOpen"
    :asset="selectedAsset"
    :asset-type="assetType"
    :workspace-id="workspaceId"
    @close="closeShareDialog"
    @open-advanced="openAdvancedShareDialog"
  />
</template>

Advanced Share Dialog

File: components/dam/Dialogs/AdvanceShareDialog.vue

Advanced share settings dialog with password protection, expiration, and download restrictions.

Features

  • Password protection
  • Expiration date setting
  • Hide download option
  • Access restrictions
  • Advanced permissions

Props

javascript
{
  dialog: {
    type: Boolean,
    default: false
  },
  shareLink: {
    type: Object,
    default: null
    // Existing share link to update
  },
  asset: {
    type: Object,
    required: true
  },
  workspaceId: {
    type: [String, Number],
    required: true
  }
}

Data

javascript
data() {
  return {
    form: {
      password: '',
      is_password_protected: false,
      expires_at: null,
      hide_download: false,
      allow_download: true
    },
    loading: false
  }
}

Methods

javascript
// Save advanced settings
async saveAdvancedSettings() {
  this.loading = true
  try {
    const payload = {
      workspace_id: this.workspaceId,
      share_link_id: this.shareLink?.id,
      ...this.form
    }
    
    if (this.shareLink) {
      // Update existing share link
      await this.$axios.put(
        '/digital-assets/share-link/update',
        payload
      )
      this.$toast.success('Share settings updated')
    } else {
      // Create new share link with settings
      await this.$axios.post(
        '/digital-assets/dashboard/generate-share-assets-url',
        {
          workspace_id: this.workspaceId,
          asset_id: this.asset.id,
          ...this.form
        }
      )
      this.$toast.success('Share link created with settings')
    }
    
    this.$emit('saved')
    this.closeDialog()
  } catch (error) {
    this.$toast.error('Failed to save share settings')
  } finally {
    this.loading = false
  }
}

File: components/dam/table/shareLinkListTable.vue

Table component for displaying and managing share links.

Features

  • Display share links list
  • Share link actions (edit, copy, delete)
  • Sorting and filtering
  • Pagination
  • Bulk actions

Props

javascript
{
  shareLinks: {
    type: Array,
    required: true
    // Array of share link objects
  },
  loading: {
    type: Boolean,
    default: false
  },
  total: {
    type: Number,
    default: 0
  },
  page: {
    type: Number,
    default: 1
  }
}

Methods

javascript
// Copy share link
copyShareLink(shareLink) {
  navigator.clipboard.writeText(shareLink.share_url)
  this.$toast.success('Share link copied')
}

// Delete share link
async deleteShareLink(shareLinkId) {
  try {
    await this.$axios.delete(
      '/digital-assets/share-link/delete',
      { params: { id: shareLinkId } }
    )
    this.$toast.success('Share link deleted')
    this.$emit('deleted', shareLinkId)
  } catch (error) {
    this.$toast.error('Failed to delete share link')
  }
}

// Update share link
async updateShareLink(shareLink) {
  this.$emit('edit', shareLink)
}

Share Pages

Main Sharing Page

File: pages/_workspace_id/dam/sharing/index.vue

Route: /:workspace_id/dam/sharing

Main page for managing shares and embeds.

Features

  • Share links list
  • Embed codes list
  • Create new share link
  • Create new embed code
  • Manage existing shares
  • Filter and search
  • Toggle between shares and embeds

Shared Assets Page

File: pages/shared-assets/_type.vue

Route: /shared-assets/:type

Public-facing page for viewing shared assets.

Features

  • Display shared assets
  • Password protection interface
  • Download shared assets
  • Asset preview
  • Share link information

Share URL Mixin

File: mixins/damShareUrl.js

Share URL utilities and normalized URL filters.

Functions

javascript
// Normalize share URL
normalizeShareUrl(url) {
  // Remove query parameters
  // Normalize domain
  // Return clean URL
}

// Generate share URL
generateShareUrl(shareToken, options = {}) {
  const baseUrl = options.baseUrl || 'https://app.collage.inc'
  const brandName = options.brandName
  const path = brandName 
    ? `/${brandName}/shared-assets/${shareToken}`
    : `/shared-assets/${shareToken}`
  return `${baseUrl}${path}`
}

// Validate share URL
validateShareUrl(url) {
  // Check URL format
  // Validate domain
  // Return validation result
}

Usage

vue
<script>
import damShareUrl from '~/mixins/damShareUrl'

export default {
  mixins: [damShareUrl],
  methods: {
    getShareUrl(shareToken) {
      return this.generateShareUrl(shareToken, {
        brandName: this.brandName
      })
    }
  }
}
</script>

Share Store

File: store/dam.js

Share-related state management in Vuex store.

State

javascript
state: {
  shareLinks: [],
  embedCodes: [],
  currentShareLink: null,
  shareLoading: false
}

Actions

javascript
actions: {
  async downloadMultipleSharedFiles({ commit }, { shareToken, fileIds }) {
    try {
      const response = await this.$axios.post(
        '/digital-assets/shared-assets/download',
        {
          share_token: shareToken,
          file_ids: fileIds
        },
        { responseType: 'blob' }
      )
      // Handle file download
      return response.data
    } catch (error) {
      console.error('Failed to download shared files', error)
      throw error
    }
  },
  
  async fetchShareLinks({ commit }, workspaceId) {
    try {
      const response = await this.$axios.get(
        '/digital-assets/share-link/list',
        { params: { workspace_id: workspaceId } }
      )
      commit('SET_SHARE_LINKS', response.data.share_links)
      return response.data.share_links
    } catch (error) {
      console.error('Failed to fetch share links', error)
      throw error
    }
  },
  
  async fetchEmbedCodes({ commit }, workspaceId) {
    try {
      const response = await this.$axios.get(
        '/digital-assets/embed-code/list',
        { params: { workspace_id: workspaceId } }
      )
      commit('SET_EMBED_CODES', response.data.embed_codes)
      return response.data.embed_codes
    } catch (error) {
      console.error('Failed to fetch embed codes', error)
      throw error
    }
  }
}

API Integration

Generate Share Assets URL

Endpoint: POST /digital-assets/dashboard/generate-share-assets-url

Request Body:

json
{
  "workspace_id": 123,
  "asset_id": 456,
  "asset_type": "asset",
  "password": null,
  "is_password_protected": false,
  "expires_at": null,
  "hide_download": false
}

Response:

json
{
  "success": true,
  "share_link": {
    "id": 1,
    "share_token": "abc123xyz",
    "share_url": "https://app.collage.inc/shared-assets/abc123xyz",
    "is_password_protected": false,
    "expires_at": null,
    "hide_download": false
  }
}

Endpoint: GET /digital-assets/share-link/list

Query Parameters:

  • workspace_id (required) - Workspace identifier

Response:

json
{
  "share_links": [
    {
      "id": 1,
      "asset_id": 456,
      "asset_type": "asset",
      "share_token": "abc123xyz",
      "share_url": "https://app.collage.inc/shared-assets/abc123xyz",
      "is_password_protected": false,
      "expires_at": null,
      "hide_download": false,
      "access_count": 0,
      "created_at": "2024-01-15T10:00:00Z"
    }
  ]
}

Endpoint: PUT /digital-assets/share-link/update

Request Body:

json
{
  "share_link_id": 1,
  "password": "newpassword",
  "is_password_protected": true,
  "expires_at": "2024-12-31T23:59:59Z",
  "hide_download": true
}

Response:

json
{
  "success": true,
  "share_link": {
    "id": 1,
    "is_password_protected": true,
    "expires_at": "2024-12-31T23:59:59Z",
    "hide_download": true,
    "updated_at": "2024-01-20T14:30:00Z"
  }
}

Endpoint: DELETE /digital-assets/share-link/delete

Query Parameters:

  • id (required) - Share link ID

Response:

json
{
  "success": true,
  "message": "Share link deleted successfully"
}

Generate Embed Code

Endpoint: POST /digital-assets/embed-code/generate

Request Body:

json
{
  "workspace_id": 123,
  "asset_id": 456,
  "width": 800,
  "height": 600,
  "allow_fullscreen": true
}

Response:

json
{
  "success": true,
  "embed_code": {
    "id": 1,
    "embed_token": "embed123xyz",
    "embed_code_html": "<iframe src='...' width='800' height='600'></iframe>",
    "width": 800,
    "height": 600,
    "allow_fullscreen": true
  }
}

Get Embed Codes List

Endpoint: GET /digital-assets/embed-code/list

Query Parameters:

  • workspace_id (required) - Workspace identifier

Response:

json
{
  "embed_codes": [
    {
      "id": 1,
      "asset_id": 456,
      "embed_token": "embed123xyz",
      "embed_code_html": "<iframe src='...'></iframe>",
      "width": 800,
      "height": 600,
      "created_at": "2024-01-15T10:00:00Z"
    }
  ]
}

Delete Embed Code

Endpoint: DELETE /digital-assets/embed-code/delete

Query Parameters:

  • id (required) - Embed code ID

Response:

json
{
  "success": true,
  "message": "Embed code deleted successfully"
}

Download Shared Assets

Endpoint: POST /digital-assets/shared-assets/download

Request Body:

json
{
  "share_token": "abc123xyz",
  "file_ids": [456, 457, 458],
  "password": "password123" // If password protected
}

Response: Binary file data (blob)

Workflows

1. User selects asset/folder/collage
   Component: AssetCard, FolderCard, etc.

2. Click "Share" button
   Component: ShareAssetDialog opens

3. Generate share link
   API: POST /digital-assets/dashboard/generate-share-assets-url
   Body: { workspace_id, asset_id, asset_type }

4. Share link created
   - Share token generated
   - Share URL created
   - Share link saved

5. Display share link
   - Show share URL
   - Copy button available
   - Link to advanced settings

6. User copies share link
   - Share URL copied to clipboard
   - Success message shown
1. User opens share dialog
   Component: ShareAssetDialog

2. Click "Advanced Settings"
   Component: AdvanceShareDialog opens

3. Configure advanced settings
   - Set password (optional)
   - Set expiration date (optional)
   - Toggle hide download
   - Configure access restrictions

4. Save settings
   API: POST /digital-assets/dashboard/generate-share-assets-url
   Body: { workspace_id, asset_id, password, expires_at, hide_download }

5. Share link created with settings
   - Share link with password protection
   - Share link with expiration
   - Share link with download restrictions

6. Share link ready
   - Share URL available
   - Settings applied
   - Share link saved

View Shared Assets

1. User opens share link
   URL: /shared-assets/:type or /:brand_name/shared-assets/:type

2. Load shared assets
   API: GET /digital-assets/shared-assets/:share_token

3. Check password protection
   - If password protected → Show password input
   - If not → Display assets

4. Validate password (if required)
   - User enters password
   - Validate password
   - Grant access if valid

5. Display shared assets
   - Show asset list
   - Show asset previews
   - Show download options (if allowed)

6. User downloads assets
   API: POST /digital-assets/shared-assets/download
   Body: { share_token, file_ids, password }
   - Files downloaded

Generate Embed Code

1. User selects asset
   Component: AssetCard, QuickViewDialog

2. Open share dialog
   Component: ShareAssetDialog
   - Switch to "Embed" tab

3. Generate embed code
   API: POST /digital-assets/embed-code/generate
   Body: { workspace_id, asset_id, width, height }

4. Embed code created
   - Embed token generated
   - Embed HTML code created

5. Display embed code
   - Show embed HTML code
   - Copy button available
   - Preview available

6. User copies embed code
   - Embed code copied to clipboard
   - Can paste into website/application
1. User navigates to sharing page
   Route: /:workspace_id/dam/sharing

2. Load share links
   API: GET /digital-assets/share-link/list
   Query: { workspace_id }

3. Display share links
   Component: shareLinkListTable
   - List all share links
   - Show share link details
   - Show access count

4. User manages share links
   - Edit share link → Open advanced settings
   - Copy share link → Copy to clipboard
   - Delete share link → Revoke share

5. Update share link
   API: PUT /digital-assets/share-link/update
   Body: { share_link_id, password, expires_at, hide_download }

6. Delete share link
   API: DELETE /digital-assets/share-link/delete
   Query: { id }
   - Share link revoked
   - Share URL no longer accessible

Component Integration

Using Share in Asset Components

vue
<template>
  <div class="asset-card">
    <!-- Asset content -->
    
    <v-btn icon @click="openShareDialog">
      <ShareIcon />
    </v-btn>
    
    <ShareAssetDialog
      :dialog="shareDialogOpen"
      :asset="asset"
      :asset-type="'asset'"
      :workspace-id="workspaceId"
      @close="closeShareDialog"
    />
  </div>
</template>

<script>
import ShareAssetDialog from '~/components/dam/Dialogs/ShareAssetDialog/index.vue'
import ShareIcon from '~/components/svg/CollageShareIcon.vue'

export default {
  components: {
    ShareAssetDialog,
    ShareIcon
  },
  data() {
    return {
      shareDialogOpen: false,
      asset: {},
      workspaceId: this.$route.params.workspace_id
    }
  },
  methods: {
    openShareDialog() {
      this.shareDialogOpen = true
    },
    closeShareDialog() {
      this.shareDialogOpen = false
    }
  }
}
</script>

Using Share URL Mixin

vue
<script>
import damShareUrl from '~/mixins/damShareUrl'

export default {
  mixins: [damShareUrl],
  methods: {
    getShareUrl(shareToken) {
      return this.generateShareUrl(shareToken, {
        brandName: this.brandName
      })
    },
    normalizeUrl(url) {
      return this.normalizeShareUrl(url)
    }
  }
}
</script>

Using Share Store

vue
<script>
export default {
  async mounted() {
    // Fetch share links
    await this.$store.dispatch('dam/fetchShareLinks', this.workspaceId)
    
    // Fetch embed codes
    await this.$store.dispatch('dam/fetchEmbedCodes', this.workspaceId)
  },
  computed: {
    shareLinks() {
      return this.$store.state.dam.shareLinks
    },
    embedCodes() {
      return this.$store.state.dam.embedCodes
    }
  },
  methods: {
    async downloadSharedFiles(shareToken, fileIds) {
      await this.$store.dispatch('dam/downloadMultipleSharedFiles', {
        shareToken,
        fileIds
      })
    }
  }
}
</script>