or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdfile-editor.mdfile-management.mdindex.mdmodal-management.mdpanel-management.mdplugin-integration.md

file-management.mddocs/

0

# File Management

1

2

Handle file selection, metadata editing, and file operations within the dashboard.

3

4

## Capabilities

5

6

### Add Files

7

8

Add files to the uploader with automatic metadata detection and validation.

9

10

```typescript { .api }

11

/**

12

* Add files to the uploader

13

* Handles file validation, metadata extraction, and error handling

14

* @param files - Array of File objects to add

15

*/

16

addFiles(files: File[]): void;

17

```

18

19

**Usage Examples:**

20

21

```typescript

22

import Dashboard from "@uppy/dashboard";

23

24

const dashboard = uppy.getPlugin("Dashboard") as Dashboard;

25

26

// Add files from input element

27

const fileInput = document.getElementById("file-input") as HTMLInputElement;

28

fileInput.addEventListener("change", (event) => {

29

const files = Array.from(event.target.files || []);

30

dashboard.addFiles(files);

31

});

32

33

// Add files from drag and drop

34

function handleDrop(event: DragEvent) {

35

event.preventDefault();

36

const files = Array.from(event.dataTransfer?.files || []);

37

dashboard.addFiles(files);

38

}

39

40

// Add files programmatically

41

async function addFromCustomSource() {

42

const customFiles = await fetchFilesFromAPI();

43

const fileObjects = customFiles.map(data => new File([data.blob], data.name));

44

dashboard.addFiles(fileObjects);

45

}

46

```

47

48

**Behavior:**

49

- Creates file descriptors with source, name, type, and data

50

- Extracts relative path metadata for directory uploads

51

- Validates files against Uppy restrictions

52

- Logs file addition events

53

- Handles and logs any validation errors

54

55

### Save File Card

56

57

Save metadata for a specific file and close the file card interface.

58

59

```typescript { .api }

60

/**

61

* Save file metadata

62

* Updates file metadata and closes file card interface

63

* @param meta - Metadata object to save

64

* @param fileID - ID of the file to update

65

*/

66

saveFileCard(meta: Meta, fileID: string): void;

67

```

68

69

**Usage Examples:**

70

71

```typescript

72

// Save file metadata from form

73

function saveFileMetadata(fileId: string, formData: FormData) {

74

const metadata = {

75

name: formData.get("title") as string,

76

caption: formData.get("caption") as string,

77

altText: formData.get("altText") as string

78

};

79

80

dashboard.saveFileCard(metadata, fileId);

81

}

82

83

// Save metadata with validation

84

function saveWithValidation(fileId: string, metadata: any) {

85

// Validate required fields

86

const requiredFields = uppy.opts.restrictions.requiredMetaFields || [];

87

const missing = requiredFields.filter(field => !metadata[field]);

88

89

if (missing.length > 0) {

90

console.error("Missing required fields:", missing);

91

return;

92

}

93

94

dashboard.saveFileCard(metadata, fileId);

95

}

96

97

// Programmatic metadata saving

98

uppy.on("file-added", (file) => {

99

// Auto-populate metadata for certain file types

100

if (file.type?.startsWith("image/")) {

101

const autoMetadata = {

102

altText: `Image: ${file.name}`,

103

category: "image"

104

};

105

dashboard.saveFileCard(autoMetadata, file.id);

106

}

107

});

108

```

109

110

**Behavior:**

111

- Calls `uppy.setFileMeta()` to update file metadata

112

- Calls `toggleFileCard(false, fileID)` to close the file card

113

- Updates dashboard state to hide file card interface

114

115

### File Card Management

116

117

Control the display and interaction with individual file metadata cards.

118

119

```typescript { .api }

120

/**

121

* Toggle file card visibility for specific file

122

* @param show - Whether to show or hide the file card

123

* @param fileID - ID of the file to show card for

124

*/

125

private toggleFileCard(show: boolean, fileID: string): void;

126

```

127

128

**File Card State:**

129

130

```typescript { .api }

131

/**

132

* File card related state properties

133

*/

134

interface FileCardState {

135

/** File ID for which card is shown, null if no card is active */

136

fileCardFor: string | null;

137

/** Whether file editor is currently shown */

138

showFileEditor: boolean;

139

/** Active overlay type */

140

activeOverlayType: 'FileCard' | 'FileEditor' | null;

141

}

142

```

143

144

### Metadata Fields Configuration

145

146

Configure metadata fields for file information collection.

147

148

```typescript { .api }

149

/**

150

* Metadata field configuration

151

*/

152

interface MetaField {

153

/** Unique field identifier */

154

id: string;

155

/** Display name for the field */

156

name: string;

157

/** Placeholder text for input field */

158

placeholder?: string;

159

/** Custom render function for field */

160

render?: (field: FieldRenderOptions, h: PreactRender) => VNode<any>;

161

}

162

163

/**

164

* Field render options passed to custom render functions

165

*/

166

interface FieldRenderOptions {

167

/** Current field value */

168

value: string;

169

/** Function to update field value */

170

onChange: (newVal: string) => void;

171

/** CSS classes for field styling */

172

fieldCSSClasses: { text: string };

173

/** Whether field is required */

174

required: boolean;

175

/** Form identifier */

176

form: string;

177

}

178

```

179

180

**Metadata Configuration Examples:**

181

182

```typescript

183

// Static metadata fields

184

uppy.use(Dashboard, {

185

metaFields: [

186

{

187

id: "title",

188

name: "Title",

189

placeholder: "Enter file title"

190

},

191

{

192

id: "description",

193

name: "Description",

194

placeholder: "Describe this file"

195

},

196

{

197

id: "tags",

198

name: "Tags",

199

placeholder: "Comma-separated tags"

200

}

201

]

202

});

203

204

// Dynamic metadata fields based on file type

205

uppy.use(Dashboard, {

206

metaFields: (file) => {

207

const baseFields = [

208

{ id: "title", name: "Title", placeholder: "Enter title" }

209

];

210

211

if (file.type?.startsWith("image/")) {

212

return [

213

...baseFields,

214

{ id: "altText", name: "Alt Text", placeholder: "Describe the image" },

215

{ id: "caption", name: "Caption" }

216

];

217

} else if (file.type?.startsWith("video/")) {

218

return [

219

...baseFields,

220

{ id: "transcript", name: "Transcript" },

221

{ id: "duration", name: "Duration" }

222

];

223

}

224

225

return baseFields;

226

}

227

});

228

229

// Custom field rendering

230

uppy.use(Dashboard, {

231

metaFields: [

232

{

233

id: "priority",

234

name: "Priority",

235

render: (field, h) => {

236

return h('select', {

237

value: field.value,

238

onChange: (e) => field.onChange(e.target.value),

239

className: field.fieldCSSClasses.text

240

}, [

241

h('option', { value: '' }, 'Select priority'),

242

h('option', { value: 'low' }, 'Low'),

243

h('option', { value: 'medium' }, 'Medium'),

244

h('option', { value: 'high' }, 'High')

245

]);

246

}

247

}

248

]

249

});

250

```

251

252

### File Events

253

254

Events related to file management operations.

255

256

```typescript { .api }

257

/**

258

* File management events

259

*/

260

interface DashboardFileEvents<M extends Meta, B extends Body> {

261

/** Emitted when file card editing starts */

262

"dashboard:file-edit-start": (file?: UppyFile<M, B>) => void;

263

/** Emitted when file card editing completes */

264

"dashboard:file-edit-complete": (file?: UppyFile<M, B>) => void;

265

}

266

```

267

268

**Event Usage Examples:**

269

270

```typescript

271

// Track file editing

272

uppy.on("dashboard:file-edit-start", (file) => {

273

console.log(`Started editing: ${file?.name}`);

274

// Show editing indicators, disable other actions, etc.

275

});

276

277

uppy.on("dashboard:file-edit-complete", (file) => {

278

console.log(`Finished editing: ${file?.name}`);

279

// Hide editing indicators, enable other actions, etc.

280

});

281

282

// Auto-save drafts during editing

283

let editingFile: UppyFile | null = null;

284

uppy.on("dashboard:file-edit-start", (file) => {

285

editingFile = file;

286

startAutoSave();

287

});

288

289

uppy.on("dashboard:file-edit-complete", () => {

290

editingFile = null;

291

stopAutoSave();

292

});

293

294

function startAutoSave() {

295

const interval = setInterval(() => {

296

if (editingFile) {

297

// Save current form state as draft

298

saveDraft(editingFile.id);

299

}

300

}, 30000); // Save every 30 seconds

301

}

302

```

303

304

### File Validation

305

306

Built-in file validation and restriction handling.

307

308

```typescript { .api }

309

/**

310

* File validation is handled by Uppy core

311

* Dashboard respects these restriction options:

312

*/

313

interface UppyRestrictions {

314

/** Allowed file types (MIME types or extensions) */

315

allowedFileTypes?: string[];

316

/** Maximum number of files */

317

maxNumberOfFiles?: number;

318

/** Maximum file size in bytes */

319

maxFileSize?: number;

320

/** Minimum file size in bytes */

321

minFileSize?: number;

322

/** Required metadata fields */

323

requiredMetaFields?: string[];

324

}

325

```

326

327

**Validation Examples:**

328

329

```typescript

330

// Configure file restrictions

331

const uppy = new Uppy({

332

restrictions: {

333

allowedFileTypes: ['.jpg', '.jpeg', '.png', '.gif'],

334

maxNumberOfFiles: 5,

335

maxFileSize: 10 * 1024 * 1024, // 10MB

336

requiredMetaFields: ['title', 'description']

337

}

338

});

339

340

// Handle validation errors

341

uppy.on('restriction-failed', (file, error) => {

342

console.error(`File ${file?.name} rejected:`, error.message);

343

// Show user-friendly error message

344

showErrorMessage(error.message);

345

});

346

347

// Custom validation

348

function validateFileContent(file: File): Promise<boolean> {

349

return new Promise((resolve) => {

350

const reader = new FileReader();

351

reader.onload = (e) => {

352

// Custom validation logic

353

const content = e.target?.result;

354

const isValid = performCustomValidation(content);

355

resolve(isValid);

356

};

357

reader.readAsArrayBuffer(file);

358

});

359

}

360

```

361

362

### File Processing

363

364

Integration with file processing and transformation.

365

366

```typescript { .api }

367

/**

368

* File processing integration points

369

*/

370

interface FileProcessing {

371

/** Generate thumbnails for files */

372

handleRequestThumbnail(file: UppyFile): void;

373

/** Cancel thumbnail generation */

374

handleCancelThumbnail(file: UppyFile): void;

375

/** Wait for thumbnails before upload */

376

waitForThumbnailsBeforeUpload?: boolean;

377

}

378

```

379

380

**Processing Examples:**

381

382

```typescript

383

// Configure thumbnail generation

384

uppy.use(Dashboard, {

385

thumbnailWidth: 300,

386

thumbnailHeight: 300,

387

thumbnailType: 'image/jpeg',

388

waitForThumbnailsBeforeUpload: true

389

});

390

391

// Custom file processing

392

uppy.on('file-added', async (file) => {

393

if (file.type?.startsWith('image/')) {

394

// Extract EXIF data

395

const exifData = await extractExifData(file.data);

396

uppy.setFileMeta(file.id, {

397

...file.meta,

398

exif: exifData,

399

location: exifData.gps

400

});

401

}

402

});

403

404

// Process files before upload

405

uppy.on('preprocess-progress', (file, progress) => {

406

console.log(`Processing ${file.name}: ${progress.uploadProgress}%`);

407

});

408

409

uppy.on('preprocess-complete', (file) => {

410

console.log(`Finished processing: ${file.name}`);

411

});

412

```

413

414

### Drag and Drop Integration

415

416

Built-in drag and drop functionality for file selection.

417

418

```typescript { .api }

419

/**

420

* Drag and drop event handlers

421

*/

422

interface DragDropHandlers {

423

/** Handle drag over events */

424

onDragOver?: (event: DragEvent) => void;

425

/** Handle drag leave events */

426

onDragLeave?: (event: DragEvent) => void;

427

/** Handle drop events */

428

onDrop?: (event: DragEvent) => void;

429

}

430

```

431

432

**Drag and Drop Examples:**

433

434

```typescript

435

// Custom drag and drop behavior

436

uppy.use(Dashboard, {

437

onDragOver: (event) => {

438

console.log('Files being dragged over dashboard');

439

// Add visual feedback

440

event.currentTarget.classList.add('drag-active');

441

},

442

443

onDragLeave: (event) => {

444

console.log('Drag left dashboard area');

445

// Remove visual feedback

446

event.currentTarget.classList.remove('drag-active');

447

},

448

449

onDrop: (event) => {

450

console.log('Files dropped on dashboard');

451

// Custom drop handling

452

const files = Array.from(event.dataTransfer?.files || []);

453

// Additional processing before adding files

454

files.forEach(file => preprocessFile(file));

455

}

456

});

457

458

// Drag and drop validation

459

function validateDropEvent(event: DragEvent): boolean {

460

const items = event.dataTransfer?.items;

461

if (!items) return false;

462

463

// Check if all items are files

464

for (let i = 0; i < items.length; i++) {

465

if (items[i].kind !== 'file') {

466

return false;

467

}

468

}

469

470

return true;

471

}

472

```