Skip to content

smartlabsAT/directus-expandable-blocks

Repository files navigation

Directus Expandable Blocks Interface

npm version npm downloads GitHub release license Directus 11+ Tests TypeScript

A powerful, production-ready M2A (Many-to-Any) interface extension for Directus with inline expandable editing, advanced item selection, comprehensive permissions, and seamless integration with Directus' native save system. Also provides reusable ItemSelector components for other extensions.

Directus Expandable Blocks Extension - Feature Presentation

πŸ“š Documentation β€’ πŸ› Report Bug β€’ ✨ Request Feature β€’ πŸ“¦ NPM Package

πŸ“– Table of Contents

🎯 Why Expandable Blocks?

Unlike other block editors, this extension works directly with Directus' native form system and provides unique killer features:

πŸš€ Killer Features

  • πŸ” Reference Tracking - See EVERYWHERE an item is used across your entire system
  • πŸ”— Link or Copy - Choose to reference existing items or create independent copies
  • ⚠️ Usage Protection - Never accidentally delete content that's used elsewhere

βœ… Native Integration

  • Native Save & Stay - Works perfectly with Directus' save options
  • Global Discard - Integrates with Directus' "Discard Changes" button
  • Proper Dirty State - Save button only appears when changes exist
  • No Data Loss - All changes tracked through Directus' form state
  • Enterprise Ready - Production-tested with comprehensive permissions
  • 100% Test Coverage - 470 unit tests ensuring reliability

✨ Features

🎨 Core Interface Features

Block Management

  • πŸ“ Inline Expandable Editing - Edit content without opening separate forms
  • 🎯 Drag & Drop Sorting - Intuitive block reordering with visual feedback
  • πŸ†• Visual NEW Indicator - See unsaved blocks at a glance
  • πŸ“Š Status Management - Quick status changes with color-coded indicators
  • πŸ“‹ Duplicate Blocks - Clone existing blocks with one click
  • πŸ—‘οΈ Smart Delete - Unlink or permanently delete with confirmation
  • πŸ”„ Discard Changes - Revert individual blocks to original state

Item Selection & Search

  • πŸ” Advanced Item Selector - Select and link existing items from any collection
  • πŸ”— Link or Copy Mode - Choose to reference existing items or create copies
  • πŸ“Š Table View - Browse items in a sortable, filterable table
  • 🏷️ Tag-Based Search - Search with AND/OR operators and field-specific queries
  • 🎯 Smart Search - Simple search mode with optional advanced tag search
  • πŸ”Ž Search Highlighting - See matching terms highlighted in results
  • πŸ“Œ Search History - Remember and reuse previous searches
  • πŸ“ˆ Result Count - See number of matching items instantly

Table Features

  • πŸ“Š Intelligent Columns - Auto-sizing based on field types
  • πŸ“Œ Sticky Columns - Keep important columns visible while scrolling
  • ↕️ Sortable Headers - Sort by any field with 3-click cycle
  • 🎨 Field Display - Smart rendering for all Directus field types
  • πŸ–ΌοΈ Image Preview - Hover to see full images
  • πŸ“ WYSIWYG Support - Automatic HTML stripping for clean display
  • ⚑ Virtual Scrolling - Handle thousands of items efficiently

🌍 Advanced Features

Translation Support

  • 🌐 Multi-Language - Full support for Directus translations
  • πŸ”„ Language Switching - Change languages on the fly
  • πŸ” Translation Search - Search across all language versions
  • 🏷️ Language Indicators - See which fields are translatable

Permissions & Security

  • πŸ” Directus Permissions - Respects all native permissions
  • πŸ‘₯ Role-Based Control - Configure per-role access
  • πŸ”’ Read-Only Mode - Automatic for restricted items
  • ⚠️ Permission Indicators - Visual feedback for restricted actions
  • πŸ›‘οΈ Security - Built-in validation and permission checks

Usage Tracking & References πŸš€ (Requires API Extension)

  • πŸ” Reference Detection - Instantly see ALL places where an item is used across your entire Directus instance
  • πŸ“ Cross-Collection References - Track usage across different collections and relationships
  • πŸ”— Deep Links - Navigate directly to parent items with one click
  • ⚠️ Usage Warnings - Get alerts before deleting items that are referenced elsewhere
  • πŸ“Š Usage Paths - Visual breadcrumbs showing complete relationship chains
  • 🎯 Smart Prevention - Prevents accidental deletion of referenced content

Note: These features require the optional API extension to be installed.

Inline Editing

  • ✏️ Edit Drawer - Edit items without leaving the interface
  • πŸ’Ύ Independent Saves - Save edits without affecting main form
  • πŸ”„ Live Updates - See changes reflected immediately
  • πŸ“ Adjustable Width - Resize drawer to your preference

⚑ Performance & Quality

Performance

  • πŸš€ Multi-Layer Caching - Configurable TTLs for optimal speed
  • πŸ“Š Smart Loading - Load only what's needed
  • πŸ”„ Debounced Operations - Prevent excessive API calls
  • ⚑ Optimized Re-renders - Using Vue 3's advanced features
  • πŸ’Ύ Persistent Preferences - Remember user settings

Code Quality

  • βœ… 100% Test Coverage - 470 passing unit tests
  • 🎯 TypeScript Strict Mode - Zero type errors
  • πŸ“ ESLint Compliant - Zero linting errors
  • πŸ—οΈ Modular Architecture - 15+ reusable components
  • πŸ“š Comprehensive Docs - Wiki, API docs, and inline comments

πŸ› οΈ Developer Features

Extension Architecture

  • πŸ“¦ Interface Extension - Clean, focused interface implementation
  • πŸ”Œ Composable Architecture - Reusable Vue composables
  • 🎨 Component Library - Modular, tested components
  • πŸ”§ Utility Functions - Shared helpers and validators
  • πŸ“ TypeScript Types - Full type definitions

πŸ“¦ Installation

Via NPM (Recommended)

# Install the interface extension
npm install directus-extension-expandable-blocks

# Optional: Install the API extension for advanced usage tracking
npm install directus-extension-expandable-blocks-api

Via pnpm

# Install the interface extension
pnpm add directus-extension-expandable-blocks

# Optional: Install the API extension for advanced usage tracking
pnpm add directus-extension-expandable-blocks-api

Manual Installation

  1. Download the latest release from GitHub Releases
  2. Extract to your Directus extensions/ directory
  3. Restart Directus
  4. Optional: Install the API extension for usage tracking

Docker Installation

# Install the interface extension
RUN npm install directus-extension-expandable-blocks

# Optional: Install the API extension for advanced usage tracking
RUN npm install directus-extension-expandable-blocks-api

πŸ“ Important Note About the API Extension

The API extension is now a separate, optional package. The core Expandable Blocks interface works perfectly without it, using Directus' native API for all standard operations.

When to install the API extension:

  • βœ… You want to see where items are used before deleting them
  • βœ… You need to track references across M2A relationships
  • βœ… You want protection against accidentally deleting referenced content

The interface works without the API extension:

  • βœ… All core features (editing, sorting, adding blocks) work normally
  • βœ… Uses native Directus API for all operations
  • ⚠️ Cannot verify item usage before deletion (shows warning instead)

πŸš€ Usage

Basic Setup

1️⃣ Create an M2A Field

  1. Navigate to Settings β†’ Data Model β†’ [Your Collection]
  2. Click "Create Field"
  3. Choose "Many to Any Relationship (M2A)"
  4. Configure the relationship

2️⃣ Select the Expandable Blocks Interface

  1. In the field configuration, go to "Interface" tab
  2. Select "Expandable Blocks" from the dropdown
  3. Configure your options

3️⃣ Configure Options

The interface provides extensive configuration grouped into logical sections:

  • Display Options - Visual preferences
  • Permissions & Actions - What users can do
  • Collections & Relations - Available collections
  • Advanced Settings - Caching, translations, etc.

βš™οΈ Configuration

Display Settings

Option Type Default Description
enableSorting boolean true Enable drag & drop reordering
showItemId boolean true Display item IDs
showCollectionName boolean true Show collection type
startExpanded boolean false Start with blocks expanded
accordionMode boolean false One block open at a time
compactMode boolean false Condensed view

Permissions

Option Type Default Description
isAllowedDelete boolean true Allow deletion
isAllowedDuplicate boolean true Allow duplication
allowLinkExisting boolean true Allow linking existing
allowDuplicateExisting boolean true Allow duplicating linked
maxBlocks number null Maximum blocks allowed

Collections

Option Type Default Description
collection array [] Collections for new blocks
allowedCollectionsExisting array [] Collections for existing items

Advanced

Option Type Default Description
enableCache boolean true Enable API caching
enableTranslations boolean true Support translations
showUsageWarnings boolean true Show usage indicators

Environment Variables

Configure caching behavior:

# Cache TTL Settings (in minutes)
EXPANDABLE_BLOCKS_CACHE_TTL_METADATA=30
EXPANDABLE_BLOCKS_CACHE_TTL_SEARCH=5
EXPANDABLE_BLOCKS_CACHE_TTL_DETAIL=10
EXPANDABLE_BLOCKS_CACHE_TTL_PATHS=10

# Maximum cache size
EXPANDABLE_BLOCKS_CACHE_MAX_SIZE=50000

πŸ”— Shared Components for Other Extensions

This extension provides reusable ItemSelector components that can be used in other Directus extensions, allowing you to avoid code duplication and maintain consistent UX across extensions.

Quick Start for Extension Developers

# Add as dependency to your extension
npm install directus-extension-expandable-blocks
// Import shared components in your extension
import { 
  useItemSelector, 
  ItemSelectorDrawer,
  type ItemSelectorConfig 
} from 'directus-extension-expandable-blocks/shared';

// Configure for your extension
const itemSelector = useItemSelector(api, ['pages', 'articles'], {
  loggerPrefix: '[MyExtension]',
  allowLink: true,
  allowDuplicate: false,
  collectionIcons: {
    'pages': 'description',
    'articles': 'article'
  }
});

Available Shared Components

  • useItemSelector - Core composable with all functionality
  • ItemSelectorDrawer - Main selector interface
  • ItemSearchPanel - Advanced search with operators
  • FieldDisplay - Field value display component
  • UsagePopover - Shows item usage across collections

Configuration Options

interface ItemSelectorConfig {
  loggerPrefix?: string;           // Custom logging prefix
  allowLink?: boolean;             // Allow linking items
  allowDuplicate?: boolean;        // Allow duplicating items  
  defaultItemsPerPage?: number;    // Pagination size
  defaultLanguage?: string;        // Translation language
  collectionIcons?: Record<string, string>; // Custom icons
  fieldMappings?: Record<string, string>;   // Field name mappings
  debug?: boolean;                 // Enable debug logging
}

Full Documentation

πŸ“– Complete Shared Components Documentation - Detailed usage guide, examples, and API reference for extension developers.

Example Usage in LayoutBlocks Extension

<template>
  <ItemSelectorDrawer
    :open="itemSelector.isOpen.value"
    :collection="itemSelector.selectedCollection.value"
    :items="itemSelector.availableItems.value"
    :loading="itemSelector.loading.value"
    :logger-prefix="'[LayoutBlocks]'"
    @close="itemSelector.close"
    @confirm="handleItemsSelected"
  />
</template>

<script setup>
import { useItemSelector, ItemSelectorDrawer } from 'directus-extension-expandable-blocks/shared';

const itemSelector = useItemSelector(api, ['layouts'], {
  loggerPrefix: '[LayoutBlocks]',
  allowDuplicate: false
});
</script>

πŸ§ͺ Testing

# Run all tests (100% coverage)
npm run test -- --run

# Test with UI
npm run test:ui

# Coverage report
npm run test:coverage

# Type checking
npm run type-check

# Linting
npm run lint

Test Statistics

  • βœ… 470 unit tests - All passing
  • βœ… 100% coverage - Full test coverage
  • βœ… 0 TypeScript errors - Strict mode compliant
  • βœ… 0 ESLint errors - Clean code

πŸ“ Development

# Install dependencies (we use pnpm)
pnpm install

# Development mode
npm run dev

# Production build
npm run build

# Type checking
npm run type-check

# Create demo videos
npm run demo:product
npm run demo:highlights

Project Structure

expandable-blocks/
β”œβ”€β”€ config/           # Configuration files
β”‚   β”œβ”€β”€ scripts/      # Build scripts
β”‚   └── *.config.*    # Various configs
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ components/   # Vue components
β”‚   β”œβ”€β”€ composables/  # Vue composables
β”‚   β”œβ”€β”€ types/        # TypeScript types
β”‚   └── utils/        # Utilities
β”œβ”€β”€ test/             # Test files
└── wiki/             # Documentation

πŸ“š Documentation

Wiki Documentation

Visit our GitHub Wiki for:

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

πŸ“„ License

MIT License - see LICENSE file for details

πŸ™ Acknowledgments

Made with ❀️ for the Directus community

πŸ† Stats

  • 200+ commits of continuous improvement
  • 15+ components for modular architecture
  • 470 tests ensuring reliability
  • 0 errors in TypeScript and ESLint
  • 100% coverage for peace of mind

Ready for production use! πŸš€