Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Adi 79 posts 183 karma points
    Jan 18, 2014 @ 13:05
    Adi
    0

    Adding attachments to articles in back-end and then showing them in front-end CMS

    Hello,

    On my Umbraco website, I have the section which shows latest News. Each news is one article.

    Unfortunately, I can't add any attachments to aexamny News article in back-end so users could see that attachment(s) on front-end of website and download them if they want to. This is how I it should look like

    example

    Is this possible to do? While I was using Joomla CMS it was very easy by installing additional module/component which took me only 15 minutes to set.

    Any help is appreciated and many thanks in advance for prompt replies! Adi

  • Amir Khan 1282 posts 2739 karma points
    Jan 18, 2014 @ 23:01
    Amir Khan
    0

    You could use the uComponents Multi-URL picker and only enable the media type in "Allowed modes", or you could just link them up in the RTE.

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 18, 2014 @ 23:36
    Bjarne Fyrstenborg
    0

    Hi Adi..

    In your case I would go for uComponents Multi-URL picker as Amir mention.. and the build the table dynamic... might be easier to manage for editors and more semantic markup in the HTML..

    If you are using xslt you could use one of Chriztian Steinmeier great xslt helper here to easier get data from multi-url picker: https://github.com/greystate/Greystate-XSLT-Helpers 

    /Bjarne

  • Amir Khan 1282 posts 2739 karma points
    Jan 18, 2014 @ 23:41
    Amir Khan
    1

    Good point regarding semantics Bjarne.

    Here's how you can grab the data from the picker in Razor as well. We use that datatype for all kinds of "related" content on pages.

     

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
    if(CurrentPage.HasValue("relatedLinks")){
    <ul>
    @foreach (var link in CurrentPage.relatedLinks.Items)
    {
    if(@link.NewWindow == false && @link.Mode.ToString() != "Media"){
    <li>
    <a href="@link.Url" @Html.Raw(link.NewWindow ? "target=\"_blank\"" : "")>@link.Title</a><br />
    </li>
    }
    if(@link.NewWindow == true){
    <li>
    <a href="@link.Url" @Html.Raw(link.NewWindow ? "target=\"_blank\"" : "")>@link.Title</a>
    </li>
    }
    if(@link.Mode.ToString() == "Media"){
    <li>
    <a href="@link.Url" @Html.Raw(link.NewWindow ? "target=\"_blank\"" : "")>@link.Title (pdf)</a>
    </li>
    }
    }
    </ul>
    }
    }
  • Adi 79 posts 183 karma points
    Jan 19, 2014 @ 17:49
    Adi
    0

    Hello,

    thank you all for help, I have already made some progress but I am missing some parts.

    This is what I have managed to do:

    1. I have installed Multi-URL picker data type and I have enabled "Allowed modes" I also decided just to focus on 'Upload' tab for now.

    Now I have issue that I can't upload more than one attachment. Please see screen.

    can't upload more than one attachment

    2. I have edited my main Template so users could see attachment they have uploaded, one the front-end of the website. This is what I did, please see picture. editing template

    I am not sure what code should I use on this part in order for front-end, to look like this:

    example screen

    3. This is how it looks like now on my website

    my website

    I am not sure what to do anymore?!

    Greetings, Adi

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 19, 2014 @ 19:14
    Bjarne Fyrstenborg
    0

    Hi Adi

    I'm not sure if uComponents Multi-URL Picker support multiple items for the Upload-tab. But the Media-tab does. Mostly I use the Media-tab because it allow you to reuse and link to media items from many different pages of your site.. generally I think you should use Upload datatype (the normal one in core or in uComponents) if the uploaded file only is expected to be used for that single page, otherwise I would go for media items.

    The reason why your output display True/media/441/example_attachment.jpgTest is because you use umbraco:Item which return the output for that specific property.. you need to replace that with a macro instead, which link to e.g. a xslt or razor file..

    In either xslt or razor you need to pull out the data stored in the property and modify the output to what you want to return - e.g. a table and dynamic build the table rows and in each table row display a link to the attachments..

    /Bjarne

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 19, 2014 @ 19:28
    Bjarne Fyrstenborg
    0

    Here is some similar I have done with downloads for a product in a webshop with uComponents Multi-URL Picker:

    @{
    bool hasDownloads = false;
    if(!Model.IsNull("productDownloads")) { if(Model.HasValue("productDownloads")) { hasDownloads = Model.productDownloads.Items.Count > 0 ? true : false; } }
    }

    @if (hasDownloads) { <ul class="downloads"> @foreach (var link in Model.productDownloads.Items) { var urlPickerLinkTarget = (link.NewWindow) ? " target=\"_blank\"" : String.Empty; <li><a href="@link.Url" @Html.Raw(urlPickerLinkTarget)>@link.Title</a></li> } </ul> }

    I have left out some of the additional code, but this should give you an idea to get started.. instead of <ul> and <li> your could build <table> and <tr> + <th> or <td>

    /Bjarne

  • Adi 79 posts 183 karma points
    Jan 19, 2014 @ 19:40
    Adi
    0

    Hello Bjarne,

    thank you very much for quick reply!

    I'm not sure if uComponents Multi-URL Picker support multiple items for the Upload-tab. But the Media-tab does. Mostly I use the Media-tab because it allow you to reuse and link to media items from many different pages of your site.. generally I think you should use Upload datatype (the normal one in core or in uComponents) if the uploaded file only is expected to be used for that single page, otherwise I would go for media items.

    Even under Media-tab I can only add one item and I don't see 'Add new item' option, I don't know why is that? I must note that after reading your comment, most likely I will use Media-tab because it interacts with Ubmraco Media segment which works great.

    I either xslt or razor you need to pull out the data stored in the property and modify the output to what you want to return - e.g. a table and dynamic build the table rows and in each table row display a link to the attachments..

    This is the part that is giving me most troubles. I have already visited and learned something new from link you provide me with https://github.com/greystate/Greystate-XSLT-Helpers BUT I can't find some solid example which would fit my needs in order to achieve something like this example

    Can you give me some pointers or recomment some example?

    Thanks, Adi

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 19, 2014 @ 19:56
    Bjarne Fyrstenborg
    0

    Are you sure your datatype for your property inherit from uComponents Multi-URL Picker and not URL Picker?

    It should look like this in content:

    and like this in your datatype:

    You could build the attachment table dynamic from either xslt or razor.. razor might be easier if you already have experience with ASP.NET C# but if you already have some experience with xslt that might be easiest to understand..

     

  • Adi 79 posts 183 karma points
    Jan 19, 2014 @ 23:03
    Adi
    0

    You are right, I have used URL Picker and not Multi-URL Picker. After your suggestion I have corrected that and now it works as it should.

    To be honest I am not familiar with XSLT to much and I am still learning. However, I am amateur in ASP.NET C# and have some basic experience so perhaps I should start with that.

    Could you show me some example code which would be similar in achieving result like this

    example

    I assume there should be some Loop which would check how many items were added by end-user via Multi-URL Picker and then to show (echo)the list of the items (links). For example, list would look like this:

    Winning ticket.pdf 3025 kB

    winner.jpg 9801 kB

    introduction.ppt 12435 kB

    etc

    Thank you, Adi

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 19, 2014 @ 23:12
    Bjarne Fyrstenborg
    0

    Sorry it was these xslt helpers I was refering to https://github.com/leekelleher/ucomponents-xslt/tree/master/uComponents.XsltTemplates in xslt, where there is one for urlpicker and multi-url picker.. it helps you to get the output..

    urlpicker-helper.xslt outputs for multi-url picker a unordnered list for the items, but you might need to modify it or create an extra template with output a table instead.

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 19, 2014 @ 23:23
    Bjarne Fyrstenborg
    0

    The previous example it is in razor and when you are inside the loop link has the properties from the items.. http://ucomponents.codeplex.com/wikipage?title=UrlPicker

    One of them is the node-id of the media items.. when you have the id of an media item you can get the sizes of the files, where you can use umbracoBytes.

    These examples might help you to work with umbracoBytes: http://our.umbraco.org/forum/developers/razor/31407-UmbracoBytes

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 20, 2014 @ 03:19
    Bjarne Fyrstenborg
    1

    I have created an example you hopefully can use, feel free to modify it for your needs...

    I created a razor file called displayAttachments and created a macro as well..
    You could also include the razor file in an existing another or a existing razor file..

    The razor file included this code:

    @inherits umbraco.MacroEngines.DynamicNodeContext
    
    @{
        bool hasAttachments = false;
        if(!Model.IsNull("attachments"))
        {
            if(Model.HasValue("attachments"))
            {
                hasAttachments = Model.attachments.Items.Count > 0 ? true : false;
            }
        }
    
        if (hasAttachments)
        {
            int index = 0;
            <table class="attachments">
                <caption>Attachments:</caption>
            @foreach (var link in Model.attachments.Items)
            {
                var urlPickerLinkTarget = (link.NewWindow) ? " target=\"_blank\"" : String.Empty;
                var chosenMedia = Model.MediaById(link.NodeId);
                string oddeven = index % 2 == 0 ? "odd" : "even";
                string cssClass = "class=" + oddeven + "";
    
                <tr @cssClass>
                    <td><a href="@link.Url" @Html.Raw(urlPickerLinkTarget)>@chosenMedia.Name</td>
                    <td>[ ]</td>
    
                    @{
                        var fileSize = "";
                        if (Convert.ToUInt64(@chosenMedia.umbracoBytes) < 1048576)
                        {
                            fileSize = ((Math.Round(Convert.ToDecimal(@chosenMedia.umbracoBytes) / 1024, 0)).ToString() + " KB");
                        }
                        else
                        {
                            fileSize = ((Math.Round(Convert.ToDecimal(@chosenMedia.umbracoBytes) / 1048576, 2)).ToString() + " MB");
                        }
                    }
                    <td class="pull-right">@fileSize</td>
                </tr>
                index++;
            }
            </table>
        }
    
    }

     

    Furthermore I added some additional styling for the table in my css file:

    table.attachments {
       border-collapse: separate; border-spacing: 3px; font-size: 12px; border: 1px solid #ccc;
    }
    table.attachments caption {
       text-align: left;
       margin-bottom: 3px;
    }
    table.attachments th, table.attachments td { padding: 5px; vertical-align: top; }
    
    table.attachments tr.odd td {
       background-color: #fff;
    }
    table.attachments tr.even td {
       background-color: #eee;
    }
    
    table.attachments td a {
       color: #2595ec;
       display:inline-block;
       padding-left:22px;
       line-height:18px;
       background-color: transparent;
       background-position: center left;
       background-repeat: no-repeat;
    }
    
    table.attachments td a[href$='.pdf'] {
        background-image: url(/images/icons/pdf.gif);
    }
    table.attachments td a[href$='.doc'], table.attachments td a[href$='.docx'] {
        background-image: url(/images/icons/docx.gif);
    }
    table.attachments td a[href$='.xls'], table.attachments td a[href$='.xlsx'] {
        background-image: url(/images/icons/xls.gif);
    }
    table.attachments td a[href$='.jpg'], table.attachments td a[href$='.png'],
    table.attachments td a[href$='.gif'] {
        background-image: url(/images/icons/image.gif);
    }
    .pull-right { text-align: right; }

    Then just place the macro in your template, where you want the table or inside another razor file if you have some existing code: 

    @RenderPage("~/macroScripts/displayAttachments.cshtml")

    And this is how it looks:

    I have used the media node name for link text, but your could also use the Multi-URL Picker title property with @link.Title or combine node name + extensions in parentheses.. or use the exact filename (where you probably want to exclude the path).

    In that case you could after the line string cssClass = "...."; in the razor file include these lines

    string path = chosenMedia.umbracoFile;
    int pos = path.LastIndexOf("/") + 1;
    string fileName = path.Substring(pos, path.Length - pos);

    and then just replace @chosenMedia.Name inside the loop with @fileName

    /Bjarne 

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 20, 2014 @ 03:29
    Bjarne Fyrstenborg
    0

    It might be easier to define fileSize before building the row and have a more clear overview of your markup.

    @inherits umbraco.MacroEngines.DynamicNodeContext
    
    @{
        bool hasAttachments = false;
        if(!Model.IsNull("attachments"))
        {
            if(Model.HasValue("attachments"))
            {
                hasAttachments = Model.attachments.Items.Count > 0 ? true : false;
            }
        }
    
        if (hasAttachments)
        {
            int index = 0;
            <table class="attachments">
                <caption>Attachments:</caption>
            @foreach (var link in Model.attachments.Items)
            {
                var urlPickerLinkTarget = (link.NewWindow) ? " target=\"_blank\"" : String.Empty;
                var chosenMedia = Model.MediaById(link.NodeId);
                string oddeven = index % 2 == 0 ? "odd" : "even";
                string cssClass = "class=" + oddeven + "";
    
                string path = chosenMedia.umbracoFile;
                int pos = path.LastIndexOf("/") + 1;
                string fileName = chosenMedia.Name; @* path.Substring(pos, path.Length - pos); *@
    
                var fileSize = "";
                if (Convert.ToUInt64(@chosenMedia.umbracoBytes) < 1048576)
                {
                    fileSize = ((Math.Round(Convert.ToDecimal(@chosenMedia.umbracoBytes) / 1024, 0)).ToString() + " KB");
                }
                else
                {
                    fileSize = ((Math.Round(Convert.ToDecimal(@chosenMedia.umbracoBytes) / 1048576, 2)).ToString() + " MB");
                }
    
                <tr @cssClass>
                    <td><a href="@link.Url" @Html.Raw(urlPickerLinkTarget)>@fileName</td>
                    <td>[ ]</td>
                    <td class="pull-right">@fileSize</td>
                </tr>
                index++;
            }
            </table>
        }
    }
  • Adi 79 posts 183 karma points
    Jan 20, 2014 @ 23:11
    Adi
    0

    Hi Bjarne,

    thank you for detailed answer, now I understand that everything is about razor file which is key to solution.

    This is what I managed to do based on your suggestions (I have describe it through pictures, I hope that is ok):

    1. enter image description here

    2. enter image description here

    3. enter image description here

    4. enter image description here

    5. enter image description here

    6. enter image description here

    7. enter image description here

    8. enter image description here

    9. enter image description here

    As you can see on last two pictures, Macro should show some list based on the code provided but it doesn't and I am confused why is that? I assume it has something with changing 'var urlPickerLinkTarget' part in 'displayAttachments.cshtml' but I am not sure anymore because I tried few combinations and changes in code but no luck;( If it is easier and if you agree, I can send you link to my website so you could see backoffice and check out what I could miss perhaps.

    I hope you can help me because I feel that I am on 90% of solution but I am missing that 10% to be complete;)

    Thank you, Adi

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 20, 2014 @ 23:40
    Bjarne Fyrstenborg
    0

    Hi Adi..

    You need to rename the property to attachments or modify the razor file to use UrlPicker3 as alias..

    But I would recommend you to give your property a name: Attachments and alias attachments as it is more descriptive...

    In razor file it says Model.attachments ... Model means current page/current node.. and attachments is the alias of the property on that node..

    /Bjarne

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 20, 2014 @ 23:47
    Bjarne Fyrstenborg
    0

    Your could also just call your datatype Attachments .. or Multi-URL Picker.. and perhaps reuse that datatype for other thing if is has same settings.. otherwise you just create a new datatype, with diffenrent settings.. I would not call it UrlPicker as you associate it would uComponents UrlPicker.. and it's not one you are using in this case - actually Multi-URL Picker.. so just make life easier to yourself and not become more confused than necessary..

  • Adi 79 posts 183 karma points
    Jan 21, 2014 @ 20:04
    Adi
    0

    Hello Bjarne,

    Finnaly, now I have first working version and thanks to you it is working as you described in last post. I have also followed your suggestion and I renamed data type to Attachments, just to avoid confusion.

    What I have noticed that code is working for Media tab only, if I decide to include all other tabs from Multi-URL picker, is this the main part of code I should change?

    var chosenMedia = Model.MediaById(link.NodeId);

    I assume I have to update MediaById(link.NodeId) part with content which will 'connect' which other tabs (URL, Content, Upload)?

    All the best, Adi

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 21, 2014 @ 21:01
    Bjarne Fyrstenborg
    1

    Hi Adi..

    Yes, because MediaById is related to media nodes..
    If you should use multiple tab, you should check which tab the item belongs to first, where you check for the state "Content", "Media", "URL" og "Upload".

    Take a look at this example at the bottom of the page: http://ucomponents.org/data-types/url-picker/

     

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 22, 2014 @ 13:27
    Bjarne Fyrstenborg
    0

    Hi Adi

    I took a look at it and if you want to use more than just the Media tab you could change the code to this:

    @inherits umbraco.MacroEngines.DynamicNodeContext
    @using uComponents.DataTypes.UrlPicker;
    @using uComponents.DataTypes.MultiUrlPicker.Dto;
    
    @{
        bool hasAttachments = false;
        if(!Model.IsNull("attachments"))
        {
            if(Model.HasValue("attachments"))
            {
                hasAttachments = Model.attachments.Items.Count > 0 ? true : false;
            }
        }
    
        if (hasAttachments)
        {
            MultiUrlPickerState attachments = MultiUrlPickerState.Deserialize(Model.GetPropertyValue("attachments"));
    
            int index = 0;
            <table class="attachments">
                <caption>Attachments:</caption>
            @foreach (var link in attachments.Items)
            {
                string target = link.NewWindow ? " target=\"_blank\"" : "";
    
                string oddeven = index % 2 == 0 ? "odd" : "even";
                string cssClass = "class=" + oddeven + "";
    
                string path = "";
                int pos = 0;
                string linkName = "";
    
                string fileSize = "";
    
                <tr @cssClass>
                    <td>
                        @switch ((UrlPickerMode)link.Mode)
                        {
                            case UrlPickerMode.Content:
                                <a href="@Library.NodeById(link.NodeId).Url"@Html.Raw(target)>@(string.IsNullOrWhiteSpace(link.Title) ? Library.NodeById(link.NodeId).Name : link.Title)</a>
                                break;
    
                            case UrlPickerMode.Media:
                                var chosenMedia = Library.MediaById(link.NodeId);
                                fileSize = FormatFileSize(Convert.ToDouble(@chosenMedia.umbracoBytes));
                                <a href="@chosenMedia.umbracoFile"@Html.Raw(target)>@(string.IsNullOrWhiteSpace(link.Title) ? chosenMedia.Name : link.Title)</a>
                                break;
    
                            case UrlPickerMode.Upload:
                                path = link.Url;
                                pos = path.LastIndexOf("/") + 1; 
                                <a href="@path"@Html.Raw(target)>@link.Title</a>
                                break;
    
                            case UrlPickerMode.URL:
                                path = link.Url;
                                pos = path.LastIndexOf("/") + 1; 
                                linkName = string.IsNullOrWhiteSpace(link.Title) ? path.Substring(pos, path.Length - pos) : link.Title;
                                <a href="@path"@Html.Raw(target)>@linkName</a>
                                break;
                        }
                    </td>
                    <td>[ ]</td>
                    <td class="pull-right">@fileSize</td>
                </tr>
                index++;
            }
            </table>
        }
    
    }
    
    
    @functions{ 
    
        private string FormatFileSize(double size) {
            string fileSizeFormatted = "";
            if (Convert.ToUInt64(size) < 1048576)
            {
                fileSizeFormatted = ((Math.Round(Convert.ToDecimal(size) / 1024, 0)).ToString() + " KB");
            }
            else
            {
                fileSizeFormatted = ((Math.Round(Convert.ToDecimal(size) / 1048576, 2)).ToString() + " MB");
            }
    
            return fileSizeFormatted;
        }
    
    }

    And you get an output like this:

    However notice that umbracoBytes is related to Media, so when link to a file via URL and using Upload tab, you don't know it's filesize..
    With URL I have used a fallback to the filename there is linked to if the Title textfield is empty.

    /Bjarne

  • Adi 79 posts 183 karma points
    Jan 22, 2014 @ 22:44
    Adi
    0

    Hello Bjarne,

    this code update is great! I will analyse and test it little more and let you now how it works after testing.

    Thank you, Adi

  • Bjarne Fyrstenborg 1280 posts 3990 karma points MVP 7x c-trib
    Jan 24, 2014 @ 22:53
    Bjarne Fyrstenborg
    0

    You are welcome :) .. remember to mark the answer as solved if you find it useful and it solved your questions :)

    /Bjarne

Please Sign in or register to post replies

Write your reply to:

Draft