Pagina Unica
  •   Manuel
  •   12 Jul 2024

En este tutorial, te mostraré cómo construir un sitio web de página única en Umbraco utilizando BlockList. A través de unos sencillos pasos, podrás crear una estructura flexible y dinámica para tu sitio web, facilitando la gestión de contenido desde el back-office.

1. Configuración del Entorno

Primero, asegúrate de tener instalado Umbraco en tu entorno de desarrollo. Puedes seguir la documentación oficial de Umbraco para configurar tu sitio. O seguir los primeros pasos del blog Crear una Página de Espera en Umbraco

2. Creación de Tipos de Datos

Antes de crear los documentos, necesitamos configurar algunos tipos de datos personalizados.

tipos de datos

2.1. Estilo de Foto

Estilo de foto

  1. En el back-office de Umbraco, dirígete a Settings (Configuración) > Data Types (tipos de datos).
  2. Crea un nuevo tipo de dato llamado Estilo de Foto.
  3. Selecciona Radio button list como el editor.
  4. Añade los valores: Original, Panoramica, Retrato.

2.2. Elementos por fila

Elementos por fila

  1. En el back-office de Umbraco, dirígete a Settings (Configuración) > Data Types (tipos de datos).
  2. Crea un nuevo tipo de dato llamado Elementos por fila.
  3. Selecciona Slider como el editor.
  4. Configura el initial value a 1, el minimum value a 1, el maximum value a 4, y el step increment a 1.

2.3. Contenido (primero completar punto 3.2. Bloque de Tarjetas y luego retornar a éste punto 2.3)

Tipo de dato - Contenido

  1. En el back-office de Umbraco, dirígete a Settings (Configuración) > Data Types (tipos de datos).
  2. Crea un nuevo tipo de dato llamado Contenido.
  3. Selecciona Block List como el editor.

2.4. Tarjeta (primero completar punto 3.1. Tarjeta y luego retornar a éste punto 2.4)

Tarjeta - tipo de dato

  1. En el back-office de Umbraco, dirígete a Settings (Configuración) > Data Types (tipos de datos).
  2. Crea un nuevo tipo de dato llamado Tarjeta.
  3. Selecciona Block List como el editor.

3. Creación de Tipos de Documentos

A continuación, vamos a crear los tipos de documentos necesarios.

Tipos de documentos

3.1. Tarjeta

Tarjeta - tipos de documentos

  1. En el back-office de Umbraco, dirígete a Settings (Configuración) > Document Types.
  2. Crea un nuevo tipo de documento (Tipo de Elemento) llamado Tarjeta.
  3. Añade las siguientes propiedades:
    • Foto: Medios
    • EstiloDeFoto: Estilo de Foto (Radio button list)
    • Titulo: Texto
    • Subtitulo: Texto
    • Icono: Texto
    • Texto: Texto Rico
    • Enlace: Lista de enlaces

3.2. Bloque de Tarjetas

Bloque de tarjetas - tipos de documentos

  1. En el back-office de Umbraco, dirígete a Settings (Configuración) > Document Types.
  2. Crea un nuevo tipo de documento (Tipo de Elemento) llamado Bloque de Tarjetas.
  3. Añade las siguientes propiedades:
    • NumeroDeTarjetasPorFila: Elementos por fila (Slider)
    • BordeYsombra: Booleano
    • ColorDeFondo: Booleano
    • AnchoCompleto: Booleano
    • Titulo: Texto
    • Tarjetas: Tarjeta (Block List)

3.3. Bloque de Contenido

Bloque de contenido - tipo de documento

  1. En el back-office de Umbraco, dirígete a Settings (Configuración) > Document Types.
  2. Crea un nuevo tipo de documento (Tipo de Elemento) llamado Bloque de Contenido.
  3. Añade la propiedad:
    • Contenido: Contenido (Block List)

3.4. Pájina (Pages) - Inicio

Inicio - tipo de documento

Inicio - tipo de documento

  1. En el back-office de Umbraco, dirígete a Settings (Configuración) > Document Types.
  2. Crea un nuevo tipo de documento (con Plantilla) llamado Inicio.
  3. Añade la propiedad haciendo un click en Composiciones:
    • Contenido: Contenido (Block List)
  4. Para el menú navegador, agrega una pestaña o un grupo y añade una propiedad con el nombre de Menú y usa un Multi Url Picker.
  5. Hacer un click en Permissions y seleccionar "Permitir como Raíz"
  6. En el menu de arriba navega a Contenido (Content), haz un click sobre los tres puntos y crea una instancia de Inicio

Inicio - Menú

4. Creación de las Vistas

Ahora que tenemos nuestros tipos de documentos y datos configurados, vamos a crear las vistas correspondientes en la carpeta Views.

Plantilla

BloqueDeTarjetas.cshtml

Este archivo definirá el contenedor principal para nuestras tarjetas. Crea un archivo llamado BloqueDeTarjetas.cshtml en la carpeta Views.

@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockListItem>
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels

@{
    var content = (ContentModels.BloqueDeTarjetas)Model.Content;
    var columnas = content.NumeroDeTarjetasPorFila;
    var bordeYsombra = content.BordeYsombra ? "card shadow-sm" : string.Empty;
    var colorDeFondo = content.ColorDeFondo ? "bg-light" : string.Empty;
    var anchoCompleto = content.AnchoCompleto ? "container-fluid" : "container";
}

<div class="album py-5 @colorDeFondo" id="@content.Titulo" data-height="@content.Key">
    <div class="@anchoCompleto">
        <h2>@content.Titulo</h2>
        <div class="row row-cols-1 row-cols-sm-@(columnas == 1 ? columnas : "2") row-cols-md-@columnas g-@columnas">
            @foreach (var block in content.Tarjetas)
            {
                <div class="col">
                    <div class="@bordeYsombra">
                        @Html.Partial($"blocklist/Components/{block.Content.ContentType.Alias}", block)
                    </div>
                </div>
            }
        </div>
    </div>
</div>

Tarjeta.cshtml

Este archivo definirá cada tarjeta individual. Crea un archivo llamado Tarjeta.cshtml en la carpeta Views.

@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockListItem>
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels

@{
    var content = (ContentModels.Tarjeta)Model.Content;
}

@if (content.Foto != null)
{
    if (content.HasValue("estiloDeFoto"))
    {
        var estiloDeFoto = content.EstiloDeFoto;           
        if (!string.IsNullOrEmpty(estiloDeFoto) && estiloDeFoto != "Original")
        {
            <img src="@content.Foto.GetCropUrl(@estiloDeFoto)" class="card-img-top" alt="@content.Foto.Name">
        }
        else
        {
            <img src="@content.Foto.Url()" class="card-img-top" alt="@content.Foto.Name">
        }
    }
    else
    {
        <img src="@content.Foto.Url()" class="card-img-top" alt="@content.Foto.Name">
    }
}

<div class="card-body">
    @if (!string.IsNullOrEmpty(content.Titulo))
    {
        <h3 class="my-3">@content.Titulo</h3>
    }
    @if (!string.IsNullOrEmpty(content.Subtitulo))
    {
        <h5 class="my-3">@content.Subtitulo</h5>
    }
    @if (!string.IsNullOrEmpty(content.Icono))
    {
        <div class="d-flex justify-content-center text-primary" style="font-size:6rem;">
            @Html.Raw(content.Icono)            
        </div>
    }
    @Html.Raw(content.Texto)

    @if (content.Enlace != null && content.Enlace.Any())
    {
        <div class="d-flex @(!string.IsNullOrEmpty(content.Icono) ? "justify-content-center" : "justify-content-start")">
            <div class="btn-group">
                @foreach (var item in content.Enlace)
                {
                    <a href="@item.Url" class="btn btn-primary">@item.Name</a>
                }
            </div>
        </div>
    }
</div>

5. Renderización de Bloques en la Página de Inicio

Para renderizar los bloques en tu página de inicio, usa el siguiente código en la vista de la página de inicio (Inicio.cshtml).

Inicio.cshtml

@using Umbraco.Cms.Web.Common.PublishedModels
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.Inicio>
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels

@{
    Layout = null;
}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
    <meta name="generator" content="Hugo 0.84.0">
    <title>Mano a mano</title>

    <link rel="canonical" href="https://getbootstrap.com/docs/5.0/examples/starter-template/">    

    <!-- Bootstrap core CSS -->
    <link href="https://getbootstrap.com/docs/5.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
    <!-- Favicons -->
    <link rel="icon" href="https://getbootstrap.com/docs/5.0/assets/img/favicons/favicon.ico">
  </head>
  <body>
  <main>
        <div class="container">
            <header class="d-flex flex-wrap align-items-center justify-content-center justify-content-md-between py-3 mb-4 border-bottom">
                
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hand-thumbs-up-fill" viewBox="0 0 16 16">
                    <path d="M6.956 1.745C7.021.81 7.908.087 8.864.325l.261.066c.463.116.874.456 1.012.965.22.816.533 2.511.062 4.51a10 10 0 0 1 .443-.051c.713-.065 1.669-.072 2.516.21.518.173.994.681 1.2 1.273.184.532.16 1.162-.234 1.733q.086.18.138.363c.077.27.113.567.113.856s-.036.586-.113.856c-.039.135-.09.273-.16.404.169.387.107.819-.003 1.148a3.2 3.2 0 0 1-.488.901c.054.152.076.312.076.465 0 .305-.089.625-.253.912C13.1 15.522 12.437 16 11.5 16H8c-.605 0-1.07-.081-1.466-.218a4.8 4.8 0 0 1-.97-.484l-.048-.03c-.504-.307-.999-.609-2.068-.722C2.682 14.464 2 13.846 2 13V9c0-.85.685-1.432 1.357-1.615.849-.232 1.574-.787 2.132-1.41.56-.627.914-1.28 1.039-1.639.199-.575.356-1.539.428-2.59z" />
                </svg>
                <ul class="nav col-12 col-md-auto mb-2 text-end mb-md-0">
                    
                    @if (Model.Menu.Any())
                    {
                        foreach (var menu in Model.Menu)
                        {
                            <li><a href="@menu.Url" class="nav-link px-2 link-secondary">@menu.Name</a></li>
                        }    
                    }
                </ul>
            </header>
        </div>
    @foreach (var block in Model.Contenido)
    {
        @Html.Partial($"blocklist/Components/{block.Content.ContentType.Alias}", block)
    }            

  </main>
  <footer class="pt-5 pb-5 my-5 text-muted border-top">
          <div class="container pb-5 pt-5 my-5">
            &copy;Mano a mano 2024
        </div>
  </footer>

    <script src="https://getbootstrap.com/docs/5.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

    <script>
        const parentDiv = document.querySelector('[data-height]'); 
        const cardElements = parentDiv.querySelectorAll('.card'); /
        let maxHeight = 0;
        // Calculate the maximum height among the child elements
        cardElements.forEach(function (card) {
            const height = card.offsetHeight;
            maxHeight = Math.max(maxHeight, height);
        });
        // Set the height of each child element to the maximum height
        cardElements.forEach(function (card) {
            card.style.height = maxHeight + 'px';
        });
    </script>

  </body>
</html>

Conclusión

Siguiendo estos pasos, has creado un sitio web de página única en Umbraco usando BlockList. Esta configuración te permite gestionar tu contenido de manera flexible y eficiente desde el back-office de Umbraco, proporcionando una estructura modular que puede adaptarse fácilmente a futuros cambios.