@teamleaf-js/medialibrary-ui
v0.1.3
Published
<p align="center"> <a href="https://senses.co.uk" target="_blank"> <img src="https://github.com/Senses-Web-Solutions/meta/blob/main/art/senses-logo.png?raw=true"> </a> </p>
Downloads
3
Readme
senses-medialibrary-ui
A cross-project frontend for media library UI.
Usage
MediaLibrary.vue is the main component. An example is viewable in App.vue.
The Media Library requires a few props to function:
Url
Required
Note This prop is non-reactive. If you change the instance after the media library loads, it will not update.
The url function generates the URL that the media library will use to retrieve files from your API.
The URL should be returned as a string. The function is passed the previousResponse (can be null), sort as a string and filters as an object.
You can use this information to manipulate the URL. If sort or filters are updated, the media library will perform a fresh load.
Note: Your API response should return your files in an object with a data key. The Laravel paginator already does this.
Example url function
const url = (previousResponse = null, sort = null, filters = null) => {
// If the previous response is not set, we're on the first page. Supply a base URL.
// Otherwise, use the next_page_url from the past response.
const baseUrl = previousResponse ? previousResponse.next_page_url : 'http://teamleaf.harry/api/v2/files-test';
const urlOb = new URL(baseUrl);
// Set the sort param in the URL
urlOb.searchParams.set('sort', sort);
if (filters) {
// Loop through the filter groups
Object.keys(filters).forEach((filterGroupKey) => {
const selectedValues = [];
const filterGroupValues = filters[filterGroupKey];
// Loop through the values in the filter groups
Object.keys(filterGroupValues).forEach((filterKey) => {
if (filterGroupValues[filterKey]) {
selectedValues.push(filterKey);
}
});
// Set the URL
if (selectedValues.length) {
urlOb.searchParams.set(`filter[${filterGroupKey}]`, selectedValues.join(','));
} else {
urlOb.searchParams.delete(`filter[${filterGroupKey}]`);
}
});
}
// Return the URL as a string.
return urlOb.toString();
};Filters
Required
This prop provides the data to generate the filter options in the sidebar.
The below code will create filters that look like this:
Type
[] DOC
[] IMG
const filters = [
{
title: 'Type',
key: 'service_type_id',
options: {
pdf: 'PDF',
doc: 'DOC',
img: 'IMG',
},
},
]Upload
Required
Note This prop is non-reactive. If you change the instance after the media library loads, it will not update.
This prop is a function that allows you to handle file uploads. The file will be supplied as the first (and only) param.
The function must return a promise.
const upload = (file) => {
const formData = new FormData();
formData.set('file', file);
return axios.post('/api/v2/files', formData); // returns a Promise
};Map
Optional
Note This prop is non-reactive. If you change the instance after the media library loads, it will not update.
The map function handles mapping each individual file to a format the media library is able to use.
The required format is:
interface File {
name: string;
size: number; // in Megabytes
created_at: string; // Format doesn't matter. Provide it in a nice display format.
preview_url: string; // A thumbnail size image.
download_url: string; // The full size file
extension: string; // the file extension (png/jpg/pdf etc)
creator: {
full_name: string;
}
}Example:
const map = (file) => {
file.size /= 1000000; // mb
file.created_at = format(
parse(file.created_at, 'yyyy-MM-dd HH:mm:ss', new Date()),
'dd/MM/yyyy'
);
return file;
};Axios
Optional
Note This prop is non-reactive. If you change the instance after the media library loads, it will not update.
You can optionally pass in an instance of axios which can be preconfigured to work with your API's authentication. The media library will use that instance rather than the default axios instance.
Slots
Info
The info slot allows you to display more information about a file below its attributes. This is good for custom data.
The file will be passed as a slot prop. As well as close, which is a function you can call to close the modal.
Form
The form slot allows you to add an edit form to the media library. You need to register a callback to tell the media library that you're done updating, as well as register a hook to fire your save event when the media library's save button is clicked.
<!-- Inside <MediaLibrary> -->
<template #form="{ file, close, onSave, afterSave }">
<file-form :file="file" :close="close" :on-save="onSave" :after-save="afterSave" />
</template>
<!-- Inside <FileForm> -->
<script>
props: {
onSave: {
type: Function,
required: true
},
afterSave: {
type: Function,
required: true
}
}
mounted() {
// ...
// The media library will call your submit function
// when the user hits the save button.
this.onSave(this.submit)
},
methods: {
submit() {
axios.post(/*..*/, { /*...*/ }).then(() => {
// Return the modified version of the file back
// to the media library.
this.afterSave(file);
})
}
},
</script>
unplugin
This package is using unplugin auto import for both Vue components and certain js libraries, just means you don't have to import Vue components, Vue functions or @vueuse/core functions directly, it'll be done for you. Configurable in vite.config.js. Installed purely for speed of development.
It won't affect usage.
