@glyphtek/unspecd
Version:
A declarative UI framework for building internal tools and dashboards with TypeScript. Create interactive tables, forms, and dashboards using simple specifications.
475 lines (428 loc) • 16.2 kB
text/typescript
/**
* Batch Order Status Updater - Advanced SmartTable Conceptual Example for Unspec'd Framework
*
* This example demonstrates how the editableTable content type could be extended to support
* advanced batch operations with multi-row selection. This is a conceptual design showing
* how the framework could evolve to handle complex real-world use cases.
*
* Key conceptual features demonstrated:
* - Multi-row selection with checkboxes (`selectionMode: 'multiple'`)
* - Batch table actions that operate on selected rows
* - Actions with associated input controls (`withInput` configuration)
* - Selection-aware action states (`requiresSelection: true`)
* - Comprehensive batch operation handling
*
* Real-world use case:
* E-commerce operations team needs to update order statuses in bulk after shipping
* events. Users can select multiple orders and change their status from "Processing"
* to "Shipped" in a single operation.
*/
import type { ToolSpec } from '../../src/lib/dsl-schema.js';
/**
* Interface for order data structure
*/
interface Order {
orderId: string;
customerName: string;
orderDate: string;
currentStatus: 'Pending' | 'Processing' | 'Shipped' | 'Delivered' | 'Cancelled';
orderValue: number;
items: number; // Number of items in the order
shippingAddress: string;
}
/**
* Interface for batch update parameters
*/
interface BatchUpdateParams {
selectedItems: Order[];
inputs: {
newStatus: string;
updateReason?: string;
};
}
/**
* Mock order data - realistic e-commerce order dataset
*/
const MOCK_ORDERS: Order[] = [
{
orderId: 'ORD-2024-001',
customerName: 'Alice Johnson',
orderDate: '2024-01-15T10:30:00Z',
currentStatus: 'Processing',
orderValue: 129.99,
items: 3,
shippingAddress: '123 Main St, Springfield, IL'
},
{
orderId: 'ORD-2024-002',
customerName: 'Bob Smith',
orderDate: '2024-01-15T14:22:00Z',
currentStatus: 'Processing',
orderValue: 79.50,
items: 2,
shippingAddress: '456 Oak Ave, Madison, WI'
},
{
orderId: 'ORD-2024-003',
customerName: 'Carol Davis',
orderDate: '2024-01-16T09:15:00Z',
currentStatus: 'Processing',
orderValue: 245.00,
items: 5,
shippingAddress: '789 Pine Rd, Austin, TX'
},
{
orderId: 'ORD-2024-004',
customerName: 'David Wilson',
orderDate: '2024-01-16T11:45:00Z',
currentStatus: 'Pending',
orderValue: 99.99,
items: 1,
shippingAddress: '321 Elm St, Seattle, WA'
},
{
orderId: 'ORD-2024-005',
customerName: 'Eva Martinez',
orderDate: '2024-01-16T16:30:00Z',
currentStatus: 'Processing',
orderValue: 189.75,
items: 4,
shippingAddress: '654 Maple Dr, Denver, CO'
},
{
orderId: 'ORD-2024-006',
customerName: 'Frank Brown',
orderDate: '2024-01-17T08:20:00Z',
currentStatus: 'Processing',
orderValue: 159.99,
items: 2,
shippingAddress: '987 Cedar Ln, Portland, OR'
},
{
orderId: 'ORD-2024-007',
customerName: 'Grace Lee',
orderDate: '2024-01-17T13:10:00Z',
currentStatus: 'Pending',
orderValue: 299.99,
items: 6,
shippingAddress: '147 Birch Way, Nashville, TN'
},
{
orderId: 'ORD-2024-008',
customerName: 'Henry Taylor',
orderDate: '2024-01-17T15:55:00Z',
currentStatus: 'Processing',
orderValue: 85.50,
items: 3,
shippingAddress: '258 Walnut St, Phoenix, AZ'
},
{
orderId: 'ORD-2024-009',
customerName: 'Ivy Chen',
orderDate: '2024-01-18T10:05:00Z',
currentStatus: 'Processing',
orderValue: 199.99,
items: 4,
shippingAddress: '369 Spruce Ave, Boston, MA'
},
{
orderId: 'ORD-2024-010',
customerName: 'Jack Robinson',
orderDate: '2024-01-18T12:40:00Z',
currentStatus: 'Pending',
orderValue: 119.99,
items: 2,
shippingAddress: '741 Poplar Rd, Miami, FL'
}
];
/**
* Complete tool specification for the Batch Order Status Updater.
* This tool demonstrates advanced table features for batch operations.
*
* NOTE: This is a conceptual example. The actual SmartTable component would need
* to be extended to support these advanced features like multi-row selection
* and batch actions with associated inputs.
*/
export const batchOrderUpdaterTool: ToolSpec = {
id: 'batch-order-updater',
title: 'Batch Order Status Updater',
// No global inputs needed - this tool focuses on table-level batch operations
// Advanced editableTable configuration with batch operation support
content: {
type: 'editableTable',
// Data loading configuration
dataLoader: {
functionName: 'getProcessableOrders'
},
// Advanced table configuration with batch operation features
tableConfig: {
// Unique identifier for each row
rowIdentifier: 'orderId',
// CONCEPTUAL FEATURE: Multi-row selection mode
// This would tell the SmartTable component to render checkboxes for each row
// and manage selection state across the entire table
// selectionMode: 'multiple', // Type assertion since this is conceptual
// Table column definitions (read-only for batch operations)
columns: [
{
field: 'orderId',
label: 'Order ID',
isSortable: true,
isEditable: false,
width: '120px'
},
{
field: 'customerName',
label: 'Customer',
isSortable: true,
isEditable: false,
width: '160px'
},
{
field: 'orderDate',
label: 'Order Date',
isSortable: true,
isEditable: false,
formatter: 'date',
width: '120px'
},
{
field: 'currentStatus',
label: 'Current Status',
isSortable: true,
isEditable: false,
width: '120px'
},
{
field: 'orderValue',
label: 'Value',
isSortable: true,
isEditable: false,
formatter: 'currency',
width: '100px'
},
{
field: 'items',
label: 'Items',
isSortable: true,
isEditable: false,
width: '80px'
}
],
/* CONCEPTUAL FEATURE: Advanced batch table actions
* These actions would be aware of selected rows and could have associated inputs
*
* batchActions: [
* {
* // Basic action configuration
* id: 'batchUpdateStatus',
* label: 'Set Status for Selected',
* variant: 'primary',
*
* // CONCEPTUAL FEATURE: Selection requirement
* // The action button would be disabled until at least one row is selected
* requiresSelection: true,
*
* // CONCEPTUAL FEATURE: Associated input controls
* // This allows the action to have input fields rendered alongside it
* withInput: {
* newStatus: {
* type: 'select',
* label: 'New Status',
* placeholder: 'Select new status...',
* options: [
* { value: 'Pending', label: 'Pending' },
* { value: 'Processing', label: 'Processing' },
* { value: 'Shipped', label: 'Shipped' },
* { value: 'Delivered', label: 'Delivered' },
* { value: 'Cancelled', label: 'Cancelled' }
* ],
* required: true
* },
* updateReason: {
* type: 'text',
* label: 'Reason (Optional)',
* placeholder: 'Enter reason for status change...',
* required: false
* }
* },
*
* // Function to call for the batch action
* functionName: 'batchUpdateOrderStatus',
*
* // CONCEPTUAL FEATURE: Confirmation for batch operations
* needsConfirmation: true,
* confirmationMessage: 'Are you sure you want to update the status of all selected orders? This action cannot be undone.'
* }
* ]
*/
// Standard pagination configuration
pagination: {
defaultPageSize: 10,
showPageSizeSelector: true,
pageSizeOptions: [5, 10, 20, 50]
},
// Default sorting by order date (newest first)
defaultSort: {
field: 'orderDate',
direction: 'desc'
}
}
},
// Mock function implementations for batch operations
functions: {
/**
* Loads orders that are available for status updates.
* In a real application, this might filter to only show orders in certain statuses.
*
* @param params - Query parameters for filtering, sorting, and pagination
* @returns Promise resolving to paginated order data
*/
getProcessableOrders: async (params: any): Promise<{ items: Order[]; totalItems: number }> => {
console.log('🔍 Loading processable orders with parameters:', params);
// Simulate API delay
await new Promise(resolve => setTimeout(resolve, 600));
// Filter to orders that can be updated (exclude already delivered/cancelled)
let processableOrders = MOCK_ORDERS.filter(order =>
!['Delivered', 'Cancelled'].includes(order.currentStatus)
);
// Apply sorting if specified
if (params.sortBy && params.sortDirection) {
processableOrders.sort((a, b) => {
const aValue = a[params.sortBy as keyof Order];
const bValue = b[params.sortBy as keyof Order];
let comparison = 0;
if (typeof aValue === 'string' && typeof bValue === 'string') {
comparison = aValue.localeCompare(bValue);
} else if (typeof aValue === 'number' && typeof bValue === 'number') {
comparison = aValue - bValue;
} else {
comparison = String(aValue).localeCompare(String(bValue));
}
return params.sortDirection === 'desc' ? -comparison : comparison;
});
}
// Calculate pagination
const page = params.page || 1;
const pageSize = params.pageSize || 10;
const startIndex = (page - 1) * pageSize;
const endIndex = startIndex + pageSize;
const paginatedOrders = processableOrders.slice(startIndex, endIndex);
console.log(`✅ Loaded ${paginatedOrders.length} of ${processableOrders.length} processable orders`);
return {
items: paginatedOrders,
totalItems: processableOrders.length
};
},
/**
* CONCEPTUAL FUNCTION: Performs batch status updates on selected orders.
* This demonstrates how a batch action function would receive both the selected
* items and the values from associated input controls.
*
* @param params - Batch update parameters including selected items and inputs
* @returns Promise resolving when batch update is complete
*/
batchUpdateOrderStatus: async (params: BatchUpdateParams): Promise<{ updated: number; errors: string[] }> => {
console.log('📦 Starting batch order status update:', params);
// Validate that we have selected items
if (!params.selectedItems || params.selectedItems.length === 0) {
throw new Error('No orders selected for batch update');
}
// Validate that we have a new status
if (!params.inputs || !params.inputs.newStatus) {
throw new Error('New status is required for batch update');
}
console.log(`🔄 Updating ${params.selectedItems.length} orders to status: ${params.inputs.newStatus}`);
if (params.inputs.updateReason) {
console.log(`📝 Update reason: ${params.inputs.updateReason}`);
}
// Simulate batch processing with realistic timing
await new Promise(resolve => setTimeout(resolve, 1500));
let updatedCount = 0;
const errors: string[] = [];
// Process each selected order
for (const order of params.selectedItems) {
try {
// Simulate some orders failing validation
if (order.currentStatus === 'Cancelled') {
errors.push(`Order ${order.orderId}: Cannot update cancelled orders`);
continue;
}
// Find and update the order in our mock data
const orderIndex = MOCK_ORDERS.findIndex(o => o.orderId === order.orderId);
if (orderIndex !== -1) {
const oldStatus = MOCK_ORDERS[orderIndex].currentStatus;
MOCK_ORDERS[orderIndex].currentStatus = params.inputs.newStatus as any;
console.log(` ✅ ${order.orderId}: ${oldStatus} → ${params.inputs.newStatus}`);
updatedCount++;
} else {
errors.push(`Order ${order.orderId}: Order not found`);
}
// Simulate per-item processing time
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
errors.push(`Order ${order.orderId}: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
const result = { updated: updatedCount, errors };
console.log('🎯 Batch update completed:', result);
// Show user-friendly results
if (result.updated > 0) {
console.log(`✅ Successfully updated ${result.updated} order(s) to "${params.inputs.newStatus}"`);
}
if (result.errors.length > 0) {
console.warn(`⚠️ ${result.errors.length} order(s) could not be updated:`);
result.errors.forEach(error => console.warn(` - ${error}`));
}
return result;
},
/**
* Helper function to get statistics about orders by status.
* This could be used for additional dashboard features.
*
* @param params - Query parameters (unused in this mock)
* @returns Promise resolving to status statistics
*/
getOrderStatusStats: async (params: any): Promise<Record<string, number>> => {
console.log('📊 Calculating order status statistics...');
await new Promise(resolve => setTimeout(resolve, 300));
const stats: Record<string, number> = {};
MOCK_ORDERS.forEach(order => {
stats[order.currentStatus] = (stats[order.currentStatus] || 0) + 1;
});
console.log('📈 Order status statistics:', stats);
return stats;
}
}
};
/**
* CONCEPTUAL DESIGN NOTES:
*
* This example demonstrates how the Unspec'd framework could be extended to support
* advanced batch operations. The key conceptual features are:
*
* 1. SELECTION MODE:
* - `selectionMode: 'multiple'` enables checkbox rendering for each row
* - The SmartTable component would track selected state internally
* - Selection state would persist across pagination and sorting
*
* 2. BATCH ACTIONS:
* - `batchActions` array defines actions that operate on selected rows
* - `requiresSelection: true` disables the action until rows are selected
* - Actions can have associated input controls via `withInput`
*
* 3. BATCH FUNCTION INTERFACE:
* - Functions receive `{ selectedItems: Item[], inputs: Record<string, any> }`
* - This provides both the selected data and values from action inputs
* - Functions can return detailed results including success/error counts
*
* 4. USER EXPERIENCE:
* - Users see checkboxes next to each row for selection
* - Batch action buttons are disabled until selections are made
* - Input controls appear alongside action buttons
* - Confirmation dialogs prevent accidental batch operations
* - Progress indicators show batch operation status
*
* This design would enable powerful batch operations while maintaining the
* declarative simplicity that makes Unspec'd easy to use.
*/