decaporg / decap-cms

A Git-based CMS for Static Site Generators
https://decapcms.org
MIT License
17.85k stars 3.04k forks source link

Media Library backed by a Netlify CMS collection #6160

Open gnfzdz opened 2 years ago

gnfzdz commented 2 years ago

Is your feature request related to a problem? Please describe. As a Netlify CMS user, I would like the ability to present a media library where users can select from a curated collection of images, videos or other media items (potentially) not contained within git.

Describe the solution you'd like When the media library component is opened, instead of displaying a list of media files contained in a media_folder, a list of items specified in a standard Netlify CMS collection would be displayed instead.

Collections of this type would need to adhere to a minimal base schema (id, url, but also potentially thumbnail, file size, etc) but could also be enriched with user specified fields, ex: tags #5029, location data (from exif or manually assigned), default alt text, attribution details, etc

On selecting a file from the media library, the default behavior would be to use the returned entries url as the value for the corresponding file or image field, but we could expose a configuration option to instead return a user configurable field (like an identifier).

Sample Use Cases

Not (initially) in scope

gnfzdz commented 2 years ago

Also, I should clarify that this is a feature I'm interested in implementing. I'm just looking for confirmation this is a feature that you're interested in merging and any feedback on what I've described out above.

erezrokah commented 2 years ago

Hi @gnfzdz, could you use a list widget to represent a collection of images? You can configure the media folder per collection and have all images saved under a specific folder.

Then in a new collection you can configure the same media to pick up images from the first "media" collection.

Wouldn't that work?

See more in https://www.netlifycms.org/docs/widgets/#image

gnfzdz commented 2 years ago

Hi @erezrokah thanks for the reply. That is similar to what I have in mind, but unless I'm misunderstanding, I don't think that solves for the scenario where the media isn't actually stored in git. With the current media library in Netlify CMS, the media displayed in the library are assumed to be references to actual files stored in git as returned by the configured git backend.

For my use case, specifically, I have a large volume of media currently stored in S3 (primarily images, but also videos and a few other asset types). It's currently around 10 GB and I'm only expecting it to grow.

I do think the pattern you described works for managing the metadata of assets stored in git, but with the current set of widgets, you'd never have the benefit of both the media library to select the asset (provided by file or image widgets) or the related metadata in previews (as provided by the relation widget). I think adding first class support for that use case to the image and file widgets would make sense as another feature and I think the feature in this issue would help by standardizing the pattern.

I think the bulk of the changes would only be the MediaLibrary container component and configuration parsing/validation. I've provided below a sample configuration for both the library configuration and a consumer of assets. I do think this could actually play nicely with #3683 as well where there could be built-in capabilities to provide the required mediaLibrary field(s) and possibly additional extensions (ex: tags, alternative text, etc).

# Sample declaration of a new library
collections:
  - label: "Image Assets"
    name: "imageAssets"
    # I'm not sure this actually makes sense. Other alternatives, source filename, file hash or a randomly generated GUID.
    identifier_field: "url"
    media_folder: "assets/images"
    fields:
      # Mandatory field(s)
      - label: "Url"
        name: "url"
        widget: "file"
        description: "Location where the image may be retrieved. Relative paths are assumed relative to the configured media_folder." 
      # Optional fields
      - label: "Size"
        name: "size"
        widget: "number"
        required: false
        description: "Size of the file in bytes" 
      - label: "Preview Url" 
        name: "previewUrl"
        widget: "file"
        required: false
        description: "A low resolution image to help with identification in the media library"
      # Sample custom fields. These could be injected to previews as fieldMetaData, used 
      # to drive filters in the media_library configuration or filters within the library UI itself.
      - label: "Description"
        name: "description"
        widget: "string"
        description: "An accessible summary of the image's contents"
      - label: "Location"
        name: "location"
        widget: "map"
        required: false
        description: "Location where the image was initially captured. Extracted from EXIF where available otherwise manually assigned by an editor."
      - label: "Tags"
        name: "tags"
        widget: "list"
        required: false
        description: "A label used to aid in identification and association of images"

  # Another collection that's referencing images within the imageAssets library
  - label: "Posts"
    name: "posts"
    fields:
      - label: "Title" 
        name: "title"
        widget: "string"
      - label: "Image Gallery"
        name: "imageGallery"
        widget: "image"
        media_library:
          collection:
            name: "imageAssets"
          allow_multiple: true
      - label: "Content"
        name: "body"
        widget: "Markdown"
erezrokah commented 2 years ago

For my use case, specifically, I have a large volume of media currently stored in S3 (primarily images, but also videos and a few other asset types). It's currently around 10 GB and I'm only expecting it to grow.

We have an API to register an external media library, see https://github.com/netlify/netlify-cms/blob/893d01eb8cad5e4fa396a48270940cb036000ca5/packages/netlify-cms-media-library-cloudinary/src/index.js and https://www.netlifycms.org/docs/cloudinary/, so that's probably the best approach for managing media files that are outside of git. One would have to write a UI modal that acts as a wrapper over S3, or find an existing one to use.

but with the current set of widgets, you'd never have the benefit of both the media library to select the asset (provided by file or image widgets) or the related metadata in previews (as provided by the relation widget)

Is the request to pass more information about the image to preview template?

gnfzdz commented 2 years ago

but with the current set of widgets, you'd never have the benefit of both the media library to select the asset (provided by file or image widgets) or the related metadata in previews (as provided by the relation widget)

Is the request to pass more information about the image to preview template?

Yes. Basically, this is a hybrid between image and relation widgets where you want the benefit of the media library UI displaying images to aid in selection but after a value is set, you may want the additional metadata describing the image for use in a preview.

See the example below with a single file collection defining the library and one post referencing an asset in the library. If featureImage is configured with widget type:


# content/my-library.yml
assets:
- url: "dog_in_central_park.png"
  description: "A picture of a dog running around central park"
  location: "{\"type\":\"Point\",\"coordinates\":[73.9665,40.7812]}"

- url: "raccoon_in_trash_can.png"
  description: "A picture of a raccoon trying to scavenge some dinner"
  attribution:
    title: "Raccoon in Trash Can"
    creator: gnfzdz
    source: https://example.org/raccoon_in_trash_can.png
    license: CC BY-ND 2.0
---
title: Raccoons are cool
featureImage: "raccoon_in_trash_can.png"
---
<Some text>

For my use case, specifically, I have a large volume of media currently stored in S3 (primarily images, but also videos and a few other asset types). It's currently around 10 GB and I'm only expecting it to grow.

We have an API to register an external media library, see https://github.com/netlify/netlify-cms/blob/893d01eb8cad5e4fa396a48270940cb036000ca5/packages/netlify-cms-media-library-cloudinary/src/index.js and https://www.netlifycms.org/docs/cloudinary/, so that's probably the best approach for managing media files that are outside of git. One would have to write a UI modal that acts as a wrapper over S3, or find an existing one to use.

I did see that, but it seemed more appropriate for wholly third party media libraries. Maybe I interpreted it that way as Cloudinary and Uploadcare appear to be the only current consumers.

In this scenario, the urls are still stored within git and would ideally be injected from the Netlify CMS store. I initially refrained from mentioning S3 as that's just an implementation detail specific to my situation. It could be any public url. There's also already some support for using arbitrary image urls within Netlify CMS, just not reusing such urls.