Galleries (Assets)
Galleries are used to display assets such as images, videos and files in a grid format. They allow you to upload and delete assets, which can then be used in other views such as forms.
Defining Galleries
Galleries in Minoro are used to display and manage media assets like images, videos, audio files, and documents. You can define galleries within views to provide a visual interface for browsing, uploading, and managing your assets.
Let's create a simple view with a gallery that displays various types of assets:
ts
import { defineView } from 'minoro'
import { join } from 'path'
import { readdir } from 'fs/promises'
// export it so we can reuse it in forms
export assetsGalleryId = 'assets-gallery'
export const assetsView = defineView(
{ name: 'Assets', icon: 'lucide:folder' },
(view) => {
view.defineGallery({
id: assetsGalleryId,
assets: async ({ asset }) => {
const assetsDir = join(process.cwd(), 'assets')
const imageFiles = await readdir(join(assetsDir, 'images'), {
withFileTypes: true,
})
const your_domain = 'http://localhost:5000' // replace with your actual domain
return [
// Image assets from filesystem
...imageFiles.map((file) => {
return asset({
id: file.name,
name: file.name,
publicUrl: `${your_domain}/assets/images/${file.name}`,
type: 'image',
})
}),
// File asset
asset({
id: 'example.txt',
name: 'Document Example',
publicUrl: `${your_domain}/assets/files/example.txt`,
type: 'file',
}),
// Audio asset
asset({
id: 'audio-example',
name: 'Audio Example',
publicUrl: `https://example.com/audio.mp3`,
type: 'audio',
}),
// Video asset
asset({
id: 'video-example',
name: 'Video Example',
publicUrl: `https://example.com/video.mp4`,
type: 'video',
}),
]
},
/**
* `files` is an array of `File` objects that the user has selected to upload.
*/
handleUpload: async (files) => {
// Handle file uploads
console.log('Uploading files:', files)
// Implement your upload logic here
},
handleDelete: (asset) => {
// Handle asset deletion
console.log(`Deleting asset: ${asset.name}`)
// Implement your deletion logic here
},
handleRename: (asset, newName) => {
// Handle asset renaming
console.log(`Renaming asset: ${asset.name} -> ${newName}`)
// Implement your rename logic here
},
})
},
)Gallery Options
ts
type DefineGalleryOptions = {
/**
* A unique identifier for this gallery.
* This ID is used to reference the gallery from other parts of your application,
* such as asset fields in forms.
*/
id: string
/**
* A function that returns the assets to be displayed in the gallery.
* The function receives an `asset` helper to create properly typed asset objects.
* This function can be async and return a Promise.
*/
assets: (props: {
/** A helper function to create an asset with proper typing */
asset: (asset: Asset) => Asset
}) => MaybePromise<Asset[]>
/**
* Handler function called when files are uploaded to the gallery.
* Receives an array of File objects to process.
*/
handleUpload: (files: File[]) => MaybePromise<void>
/**
* Handler function called when an asset is deleted from the gallery.
* Receives the asset object that should be deleted.
*/
handleDelete: (asset: Asset) => MaybePromise<void>
/**
* Handler function called when an asset is renamed in the gallery.
* Receives the asset object and the new name.
*/
handleRename: (asset: Asset, newName: string) => MaybePromise<void>
}
type Asset = {
/** Unique identifier for the asset */
id: string
/** Display name for the asset */
name: string
/** Public URL where the asset can be accessed */
publicUrl: string
/** Type of the asset */
type: 'image' | 'video' | 'audio' | 'file'
}Using Gallery Assets in Forms
Galleries can be referenced from form fields to allow users to select assets. This is particularly useful for thumbnail images, document uploads, or any media selection:
ts
import { defineView } from 'minoro'
import { z } from 'zod'
import { assetsView, assetsGalleryId } from './assetsView' // Import the assets view we defined earlier
const PostSchema = z.object({
title: z.string(),
thumbnail: z.string()
})
// in a view ...
view.defineForm({
name: 'Create Post',
input: PostSchema,
jsonSchema: z.toJsonSchema(PostSchema),
render: () => ({
fields: {
thumbnail: {
type: 'asset',
fromView: assetsView.id,
fromGallery: 'assets-gallery',
},
},
}),
handler: async ({ fields }) => {
// The thumbnail field is a string that contains the asset ID
console.log('Selected thumbnail:', fields.thumbnail)
},
})