@spatie/blender-media

3.3.4 • Public • Published

Blender Media

Software License Build Status

The media uploader and manager for Blender, our CMS.

Installation

The blender-media can be installed from npm.

yarn add @spatie/blender-media

blender-media also requires you to install vue@'^2.0.0', lodash@'^4.0.0', and spatie-dom@'^1.0.0':

yarn add vue@'^2.0.0' lodash@'^4.0.0' spatie-dom@'^1.0.0'

Example

This repository contains a dummy version of the media component which can be used for development. It can be built and served on http://localhost:4000 with the following command:

npm run example

script will also watch for JS and CSS file changes.

Usage

In order to use the media component, you need to register it first. You can register it globally, or inside a Vue component:

import Media from '@spatie/blender-media';
import Vue from 'vue';

// Global registration...
Vue.component('media', Media);

// ...or scoped to your view model
new Vue({
    el: 'body',
    components: {
        Media,
    },
});

After registering the component, it can be used in your html:

<media
    collection="images"
    type="images"
    upload-url="/upload"
    :model="{ name: 'MyModel', id: 1 }"
    :initial='[{
        "id": 1,
        "name": "image_1",
        "fileName": "image_1.jpeg",
        "customProperties": {},
        "orderColumn": 1,
        "thumbUrl": "/media/image_1.jpeg",
        "originalUrl": "/media/image_1.jpeg",
        "collection": "images"
    }]'
    :data="{ locales: ['nl', 'en'] }"
></media>

If you want to use a media component outside of a Vue instance, this package provides a mount function. The mount function will replace every element that matches a given selector with a media component. The element should contain props just like you'd pass them with Vue.

import { mount } from '@spatie/blender-media';

export default function init() {
    mount('.js-media');
}
<div
    class="js-media"
    collection="images"
    type="images"
    upload-url="/upload"
    :model="{ name: 'MyModel', id: 1 }"
    :initial="[]"
    :data="{ locales: ['nl', 'en'] }"
></div>

Media Objects

Media objects look like the original model from the Laravel package.

interface Media {
    id: number;
    name: string;
    fileName: string;
    customProperties: any;
    orderColumn: number;
    thumbUrl: string;
    originalUrl: string;
    colection: string;
}

Component Properties

The component requires a few properties in order to handle the collection and uploads.

type: string

The type of component that should be rendered (see Types for more details).

upload-url: string

The URL that newly uploaded media will be posted to. This endpoint should handle the upload, and return a Media object.

model: { name: string, id: number }

The fully qualified class name of the model that the media is related too and it's ID.

initial: Array<Media>

The media items that are already in the collection.

data: any

Custom data that can be used in the media editor, e.g. a list of available locales so the media item can be toggled per language.

Types

Each media instance requires a type. A type determines the setup of the media component. Types are registered via the registerType method, which takes a name and options as arguments.

import { registerType } from 'blender-media';

registerType('images', {
    accepts: '.jpg,.gif',
    multiple: true,
    editor: 'basic',
});

The package ships with image, images, download and downloads types. Types have to be registered before any media component gets rendered. If you register a type with the same name twice, only the last registered type will be used.

Type Options

accepts: ?string = null

The file types that the uploader will accept. If accepts is null, all file types will be accepted. Available formats of the string are described in Dropzone's documentation.

multiple: bool = true

Determines whether multiple files can be uploaded to a collection.

editor: string = 'basic'

The name of the registered editor to be rendered inside the component. See Editors for a more detailed explanation.

extend: ?string = null

Extend an existing type. Creates a new type, based on an existing type. Other options will overwrite the existing type's options.

Editors

Every media row has an editor in the section between the thumbnail and the remove button. The default editor—named basic—has in input to rename the media object.

Available Editors

This package ships with 4 editors:

  • basic: A simple name field
  • sizePicker: A name field and a size dropdown with 4 options (full width, 2/3, 1/2, 1/3)
  • toggleLocales: A name field and a toggle for every language, to enable or disable the image. Use this when you need a different image per language
  • translatedDescription: A description field for every language. Use this when the image is the same per language, but needs a translated caption

Editors come as-is, there's no extra configuration. If you need a variation, for example different widths in the sizePicker, copy the source code and register your own project-specific editor.

Project-Specific Editors

Editors are Vue components with an editor mixin. The mixin takes care of the boilerplate that a custom editor requires.

  • It adds media and data props
  • It provides convenience methods for dealing with custom properties
  • It provides convenience methods for UI actions

The editor mixin allows you to set two new options: customProperties and translatableCustomProperties. They both take a name as key, and a default value as property value.

import editor from './editor';

export default {
    mixins: [editor],
    
    customProperties: {
        sku: '',
    },
    
    
    translatableCustomProperties: {
        description: '',
    },
    
    computed: {
        descriptions() {
            return this.customProperty('description');
        },
    },
    
    methods: {
        updateDescription(locale, value) {
            this.setTranslation('description', locale, value);
        },
    },
};

Editors can then be registered with the registerEditor method. Like types, editors have to be registered before any media component gets rendered. If you register an editor with the same name twice, only the last registered editor will be used.

import { registerEditor } from 'blender-media';
import MyEditor from './editors/MyEditor';

registerEditor('myEditor', MyEditor);

Note that editors should be contained in a .vue file since they also require a template! Browse the existing editors for some examples.

Editor Methods

customProperty(key: string, fallback: any = null)

Return the value of a custom property. If the property isn't defined, return the fallback.

// { customProperties: { foo: 'bar' } }

this.customProperty('foo');
// > 'bar'

this.customProperty('baz', 'qux');
// > 'qux'
setCustomProperty(key: string, value: any)

Set a custom property.

// { customProperties: {} }

this.updateCustomProperty('locales', { nl: true, en: false });

// { customProperties: { locales: { nl: true, en: false } } }
getTranslation(key: string, locale: string)

Get a translated custom property.

// { customProperties: { foo: { en: 'bar' } } }

this.getTranslation('foo', 'en');
// > 'bar'
setTranslation(key: string, locale: string, value: any)

Set a translated custom property's translation.

// { customProperties: { foo: { en: 'bar' } } }

this.setTranslation('foo', 'en', 'baz');

// { customProperties: { foo: { en: 'baz' } } }

Contributing

Since this is an internal project, we don't accept pull requests at this time.

License

The MIT License (MIT). Please see License File for more information.

Example images provided by Unsplash.

Dependents (0)

Package Sidebar

Install

npm i @spatie/blender-media

Weekly Downloads

4

Version

3.3.4

License

MIT

Last publish

Collaborators

  • spatie