decap-cms icon indicating copy to clipboard operation
decap-cms copied to clipboard

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

Open ksherman opened this issue 6 years ago • 19 comments
trafficstars

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

ksherman avatar Dec 05 '18 04:12 ksherman

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

kishaningithub avatar Dec 25 '18 02:12 kishaningithub

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 avatar Jan 04 '19 13:01 danlutz

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 💻

danlutz avatar Jan 04 '19 14:01 danlutz

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.

hringleikur avatar Jan 30 '19 11:01 hringleikur

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.

erquhart avatar Feb 02 '19 00:02 erquhart

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.

hringleikur avatar Feb 03 '19 12:02 hringleikur

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

erquhart avatar Feb 03 '19 12:02 erquhart

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.

aamorozov avatar Feb 19 '19 02:02 aamorozov

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.

erquhart avatar Feb 19 '19 18:02 erquhart

+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.

theoephraim avatar Jun 13 '19 20:06 theoephraim

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!

emiled avatar Jul 11 '19 04:07 emiled

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.

stale[bot] avatar Oct 29 '19 07:10 stale[bot]

Currently there is still no solution for the option

output_filename_only: true

I would like to keep this open @erquhart

pavelbinar avatar Oct 29 '19 08:10 pavelbinar

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 ?

  • it would allow admin to specify a transformed image
  • it would be independent from the used service

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.

jeromecoupe avatar Nov 04 '19 22:11 jeromecoupe

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. 😎

mark-making avatar Jan 14 '20 10:01 mark-making

  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~~

ankitshekhawat avatar Jun 03 '20 14:06 ankitshekhawat

This would be great!

martinjagodic avatar Aug 04 '21 13:08 martinjagodic

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 avatar Apr 13 '24 20:04 redraw

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
  1. that saved the image with the default transformation in the URL, then in your code replace image/upload/(.+)/ with your desired transformation

redraw avatar Apr 13 '24 20:04 redraw