decaporg / decap-cms

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

[Cloudinary] Image URL in Editor preview broken with output_filename_only option #1934

Open ksherman opened 5 years ago

ksherman commented 5 years ago

Describe the bug When using the Cloudinary Media Library integration, I want to use the output_filename_only option to take advantage of URL transformations. However, this option seems to break the rendering of the preview images.

To Reproduce Switch Cloudinary image assets to output_filename_only and observer the broken image links in the editor.

Expected behavior We would expect the editor preview components to build the preview URL for the image to append the the image filename.

Screenshots screenshot 2018-12-04 22 05 50

Applicable Versions: Netlify CMS 2.3.0

CMS configuration https://gist.github.com/ksherman/cb5b319858b8ea06fbf638818f839d84.js

Additional context You all are awesome and I know this feature was juuuuust released :D

kishaningithub commented 5 years ago

One additional point here, is i can organize images into folders in cloudinary at which point the output filename should be <folder name>/<file name> instead of just filename

danlutz commented 5 years ago

Awesome work on the Cloudinary integration!

I think what is needed here, is that the CMS integrates the "cloudinary-react" package from npm, gets the cloudname from the config.yml, and then displays the React component like this:

import React from 'react'
import { Image, Transformation } from 'cloudinary-react'

const PreviewImage = ({publicId, cloudName}) => 
    (<Image publicId={publicId} cloudName={cloudName}>
          <Transformation
            width="auto"
            crop="fill"
            dpr="auto"
            fetchFormat="auto"
            quality="auto"
          />
    </Image>)

Or alternative, without React (Just get the correct url with the cloudinary-core module):

import cloudinary from 'cloudinary-core'

const getCloudinaryUrl = (cloudName, publicId) => {
    const cl = new cloudinary.Cloudinary({
      cloud_name,
      secure: true,
    })

    return cl.url(publicId, {
        dpr: 'auto',
        responsive: 'true',
        width: 'auto',
        fetchFormat: 'auto',
        quality: 'auto',
    })
}

I'll take a look and see if I can make a PR, but don't expect too much 😆

danlutz commented 5 years ago

Also, if you want to inline an image inside the "body", it only passes the filename to the "src" attribute.

It tried digging through the source code, but unfortunatly I could not find the correct place to code this additional logic. Looking forward to someone that is more skilled than me 💻

hringleikur commented 5 years ago

Added a pull request that addresses the most basic case here, but it is still a problem when the markdown widget is used because the "path only" version gets inserted into the markdown. Ideally, the markdown editor would also have a "base_image_url" option.

erquhart commented 5 years ago

I'll be going through PR's soon, but I think the best way to handle this is probably by some cooperation between the media library and the image widget preview component. Still need to think through how that would work, but the logic for connecting the url value with the Cloudinary root url is simple, just a matter of where that should occur and whether it's possible without requiring configuration. I think it is.

hringleikur commented 5 years ago

I agree that the thumbnail at least should be possible with zero config. The main issue I see is the preview - either it would need to be left broken or we would have to make a design decision that the user might disagree with.

erquhart commented 5 years ago

Widget preview components provide a default preview for an individual field. We would make the image widget provide the image as expected by default. If someone wants the actual field value, they can still access it in a custom preview template (or custom widget preview component), so everyone wins.

The challenge is doing this in a generic way so that the image widget makes no assumptions about your media library, hence the need to provide some sort of cooperative API between these two extension points.

Sent with GitHawk

aamorozov commented 5 years ago

The issue seems be related to the image widget in general - i'm using manual upload of the images and they show up as broken links in the admin, although the frontend app is still able to query them.

erquhart commented 5 years ago

Yep, those are img elements, if you check their src you'll see what they're looking for and can determine why it's not there. Either the image wasn't deployed, your CMS is not on the same domain as the site where the image is deployed, you're developing locally, etc. Pulling through the API instead of just constructing URLs is the solution.

theoephraim commented 5 years ago

+1 - this is pretty much required for the output_filename_only option to be usable at all.

For now I'll be parsing the full URL and inserting my transformations that way, but it would be great if Netlify CMS was able to realize that I'm using an image hosting service capable of resizing and use thumbnails instead of full rez images in the admin interface.

emiled commented 5 years ago

I encountered this issue also - the workaround I found was to set output_filename_only: false, and in the html templates, use a Hugo snippet to split the string and recover the asset's name, isolated from the full path.

With this asset name string, I appended it to the Cloudinary transform URL string that was set to a variable.

  1. Set the cloudinaryAssetName variable using Scratch (replace ".cloudinaryFullURL" with your path variable)

{{ $.Scratch.Set "cloudinaryAssetName" (index (split .cloudinaryFullURL "/") (sub (len (split .cloudinaryFullURL "/")) 1)) }}

  1. Assign the image path with the concatenated URL - <img src='{{ $.Params.cloudinaryPathThumb }}{{ $.Scratch.Get "cloudinaryAssetName" }}'

here {{ $.Params.cloudinaryPathThumb }} = "https://res.cloudinary.com/myuserid/image/upload/w_200,c_scale/"

and {{ $.Scratch.Get "cloudinaryAssetName" }} = "assetname.jpg"

This outputs the desired path: <img src='https://res.cloudinary.com/myuserid/image/upload/w_200,c_scale/assetname.jpg'

..and avoids the original problem with the Editor Preview being broken, as we're using the full Cloudinary URL!

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

pavelbinar commented 4 years ago

Currently there is still no solution for the option

output_filename_only: true

I would like to keep this open @erquhart

jeromecoupe commented 4 years ago

Subscribing to this. Especially with RWD images, it's a lot easier to use URLs in templates to do the heavy lifting. output_filename_only: true makes sense in that case but it breaks the preview and the user experience in the CMS.

I understand a zero config solution would be ideal, but wouldn't the most flexible option still be to add an output_preview_path ?

Currently using full Cloudinary URLs and a custom 11ty filter to get the filename and create the URLs I need, which means I am loading the full images in the CMS.

mark-making commented 4 years ago

Currently there is still no solution for the option

output_filename_only: true

I would like to keep this open @erquhart

Such a great implementation, it would be great for the image preview to work in the editor. 😎

ankitshekhawat commented 4 years ago
  1. Set the cloudinaryAssetName variable using Scratch (replace ".cloudinaryFullURL" with your path variable)

{{ $.Scratch.Set "cloudinaryAssetName" (index (split .cloudinaryFullURL "/") (sub (len (split .cloudinaryFullURL "/")) 1)) }}

  1. Assign the image path with the concatenated URL - <img src='{{ $.Params.cloudinaryPathThumb }}{{ $.Scratch.Get "cloudinaryAssetName" }}'

You could also use Go's built-in parse function: <img src='{{ $.Params.cloudinaryPathThumb }}{{ path.Base (urls.Parse .cloudinaryFullURL ) }}' />

Maybe write this in a shortcode to get to check if the Host is Cloudinary to conditionally parse the image

martinjagodic commented 3 years ago

This would be great!

redraw commented 5 months ago

Bumping this old thread. The problem is that if storing the full path, full resolution images get loaded in the admin as thumbnails, that's crazy...

Still, we're not able to set output_filename_only: true along with some preview_path field to build a transformation url for the admin thumbnails.

Any ideas?

redraw commented 5 months ago

Ok, I've done the following if you are in the same situation:

  1. set output_filename_only: false
  2. add a default transformation at top level
    media_library:
    name: cloudinary
    config:
    cloud_name: ...
    api_key: ...
    default_transformations:
      - - fetch_format: auto
          width: 160
          quality: auto
          crop: scale
  3. that saved the image with the default transformation in the URL, then in your code replace image/upload/(.+)/ with your desired transformation