Listing recently modified pages - umbraco

How would I list URLs of recently modified pages on an Umbraco website?
Preferably with mod date and author.

All documents have information like created/updated timestamps so in Razor you could do something like this...
Razor Example:
var root = Model.AncestorOrSelf();
var documents = root.Descendants().OrderBy("UpdateDate desc").Take(10);
<ul>
#foreach (var doc in documents)
{
<li>#string.Format("{0} - Updated by {1} on {2}", doc.Name, doc.WriterName, doc.UpdateDate)</li>
}
</ul>
Note that I am not 100% sure that the WriterName property is updated with each publish so just check that.

Related

Umbaco Archtype rendering images (MediaPicker2)

I'm building a image slider using Archtype in Umbraco.
I was using umbraco 7.5.9 and Umbraco.MediaPicker when I started this but in the mean time I started a new project with the newest version Umbraco (7.6.2) which uses Umbraco.MediaPicker2
It was no problem rendering images with the old MediaPicker but with the MediaPicker2 it seems impossible.
Here is my setup.
The Archtype:
Here is the partial view that rendered the old MediaPicker
<div class="fullWidthSlider">
#foreach (var image in #CurrentPage.SliderImages)
{
<div>Id: #image.GetValue("image")</div>#*Line added for debug*#
var media = #Umbraco.Media(image.GetValue("image"));
<img src="#media.Url" />
}
</div>
This used to work for the old Media picker and the #image.GetValue returned int id. But with the new MediaPicker2 it returns Umbraco.Core.Udi[]
If I foreach through the properties of the archtype with the code below I get this result (see below code)
#foreach (var fieldset in Model.Content.GetPropertyValue<ArchetypeModel>("sliderImages"))
{
foreach(var prop in fieldset.Properties){
<p>#prop.Alias - #prop.Value</p>
}
}
href -
altText - alt test
image - umb://media/c33bfe07a82b4df18a79db154139cb91
href -
altText - Fjall
image - umb://media/40d5778d34bb4035b5146c901de75212
Can anyone tell me how I can render image from this data.
Thanks
I just went on a roller-coaster figuring this out!
You can get an IPublishedContent from your image string using this code:
// Your string which is retrieved from Archetype.
var imageString = "umb://media/c33bfe07a82b4df18a79db154139cb91";
// Get the guid from this string.
var imageGuidUdi = GuidUdi.Parse(imageString);
// Get the ID of the node!
var imageNodeId = ApplicationContext.Current.Services.EntityService.GetIdForKey(guidUdi.Guid, (UmbracoObjectTypes)Enum.Parse(typeof(UmbracoObjectTypes), guidUdi.EntityType, true));
// Finally, get the node.
var imageNode = Umbraco.TypedMedia(imageNodeId.Result);
Check out this thread on Our Umbraco which covers this issue.
I used this comment to figure out how to get the ID from the image's guid.
It looks like Umbraco HQ is pushing for people to use the new ModelsBuilder with typed models. I'm not sure if Archetype is supported by the ModelsBuilder which is why there's so much trouble.
I personally use Nested Content on all of my projects as it performs the same functionality but (IMO) is better supported by Umbraco because it uses Document Types to store repeatable content schema. Because of this, it can then easily be mapped to IPublishedContent and therefore is supported by the ModelsBuilder!

Randomly selecting an image from a folder in Umbraco

I have created a folder in Umbraco and I would like to display a random image from that folder on my page.
I found a solution from a few years ago which was giving me compile errors
dynamic folder = Library.MediaById(1054);
var randomImage = folder.Children.Where("nodeTypeAlias = \"Image\"").Random();
I found that I have to add the proper inherits in my file
#using umbraco.MacroEngines
#inherits DynamicNodeContext
but this it gives me an error because I already have a #model I'm using in the first line
The 'inherits' keyword is not allowed when a 'model' keyword is used.
Thanks for any help
You can take a look and learn from sample macro partial views pre-installed in each Umbraco website. There is a snippet called List Images From Media Folder.
The code of the default snippet looks like this:
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#*
Macro to display a series of images from a media folder.
How it works:
- Confirm the macro parameter has been passed in with a value
- Loop through all the media Id's passed in (might be a single item, might be many)
- Display any individual images, as well as any folders of images
Macro Parameters To Create, for this macro to work:
Alias:mediaId Name:Select folder with images Type:Single Media Picker
*#
#{ var mediaId = Model.MacroParameters["mediaId"]; }
#if (mediaId != null)
{
#* Get all the media item associated with the id passed in *#
var media = Umbraco.Media(mediaId);
var selection = media.Children("Image");
if (selection.Any())
{
<ul>
#foreach (var item in selection)
{
<li>
<img src="#item.umbracoFile" alt="#item.Name" />
</li>
}
</ul>
}
}
We need to remember to add the parameter to macro if we're using them there.
Then we can use both: Media or TypedMedia helper methods to retrieve folder (which is typical media item with different type), despite of the required returned type. I usually use TypedMedia to be able to operate on strongly typed object and preview properties in Visual Studio.
If we create macro properly and insert it on the template using code like this (with proper folder ID):
#Umbraco.RenderMacro("Test", new { mediaId="1082" })
we should see a list of images from this folder (all of them at that moment).
The final part is almost the same as you previously did it, but we need to adjust it a little bit. My final code and suggestion is below:
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#{
var folderId = Model.MacroParameters["mediaId"];
if (folderId != null)
{
var media = Umbraco.TypedMedia(folderId);
var rand = new Random();
var imagesInFolder = media.Children("Image");
if(imagesInFolder.Any()) {
var pick = imagesInFolder.ElementAt(rand.Next(0, imagesInFolder.Count()));
if (pick != null)
{
<img src="#pick.GetCropUrl()" alt="#pick.Name" />
}
}
}
}
Let me know if it solved your problem :)

What should be the standard coding pattern for Sitecore

Using Sitecore 8.0, MVC, VS2015
I managed to generate the footer content as desired, for a practice site, but would like to know the standard way of doing things. The question is simple, but tried to explain in detail. Please bear with that :)
Requirement: The footer should display Office addresses and they should be editable by the Content author.
Sitecore Template : Location, Telephone 1, Telephone 2, IsActive(type-checkbox).
Datasource : A folder with items of the above template.
Code:
public class FooterViewModel
{
public List<Sitecore.Data.Items.Item> Addresses { get; set; }
}
public class FooterController : Controller
{
public ActionResult Footer()
{
var datasource = RenderingContext.Current.Rendering.Item;
FooterViewModel viewModel = new FooterViewModel();
viewModel.Addresses = new List<Item>();
if(datasource != null && datasource.HasChildren && datasource.Children.Count > 0)
{
foreach(Item address in datasource.Children)
{
if (address["IsActive"] == "1")
viewModel.Addresses.Add(address);
}
}
return View("~/Views/Shared/Footer.cshtml", viewModel);
}
}
Rendering the html using a Sitecore Controller Rendering
cshtml:
#using Sitecore.Mvc
#using Sitecore.Mvc.Presentation
#model Democore.Models.FooterViewModel
<div>
#foreach (var address in Model.Addresses)
{
<div>
<h3>#Html.Sitecore().Field("Location", address)</h3>
<ul>
<li>
#Html.Sitecore().Field("Telephone 1", address)
</li>
<li>
#Html.Sitecore().Field("Telephone 2", address)
</li>
</ul>
</div>
}
</div>
<div>
<p>&copy Copyright #DateTime.Now.Year. All rights reserved</p>
</div>
Here are my questions. (..well all 3 are more or less similar)
How to better this code/structure (or) in which case might it fail.
I did not like the way I hardcoded the field names in controller &
cshtml. What if the author changes the field names. How to tackle
that.
How does it work in a real scenario, say for eg if author
wants to show a third phone number. Will they contact the developer?
Because that requires a change in design & code too right?
This is a very broad question and will probably get closed -but here are some tips!
You controller is fine as far as error handling goes. You really want to add a global error handler for your site. This is a good example of that: http://www.sitecorenutsbolts.net/2015/10/23/Rendering-Exception-Handling-The-Right-Way/
You have 2 options - use constants and field ID's not the names, not a great option but works. A better option would be to use an ORM/Wrapper to do that. Two good ones are Fortis and Glass Mapper - both are very good - I contribute to Fortis so that would be my recomendation.
Normally if the design of the component changes it will require development support. You could use something like BrainJock's Score or ZenGarden to build your site and then the editor has a lot more control. But still likely would need a developer.
Hope this helps. For some info on good Sitecore architecture look here: Sitecore Helix and Sitecore Habitat

Filter on PropertyTypeAlias in Umbraco 7

I have a Content Repository which contains 2 sections, Career Categories and Branches.
I have create for each one a filter, below you can find the code for Career categories. This is working fine. Now I want to display the amount of visible content nodes for each item of the filter.
The content node contains 2 properties which are content pickers set to only select one.
Property alias for the Career category picker is function.
This doesn't work which give me always 0, but I have created one content page. What am I missing here?
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#*
This snippet takes all of the career categories to create a filter
*#
#{
// Take the content repository node
IPublishedContent contentRepository = Umbraco.ContentAtRoot().DescendantsOrSelf("ContentElements").FirstOrDefault();
// Take the career categories node
var careerCategorieRep = contentRepository.Children.Where("DocumentTypeAlias == \"ucCareersCategoryRepository\"").FirstOrDefault();
// Take the careers list content node
IPublishedContent careersList = Umbraco.ContentAtRoot().DescendantsOrSelf("CareersList").FirstOrDefault();
}
<ul class="col-md-12 col-sm-6 aside-widget-container">
<li class="widget">
<div class="title">
<h3>Beroep</h3>
</div>
<ul class="menu">
#* // Loop over the categories *#
#foreach (var careerCategorie in careerCategorieRep.Children.Where("Visible").OrderBy("Name").ToList())
{
// Here I need to filter on the career category to get the amount of visible nodes in the content
var count = careersList.Children.Where("Visible && function == " + careerCategorie.Id).Count();
<li>#careerCategorie.Name<i class="fa fa-angle-right"></i></li>
}
</ul>
</li>
</ul>
UPDATE
The problem is in this line of code:
var count = careersList.Children.Where("Visible && function == " + careerCategorie.Id).Count();
I need to get the amount of visible pages which has a certain property value, eg. content picker with Id of the career category.
First of all, you should probably be using TypedContentAtRoot and not ContentAtRoot. TypedContent is retrieved from the Umbraco.config xml cache rather than the database so should be faster.
From your explanation I think you are saying that this line is the problem
var careerCategorieRep = contentRepository.Children.Where("DocumentTypeAlias == \"ucCareersCategoryRepository\"").FirstOrDefault();
Change it to
var contentRepository.Children.FirstOrDefault(n => n.DocumentTypeAlias == "ucCareersCategoryRepository");
That should do it.
Okay my other answer has some good advice but I think your problem may be something else.
if you are searching for Visible nodes this relies on a property on your document type called umbracoNaviHide. The property should be of a true/false datatype.
You have to add this property to the doc type and then set it to true (checked) if you wish to hide a node.
Then you can use either
myNode.Children.Where("Visible")
OR (just to show the way in which you can write lambda filter expressions)
myNode.Children.Where(x => x.IsVisible())
OR (this last just to illustrate that umbracoNaviHide is just a property on a doc type)
myNode.Children.Where(x => x.GetPropertyValue<string>("umbracoNaviHide")=="1")
Ok I have found the solution:
I needed to surround the Id with quotes because its stored as a string and not as a int.
var count = careersList.Children.Where("Visible && function == \"" + careerCategorie.Id + "\"").Count();

How to show umbraco multiple media picker images on page with a macro

Hello stackoverflow people
hope you can help me with maybe a simple question, but couldn't find a solution elsewhere and I have just been working with umbraco for a week now and have never used the mvc part before so all is new for me.
So the big problem is how I make a macro to show these images I choose from the multiple media picker the macro should just end with showing.
<img src="img1.gif" height="50" width="50">
<img src="img2.gif" height="50" width="50">
And so on depending on how many images there is. (the size is just an exempel)
I tryed somthing like this
#var selectedMedia3 = #Library.MediaById(Model.mainImage);
<img src="#selectedMedia3.umbracoFile" width="#selectedMedia3.umbracoWidth" height="#selectedMedia3.umbracoHeight" alt="#selectedMedia3.Name"/>
}
But I dont know how to parse the id of the image to the macro.
and when I choose more than one file I need a loop, but dont know how to loop the multiple media picker data, so im a little lost by now.
Are you able to let us know what version of Umbraco you are using. Umbraco has gone through a number of fundemental changes in various version over recent years. The below code should guide you in the right direction for Umbraco 7 Multiple Image picker with the propertyAlias partnersLogos.
#if (Model.Content.HasValue("partnersLogos"))
{
var partnersImagesList = Model.Content.GetPropertyValue<string>("partnersLogos").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse);
var partnersImagesCollection = Umbraco.TypedMedia(partnersImagesList).Where(x => x != null);
foreach (var partnerImage in partnersImagesCollection)
{
<img src="#partnerImage.Url" alt="partners logo" />
}
}
If anyone makes the same mistake as me and doesn't realise that there is a difference between the now obsolete media picker and the new media picker "Umbraco.MediaPicker2" (true from at least 7.6.1) then please read the documentation on Umbraco's web site.
https://our.umbraco.org/documentation/Getting-Started/Backoffice/Property-Editors/Built-in-Property-Editors/Media-Picker2
#{
var typedMultiMediaPicker = Model.Content.GetPropertyValue<IEnumerable<IPublishedContent>>("sliders");
foreach (var item in typedMultiMediaPicker)
{
<img src="#item.Url" style="width:200px"/>
}
}
I'm not really sure if you question is how to setup MVC within umbraco or getting values from an image picker.
But if you want to start up with MVC in umbraco check this out: http://24days.in/umbraco/2013/creating-reusable-code-in-mvc-apps/

Resources