Skuid Images attachments or Files?

  • 1
  • Question
  • Updated 5 months ago
  • Answered
I am in the process of converting my Attachments to Documents/Files since Salesforce is no longer going to support them.  I am using the Salesforce migration tool and so far so good!  (fingers crossed).  

I noticed that Skuid__images__c is listed as one of the objects that have attachments that could be converted to files.  I used this Skuid tutorial to create pictures of our Patients on the patient record, vehicles on the vehicle's record, and houses on the House records etc. etc.  I am using the "In Field on Record" method with a lookup to the File object as outlined in the tutorial.  

My question is simply, is Salesforce's change regarding attachments going to affect these images that are being displayed on the record like Jean Luke Picard in the tutorial?  The migrator is listing them as attachments not files so I am assuming they might be.  Is there anything we need to do with the File Upload tool to make sure we can still see and upload our images to be displayed in our records?

Thank you!
Photo of Rich Slack

Rich Slack

  • 4,134 Points 4k badge 2x thumb

Posted 11 months ago

  • 1
Photo of Rich Slack

Rich Slack

  • 4,134 Points 4k badge 2x thumb
bump
Photo of Rich Slack

Rich Slack

  • 4,134 Points 4k badge 2x thumb
Okay, I did some digging on this and my guess is that this is a big deal without some sort of fix.  I will give a quick summary and then outline in more detail below.

DISCLAIMER: This isn't a current bug.  It is a future looking statement based on current trajectory :)

Driving Issue
: After Winter ’18, the Notes & Attachments related list will no longer have an Upload File button.

Summary: I believe converting Attachments to Files on the skuid__image__c model will break the images being displayed on all the pages.  Further, new images uploaded to the File Upload component using  In Field On Record as outlined in this tutorial get uploaded as Attachments not Files.  (I.E. if you click on the place holder image of the Person or Building it auto adds the upload as an attachment.)  This isn't an issue now, but if the attachment button goes away it will be.  Also, I tested just replacing the Attachment with a File of the same name and that did not work.  So assuming it will auto rollover to Files may be a flawed assumption.

Steps to Reproduce:
In preparation for the new rule, I downloaded the Salesforce Magic Mover tool (it gets poor reviews but if you follow the prep steps before installing it worked flawlessly for me, everything has been converted with no issues except skuid__image__c and that is just because I haven't hit the button because I think it will break Skuid).  The tool lists the total count of attachments for each object and lets you convert them to Files and then allows you to delete the attachments when you are done.  I went to each page where we were using attachments and built the new Content Document Link and COntent Document objects and table with the appropriate FIle Upload component.  Once everything was converted I tested to make sure everything was there and then deleted all attachments (using the tool) and deleted the attachment models out of the SKUID page since they were no longer needed.  I went through each object until I was down to CONGA Composer templates (saved as attachments) and skuid__image__c.  

I contacted Conga and Skuid (this post) to see what the future would hold.  Conga responded that the object should work fine with either Attachments or Files.  I tested one record by downloading the Attachment file and reuploading it as a File.  I then ran composer and it worked flawlessly.  So I went ahead and converted all my Composer attachments to files and then deleted the old attachments.  Everything worked without a hitch.

I contacted SKUID using this thread but hadn't heard back yet, but the structure seemed similar.  Custom object with attachments instead of files.  Conga's solution still worked so SKUID may be in the same boat.  So I navigated to a skuid__image__c record on one of my test person accounts.  This is an image of a person.  I downloaded the image directly from the skuid__image__c record and reuploaded as a file and then deleted the attachment (but left the record intact).  This broke the image on the account detail page.  So it was different than the Conga fix.  

To fix the issue I clicked the red delete button on the image which deletes the skuid__image__c record and then clicked the placeholder image and reuploaded.  This created a new skuid__image__c record and by default, it attaches it as an Attachment, not a File.  

If I have a flaw in testing my hypothesis please let me know.  But if I am right, this is pretty core functionality that is set to be end of lifed without a fix.  

Thank you!
Rich
p.s. I love SKUID I had been trying to run standard deviation on a number of child records for some of our DRs.  Everywhere I looked said Salesforce couldn't do it.  But with SKUID + Salesforce I can calculate complex standard deviation equations for multiple child records within seconds.  Love SKUID.  Coolest thing ever!
(Edited)
Photo of Skuidward Tentacles (Raymond)

Skuidward Tentacles (Raymond), Champion

  • 17,224 Points 10k badge 2x thumb
Thanks for posting this. I’ll hope this comment “bumps” the issue for comment by the Skuid Gods.
Photo of Karen Waldschmitt

Karen Waldschmitt, Official Rep

  • 8,260 Points 5k badge 2x thumb
Hi Rich and Raymond~

Sorry for the delayed response!!!

One thing I would like to highlight is that, per Salesforce, the change only affects folks who are using Lightning Experience. As far as how to proceed, I would recommend checking out this section Salesforce Notes & Attachments versus Files on the Millau release notes. To accommodate Salesforce's change, in the Millau release, we added the option to easily upload files as Content Documents so they can be added as either Attachments or as Content Documents now. As far as the image component, you are right, the image sources are only attachment, static resource, and URL ... I will bring this up with our devs and see what to do about that ... I know this isn't ideal but, can you try changing one of your images over to using the file upload component and see if that gets you where you want? Please let us know how that goes!!!

For people who don't convert their attachments to files like Rich did, the question then becomes one of how do you display them? If you have a mix (some as attachments and some as content documents), you will need to bring both of them onto your Skuid page. On a standard Salesforce layout, you should see your attachments and files (what got uploaded as content documents) in the Notes & Attachments related list.

Hope that helps a little!
Karen
(Edited)
Photo of Bill McCullough

Bill McCullough, Champion

  • 12,436 Points 10k badge 2x thumb
Rich,

Karen's reply got me thinking about how to use Salesforce Files to store an image for a record.  Skuid included all of the pieces necessary to do this 'declaratively'.  Thanks Skuid!

I have included a Contact Detail page that demonstrates how to do this.  I have used the 'Description' field on the Contact object to store the Id of the 'File' that we want to display.  Please replace this with a custom Text field (e.g. Patient_Image_ID__c).

To add an image, click or drag a file to the 'New Contact Image' button.  To replace the image, you can click or drag a file to the 'New Contact Image' button.  Or, if you have already uploaded the image as a 'File', you can click on the image and select a different file to display as the image for the Contact.

Thanks,

Bill


<skuidpage showheader="true" personalizationmode="server" showsidebar="true" unsavedchangeswarning="" tabtooverride="Contact">
    <models>
        <model id="Contact" type="" datasource="salesforce" createrowifnonefound="false" query="true" sobject="Contact" limit="1">
            <fields>
                <field id="FirstName"/>
                <field id="LastName"/>
                <field id="CreatedDate"/>
                <field id="MailingCity"/>
                <field id="MailingStreet"/>
                <field id="MailingState"/>
                <field id="MailingCountry"/>
                <field id="MailingPostalCode"/>
                <field id="LastModifiedDate"/>
                <field id="Phone"/>
                <field id="Email"/>
                <field id="Id"/>
                <field id="AccountId"/>
                <field id="Account.Name"/>
                <field id="Birthdate"/>
                <field id="Description"/>
            </fields>
            <conditions>
                <condition type="param" value="id" enclosevalueinquotes="true" field="Id" operator="="/>
            </conditions>
            <actions/>
        </model>
        <model id="ContentDocumentLink" type="" datasource="salesforce" createrowifnonefound="false" query="true" sobject="ContentDocumentLink" limit="20">
            <fields>
                <field id="ContentDocumentId"/>
                <field id="ContentDocument.Title"/>
                <field id="LinkedEntityId"/>
                <field id="LinkedEntity.Name"/>
                <field id="ContentDocument.LatestPublishedVersionId"/>
                <field id="ContentDocument.LatestPublishedVersion.Title"/>
                <field id="Id"/>
                <field id="ContentDocument.Id"/>
            </fields>
            <conditions>
                <condition type="modelmerge" value="" model="Contact" enclosevalueinquotes="true" field="LinkedEntityId" operator="=" mergefield="Id" novaluebehavior="noquery" fieldtargetobjects="Contact"/>
            </conditions>
            <actions/>
        </model>
        <model id="LastUploaded" type="" datasource="salesforce" createrowifnonefound="false" query="false" sobject="ContentDocumentLink" limit="1" orderby="SystemModstamp DESC">
            <fields>
                <field id="ContentDocumentId"/>
                <field id="ContentDocument.Title"/>
                <field id="LinkedEntityId"/>
                <field id="LinkedEntity.Name"/>
                <field id="ContentDocument.LatestPublishedVersionId"/>
                <field id="ContentDocument.LatestPublishedVersion.Title"/>
                <field id="Id"/>
                <field id="ContentDocument.Id"/>
                <field id="SystemModstamp"/>
            </fields>
            <conditions>
                <condition type="modelmerge" value="" model="Contact" enclosevalueinquotes="true" field="LinkedEntityId" operator="=" mergefield="Id" novaluebehavior="noquery" fieldtargetobjects="Contact"/>
            </conditions>
            <actions/>
        </model>
    </models>
    <components>
        <pagetitle uniqueid="sk-2nnOO--83" model="Contact">
            <maintitle>
                <template>{{FirstName}} {{LastName}}</template>
            </maintitle>
            <subtitle>
                <template>{{Model.label}}</template>
            </subtitle>
            <actions>
                <action type="savecancel" uniqueid="sk-zZmyt-88" window="self">
                    <models>
                        <model>ContentDocumentLink</model>
                    </models>
                    <savehotkeys>
                        <hotkey key="s" modifiers="ctrl"/>
                    </savehotkeys>
                </action>
            </actions>
        </pagetitle>
        <tabset uniqueid="sk-2nnZAZ-122" renderas="" defertabrendering="true" rememberlastusertab="true">
            <tabs>
                <tab name="Demographics">
                    <components>
                        <grid uniqueid="sk-1JOn4K-289">
                            <divisions>
                                <division verticalalign="top" behavior="specified" width="250px">
                                    <components>
                                        <image source="url" uniqueid="sk-2om0aY-1786" datasource="salesforce" behavior="button" model="Contact" url="/sfc/servlet.shepherd/version/download/{{{Description}}}">
                                            <styles>
                                                <styleitem type="itemsize"/>
                                                <styleitem type="border"/>
                                            </styles>
                                            <interactions>
                                                <interaction type="tap">
                                                    <action type="requeryModel" model="ContentDocumentLink" behavior="standard"/>
                                                    <action type="showPopup">
                                                        <popup title="Select Image" width="70%">
                                                            <components>
                                                                <deck searchmethod="server" searchbox="false" columngutter=".75em" rowgutter=".75em" model="ContentDocumentLink" filtersposition="top" filterswidth="150px" showsavecancel="false" behavior="flex" verticalalign="top" ratio="1" minwidth="150px" uniqueid="sk-2oqyo7-658" buttonposition="" pagesize="5" emptysearchbehavior="query">
                                                                    <components>
                                                                        <wrapper uniqueid="sk-2or6aG-702">
                                                                            <components>
                                                                                <image source="url" uniqueid="sk-2or1Bk-683" datasource="salesforce" behavior="none" model="ContentDocumentLink" url="/sfc/servlet.shepherd/version/download/{{{ContentDocument.LatestPublishedVersionId}}}">
                                                                                    <styles>
                                                                                        <styleitem type="itemsize"/>
                                                                                        <styleitem type="border"/>
                                                                                    </styles>
                                                                                    <conditions>
                                                                                        <condition type="contextrow" field="Id" mergefield="Id"/>
                                                                                    </conditions>
                                                                                </image>
                                                                            </components>
                                                                            <styles>
                                                                                <styleitem type="background"/>
                                                                                <styleitem type="border"/>
                                                                                <styleitem type="size" width="full" height="collapse"/>
                                                                            </styles>
                                                                        </wrapper>
                                                                    </components>
                                                                    <massactions/>
                                                                    <interactions>
                                                                        <interaction type="tap" direction="either">
                                                                            <action type="updateRow" fieldmodel="Contact" affectedrows="context" field="Description" enclosevalueinquotes="true" value="{{ContentDocument.LatestPublishedVersionId}}">
                                                                                <models/>
                                                                                <popup title="{{Model.label}}: {{Name}}" width="80%">
                                                                                    <components/>
                                                                                </popup>
                                                                            </action>
                                                                            <action type="save" rollbackonanyerror="true">
                                                                                <models>
                                                                                    <model>Contact</model>
                                                                                </models>
                                                                                <onerroractions>
                                                                                    <action type="blockUI" message="There was an error" timeout="3000"/>
                                                                                    <action type="unblockUI" message="There was an error" timeout="3000"/>
                                                                                </onerroractions>
                                                                            </action>
                                                                            <action type="closeTopmostPopup"/>
                                                                        </interaction>
                                                                    </interactions>
                                                                    <actions/>
                                                                    <styles>
                                                                        <styleitem type="border"/>
                                                                    </styles>
                                                                    <searchfields/>
                                                                </deck>
                                                            </components>
                                                        </popup>
                                                    </action>
                                                </interaction>
                                            </interactions>
                                        </image>
                                        <file storeas="contentdocumentwithrecord" displayas="filename" uniqueid="sk-2oxn1B-383" datasource="salesforce" model="Contact" label="New Contact Image">
                                            <uploadsuccessactions>
                                                <action type="requeryModel" model="LastUploaded" behavior="standard"/>
                                                <action type="updateRow" fieldmodel="Contact" affectedrows="context" field="Description" enclosevalueinquotes="true" value="{{{$Model.LastUploaded.data.0.ContentDocument.LatestPublishedVersionId}}}"/>
                                                <action type="save">
                                                    <models>
                                                        <model>Contact</model>
                                                    </models>
                                                </action>
                                            </uploadsuccessactions>
                                            <uploadfailureactions/>
                                        </file>
                                    </components>
                                </division>
                                <division verticalalign="top" behavior="flex" ratio="1" minwidth="100px">
                                    <components>
                                        <basicfieldeditor uniqueid="sk-2nnOO--84" model="Contact" mode="read" buttonposition="" showsavecancel="false" layout="" showheader="true">
                                            <columns>
                                                <column width="50%">
                                                    <sections>
                                                        <section title="Basics" collapsible="no">
                                                            <fields>
                                                                <field id="FirstName" type="" uniqueid="sk-zZmzM-96" valuehalign=""/>
                                                                <field id="LastName" uniqueid="sk-zZmzP-98"/>
                                                                <field id="Phone" type="" uniqueid="sk-zaxUD-370" cssclass="" snippet="businessPhoneRender" valuehalign=""/>
                                                                <field id="Email" type="" uniqueid="sk-13zjI1-245" valuehalign=""/>
                                                                <field id="AccountId" type="" uniqueid="sk-1VHq5D-261" pagesize="5" valuehalign="" optionsource="" redirecttype="datasourcedefault">
                                                                    <searchfields soslfields="All Fields" usesosl="true"/>
                                                                    <filters/>
                                                                    <renderconditions logictype="and" onhidedatabehavior="keep"/>
                                                                    <enableconditions/>
                                                                </field>
                                                                <field id="Birthdate" uniqueid="sk-22tbDe-276" valuehalign="" type=""/>
                                                            </fields>
                                                        </section>
                                                        <section title="Image" collapsible="no">
                                                            <fields>
                                                                <field uniqueid="sk-2ovbdg-953" id="Description" valuehalign="" type=""/>
                                                            </fields>
                                                        </section>
                                                    </sections>
                                                </column>
                                                <column width="50%">
                                                    <sections>
                                                        <section title="Address" collapsible="no">
                                                            <fields>
                                                                <field id="MailingStreet" uniqueid="sk-zZmzp-115"/>
                                                                <field id="MailingCity" uniqueid="sk-zZmzq-117"/>
                                                                <field id="MailingState" uniqueid="sk-zZmzr-119" valuehalign="" type=""/>
                                                                <field id="MailingPostalCode" uniqueid="sk-zZmzv-121"/>
                                                                <field id="MailingCountry" uniqueid="sk-zZmzz-123" valuehalign="" type=""/>
                                                            </fields>
                                                        </section>
                                                    </sections>
                                                </column>
                                            </columns>
                                        </basicfieldeditor>
                                    </components>
                                </division>
                            </divisions>
       &nbsp
(Edited)
Photo of Ant Belsham

Ant Belsham

  • 1,022 Points 1k badge 2x thumb
Hi Bill,

I'm interested in your approach. Did the XML for you demo page get truncated?
Photo of Bill McCullough

Bill McCullough, Champion

  • 12,436 Points 10k badge 2x thumb
Ant,

Not sure what happened with the XML.  Try this link to a snippet hosted on Gitlab.

https://gitlab.com/snippets/1727714

Thanks,

Bill
Photo of Ant Belsham

Ant Belsham

  • 1,022 Points 1k badge 2x thumb
Thanks for that Bill. Works fine now, and a really useful example. Much appreciated!
Photo of Erik Wahlberg

Erik Wahlberg

  • 2,156 Points 2k badge 2x thumb
Any suggestions on adapting the upload for a Product Detail Page? Displaying the image after the content document is created separately is one solution, but i'd like to be able to upload directly from the detail page. Trying to figure out a workaround but still getting the Large File error on upload.