netresearch/assetpicker

A free asset or file picker with abstraction layer allowing several adapters like GitHub, EnterMediaDB, Amazon S3, Google Drive, Dropbox etc.

Installs: 131

Dependents: 1

Suggesters: 0

Security: 0

Stars: 22

Watchers: 7

Forks: 4

Open Issues: 0

Language:JavaScript

1.3.4 2016-10-20 18:45 UTC

This package is auto-updated.

Last update: 2024-10-19 09:19:29 UTC


README

AssetPicker is a free asset or file picker designed to be easily included into web application interfaces. It has a file abstraction layer allowing adapters to connect to any remote storage, be it cloud storages like Amazon S3, Google Drive or Dropbox or assets from a custom web application server. In opposite to other file managers or pickers, AssetPicker is suitable for hierarchical as well as associative file storages.

Try the demo

Manual

How it works

AssetPicker consists of two bundles: The picker (AssetPicker in picker.js) and the app (AssetPickerApp in app.js). The picker is a lightweight script without any dependencies that will add it's listeners to elements matching the configured selector. When one of these was clicked it'll setup a modal from a template, inject the styles for it into the header (both, template and style are customizable), loads the app into and iframe in the modal and passes it the config. The communication with the iframe is done with cross window messaging so it is CORS aware.

The app provides the actual user interface and functionality. It has a default configuration which will be merged with the configuration passed to the picker. The key part of this configuration are the storages, which will be mounted as top level entries on the navigation bar (and on the start screen when you use multiple storages). Each of the storages can have a separate configuration and use other adapters. It reads the storages and adapters from the config and loads the adapter source scripts into the iframe, when they are used by one of the storages - thus unneeded storages don't bloat the size of the app.

Both, app and adapters are Vue.js components which allows for a modern and maintainable application structure.

Unless you want to customize the app itself, the picker will be the only API you'll have to use.

Browser compatibility

Modern browsers (IE >= 10) - tested in Chrome 53, Firefox 35 - 47, IE 10 - 11, Edge

Installation

CDN

The easiest way to integrate AssetPicker is to use include the picker script from a CDN:

<script src="https://cdn.rawgit.com/netresearch/assetpicker/1.3.4/dist/js/picker.js"></script>

<script>
    new AssetPicker(config, options);
</script>

<button rel="assetpicker">Select a file</button>

It doesn't matter if you include the script in head or at footer - it will register on dom ready anyway.

If you don't want to use a CDN, you can download the dist directory to a web server and include the picker-min.js from there (the other files from dist must be available).

Docker

The best way to host AssetPicker on your own is to use it with docker or even easier with docker-compose:

git clone https://github.com/netresearch/assetpicker.git
cd assetpicker
docker-compose up -d

If you want to use the built in proxy, you'll need to run the following once:

docker exec -tiu www-data assetpicker_php '/bin/bash'
composer install

Composer

You can include AssetPicker into your PHP application easily with composer (but you might need to make it's directory within the vendor directory available by linking it to an adequate public folder):

composer require netresearch/assetpicker
ln -s vendor/netresearch/assetpicker web/assetpicker

Symfony Application

Feel free to use the AssetPicker Bundle.

npm

You can happily install AssetPicker using npm:

npm install --save assetpicker

but you'll need to tell it the source of the app (please open an issue or PR if you find a way to workaround this):

var AssetPicker = require('assetpicker');
new AssetPicker(
    config,
    {
        modal: {
            src: 'node_modules/assetpicker/dist'
        }
    }
);

See more on setting AssetPicker with npm below.

Configuration

The AssetPicker constructor takes two arguments: config (required) and options (both of type object). config is the configuration that will be passed to the AssetPickerApp and options can contain options for the picker and the modal.

new AssetPicker(config); /* or */ new AssetPicker(config, options);

Feel free to play around with some of the options on the demo page.

config

options

Buttons

Data attributes on the buttons can control what may be picked and what should happen after something was picked.

<button
    rel="assetpicker" 
    data-limit="0" 
    data-exts="jpeg,jpg,png">Select multiple images</button>

API

The AssetPicker provides a basic API including some methods and some events.

Methods

Events

The picker provides a simple events API with some events - the listeners will always be bound to the picker instance and receive arguments depending on the event. Register your events as follows:

var picker = new AssetPicker(config);
picker.on('pick', function(picked) {
  console.log(picked, this.element);
});

Adapters

Google Drive

The Google Drive adapter utilizes the Google API to retrieve assets from the users drive account, which he will have to pick when he has multiple accounts. For this to work you'll need to register your project on Google API Console and activate the Drive API for it. After that you'll need to create an API key and an OAuth client ID in the credentials area of the project.

Authentication

The Google Drive adapter uses Google Sign-In for Web - this means that your users will have to authenticate with Google and authorize AssetPicker in a pop up window. AssetPicker will then receive a short-lived token to access the API for the user - no further information will be stored by AssetPicker. Thus it will likely occur that AssetPicker will have to reopen this window when the token expired - as pop up blockers will likely block automatic pop ups your users will have to click a button manually to do that until we found a better solution.

Configuration

new AssetPicker({
    storages: {
        drive: {
            adapter: 'googledrive',
            // OAuth client id from API console, required
            client_id: 'xxx',
            // API key from API console, required
            api_key: 'xxx',
            // Google Apps Domain to which users must belong, optional
            hosted_domain: 'mycompany.com',
            // Requests to Google APIs are limited and AssetPicker requires some
            // of them to show the doc tree - use this to force start new requests
            // at least this amount of milliseconds after the last ones
            // (defaults for Google Drive adapter is 100), optional
            http: {
              throttle: 250
            }
        }
    }
});

GitHub

The GitHub adapter utilizes the GitHub API to provide files and folders in a GitHub repository to AssetPicker. For this to work, you either need an GitHub API token or the user will need a GitHub account.

Authentication

In case you don't provide an API token, the user will be asked for his GitHub credentials. Those credentials will then only be used to create a personal access token which will be stored in his browsers local storage. From then on this personal token will be used for authentication with GitHub. The users login and password won't be stored in any way.

Configuration

new AssetPicker({
    storages: {
        somegithubrepo: {
            adapter: 'github',
            // Owner of the repository, required:
            username: 'netresearch',
            // The repository name, required:
            repository: 'assetpicker'
        }
    },
    github: {
        // Token for authentication with GitHub API, optional (see above):
        token: '29782sdwhd2eu2e823jdjhw9832ijs92'
    }
});

EnterMediaDB

The EnterMediaDB adapter utilizes the EnterMediaDB API to provide categories and assets to AssetPicker.

Authentication

Authentication with EnterMediaDB API is session based and requires the user to provide his credentials to authenticate with the API. Thus you have to make sure, that the users using AssetPicker have the permissions to use the API inside EnterMediaDB.

Configuration

EnterMediaDB currently doesn't provide CORS support and thus, if AssetPicker is served from a different host, protocol or port than EnterMediaDB, you'll likely need a proxy.

new AssetPicker({
    storages: {
        somegithubrepo: {
            adapter: 'entermediadb',
            // URL to the catalogue, required:
            url: 'http://em9.entermediadb.org/openinstitute',
            // Proxy is likely required 
            proxy: true
        }
    }
});

Register your own adapter

Adapters are actually vue components which's template will be rendered in the navigation bar. Loading of items is completely controlled by events. Have a look at the existing adapters to see details.

The standard way to do this, is to create a standalone script, that contains the adapter and reference it in the config. The script is required as standalone because it won't be loaded in the same window as where the picker is included but from an iframe.

The following example shows a basic adapter, loading a hierarchical structure from an endpoint:

https://myapp.example.com/myadapter.js

AssetPickerAdapterMine = {
    events: {
        'load-items': function(tree) {
            this.http.get(this.config.url + '/files/' + (tree.item ? tree.item.id : '')).then(
                function(response) {
                    tree.items = response.data.map(this.createItem);
                }
            );
        }
    }
}

https://myapp.example.com/index.html (where the picker is included)

new AssetPicker({
    storages: {
        mystorage: {
            adapter: 'mine',
            url: 'https://example.com'
        }
    },
    adapters: {
        mine: 'https://myapp.example.com/myadapter.js'
    }
});

Also you can add custom adapters when you have installed the App with npm - see below for an example.

Customize the app

Apart from simply forking this repository, you can also include the app into your project. For this you'll need a npm app built with browserify to customize the app. AssetPickerApp is using [Vue.js] - so you might consider reading it's docs before.

  1. Initialize the app

    npm init
    npm install --save assetpicker
  2. Customize the AssertPickerApp or it's compontents

    src/app.js:

    var Storage = require('assetpicker/src/js/app/components/storage');
    Storage.components.myadapter = require('./myadapter');
    
    var config  = require('assetpicker/src/js/app/config');
    config.storages = {
        myadapterstorage: {
            adapter: 'myadapter',
            label: 'My Adapter'
            // ... options for myadapter
        }
    }
    
    module.exports = require('assetpicker/src/js/app');
  3. Build an HTML page for the app:

    app.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>AssetPicker</title>
        <link rel="stylesheet" href="node_modules/assetpicker/dist/css/main.css"
    </head>
    <body>
    <div id="app"></div>
    <script src="dist/js/app.js"></script>
    <script>
       new AssetPickerApp({el: '#app'});
    </script>
    </body>
    </html>
  4. Build a HTML page to which the picker should be included:

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>AssetPicker</title>
    </head>
    <body>
    <script src="node_modules/assetpicker/dist/js/picker.js"></script>
    <script>
       new AssetPicker(null, {
            modal: {
                 src: 'app.html'
            }
       });
    </script>
    <button rel="assetpicker">Pick an asset</button>
    </body>
    </html>
  5. Setup gulp or any other build tool

    npm install -g gulp
    npm install -S browserify vinyl-source-stream
    

    gulp.js

    var gulp = require('gulp');
    var browserify = require('browserify');
    var source = require('vinyl-source-stream');
    
    gulp.task('js', function () {
        var b = browserify({
            entries: './src/app.js',
            standalone: 'AssetPickerApp',
            debug: true
        });
    
        return b.bundle()
            .pipe(source('app.js'))
            .pipe(gulp.dest('./dist/js/'));
    });
    
    gulp js
    

Roadmap

  • Adapters
    • Amazon S3
    • Dropbox
  • Google Drive
    • IE compatibility
    • Reauthentication without user interaction required
  • github:
    • Two Factor Auth
    • Branch selector
    • Deal with submodules and symlinks
  • Management features like upload, renaming, moving etc.