Un servicio de subscripción al boletín Pt. M SK1 | - Requisitos y página de subscription (Español (Spanish))

Un servicio de subscripción al boletín Pt. M SK1 | - Requisitos y página de subscription

Saturday, 21 September 2024

//

15 minute read

El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer.

Durante el examen de los blogs de otras personas' he observado que muchos de ellos tienen un servicio de subscripción que permite a los usuarios registrarse para recibir una e-mail semanal con los mensajes de ese blog. Decidí poner en práctica mi propia versión de esto y compartir cómo lo hice.

Nota: No creo que nadie lo utilice realmente'No creo que alguien lo utilicen realmente , Tengo mucho tiempo en mis manos después de que se cayó un contrato, así que esto me mantiene ocupadoM SK3

El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer.

Así que para crear este servicio he decidido sobre las siguientes exigencias.

  1. Una página de abono flexible que permite a los usuarios cierta flexibilidad.
    1. Los usuarios sólo envían el correo electrónico.
    2. La capacidad de seleccionar el idioma del correo electrónico.
    3. La capacidad de seleccionar la frecuencia del correo electrónico.
      • Si el mes selecciona el día del mes es's enviadoM SK1
      • Si Weekly selecciona el día de la semana es's enviado.
      • Aprobación del programa y otras cuestiones de organización
      • Permitir la publicación automática para enviar un correo cada vez que escribo un blog.
    4. Permite al usuario seleccionar las categorías que le interesan
  2. El Comité recomienda que el Estado Parte adopte todas las medidas necesarias para garantizar la igualdad de oportunidades entre hombres y mujeres en materia de empleo, incluida la eliminación del trabajo forzoso.
  3. Permitir una vista preliminar del correo que recibirán'
  4. Permitir al usuario cambiar sus preferencias en cualquier momento.
  5. Un servicio separado que maneja el envío de correos electrónicos.
    • Este servicio será llamado por el servicio de blog cada vez que se hace un nuevo post.
    • Este servicio enviará entonces el correo electrónico a todos los abonados.
    • Usará Hangfire para programar el envío de correos electrónicos.

El impacto de esto es que tengo mucho trabajo que hacer.

La página de Subscripción

He comenzado con la parte divertida, escribir una página de subscripción. Quisiera que esto funcionase bien en el escritorio así como en los navegadores móviles M SK2y incluso el El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer.El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer. El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer. Por ejemplo, en el caso de los países en desarrollo sin litoral y los pequeños Estados insulares en desarrollo (PMA), la proporción de personas que viven con el VIH/SIDA es muy baja.

El Comité recomienda que el Estado Parte adopte todas las medidas necesarias para garantizar la igualdad de oportunidades entre los hombres y las mujeres en materia de empleo, incluida la eliminación del trabajo forzoso.

También quería que la página de Subscripción fuera obvia sobre cómo usar; IM SK1 soy un gran creyente en El Presidente (habla en inglés): Doy las gracias al representante de la República Islámica del Irán por su declaración. a) En el párrafo 2 de la parte dispositiva del proyecto de resolución A/C.3/60/L.39, la Asamblea General pidió al Secretario General que le presentara en su quincuagésimo séptimo período de sesiones un informe sobre los progresos realizados en la aplicación de las recomendaciones formuladas por la Comisión Consultiva en Asuntos Administrativos y de Presupuesto;

Esto significa que los parámenes por defecto deberían ser la mayoría de los usuarios que quieran usar. Decidí sobre los siguientes parámetros por defectos:

  1. El Presidente (habla en inglés): De conformidad con el entendimiento alcanzado en las consultas previas del Consejo, consideraré que la Asamblea General desea concluir su examen de este tema del programa.
  2. El Comité recomienda que el Estado Parte adopte todas las medidas necesarias para garantizar la igualdad de oportunidades entre hombres y mujeres en materia de empleo, incluida la adopción de medidas legislativas, administrativas, judiciales y de otra índole.
  3. El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer.
  4. El Presidente interino (habla en inglés): De conformidad con el entendimiento alcanzado en las consultas previas del Consejo, consideraré que la Asamblea General desea concluir su examen de este tema del programa.

Por supuesto, puedo cambiar esto más tarde si se demuestra que son incorrectos.

Así que esta es la página que he construido:

El Comité recomienda que el Estado Parte adopte todas las medidas necesarias para garantizar la igualdad de oportunidades entre los hombres y las mujeres en materia de empleo, incluida la asignación de recursos suficientes al sector privado.

El código para la página

Como con el resto de este sitio quería hacer el código tan simple como sea posible. Usa los siguientes HTML:

Subscription Page
@using Mostlylucid.Shared
@using Mostlylucid.Shared.Helpers
@model Mostlylucid.EmailSubscription.Models.EmailSubscribeViewModel

<form x-data="{schedule :'@Model.SubscriptionType'}" x-init="$watch('schedule', value => console.log(value))" hx-boost="true" asp-action="Save" asp-controller="EmailSubscription" 
      hx-target="#contentcontainer" hx-swap="#outerHTML">
    <div class="flex flex-col mb-4">
        <div class="flex flex-wrap lg:flex-nowrap lg:space-x-4 space-y-4 lg:space-y-0 items-start">
            <label class="input input-bordered flex items-center gap-2 mb-2 dark:bg-custom-dark-bg bg-white w-full lg:w-2/3">
                <i class='bx bx-envelope'></i>
                <input type="email" class="grow text-black dark:text-white bg-transparent border-0"
                       asp-for="Email" placeholder="Email (optional)"/>
            </label>
            <div class="grid grid-cols-2 sm:grid-cols-[repeat(auto-fit,minmax(100px,1fr))] w-full lg:w-1/3">
                @{
                    var frequency = Enum.GetValues(typeof(SubscriptionType)).Cast<SubscriptionType>().ToList();
                }
                @foreach (var freq in frequency)
                {
                    <div class="flex items-center w-auto h-full min-h-[30px] lg:mb-0 mb-3">
                        <input x-model="schedule" id="@freq" type="radio" value="@freq.ToString()" name="SubscriptionType" class="hidden peer">
                        <label for="@freq" class="ml-2 text-sm font-medium text-white 
                bg-blue-dark border-gray-light border rounded-xl px-1 py-2 w-full 
                peer-checked:text-blue-600 peer-checked:dark:bg-green text-center justify-center">
                            @freq.EnumDisplayName()
                        </label>
                    </div>
                }
            </div>
        </div>
        @{
            var languages = LanguageConverter.LanguageMap;
        }

        <div class="grid grid-cols-[repeat(auto-fit,minmax(85px,1fr))] mt-4 gap-2 pl-6 large:pl-0 w-auto">
            @foreach (var language in languages)
            {
                var [email protected] == language.Key ? "checked" : "";
                <div class="tooltip lg:mb-0 mb-2" data-tip="@language.Value)"  >
                    <div class="flex items-center justify-center w-[85px] h-full min-h-[70px]">
                        <input id="@language.Key" type="radio" value="@language.Key" @isChecked name="language" class="hidden peer">
                        <label for="@language.Key" class="flex flex-col items-center justify-center text-sm font-medium text-white bg-blue-dark opacity-50 peer-checked:opacity-100 w-full h-full">
                            <img src="/img/flags/@(language.Key).svg" asp-append-version="true" class="border-gray-light border rounded-l w-full h-full object-cover" alt="@language.Value">
                        </label>
                    </div>

                </div>
            }
        </div>
        <div class="mt-3 border-neutral-400 dark:border-neutral-600 border rounded-lg" x-data="{ hideCategories: false, showCategories: false }">
            <h4
                class="px-5 py-1 bg-neutral-500 bg-opacity-10 rounded-lg font-body text-primary dark:text-white w-full flex justify-between items-center cursor-pointer"
                x-on:click="if(!hideCategories) { showCategories = !showCategories }">
                <span class="flex flex-row items-center space-x-1">
                    Categories
                    <label class="label cursor-pointer ml-4" x-on:click.stop="">
                        all
                    </label>
                    <input type="checkbox" x-on:click.stop="" x-model="hideCategories" asp-for="AllCategories" class="toggle toggle-info toggle-sm" />
                </span>
                <span>
                    <i
                        class="bx text-2xl"
                        x-show="!hideCategories"
                        :class="showCategories ? 'bx-chevron-up' : 'bx-chevron-down'"></i>
                </span>
            </h4>

            <div class="flex flex-wrap gap-2 pt-2 pl-5 pr-5 pb-2"
                x-show="showCategories"
                x-cloak
                x-transition:enter="max-h-0 opacity-0"
                x-transition:enter-end="max-h-screen opacity-100"
                x-transition:leave="max-h-screen opacity-100"
                x-transition:leave-end="max-h-0 opacity-0">
                <div class="grid grid-cols-[repeat(auto-fit,minmax(150px,1fr))] mt-4 w-full">
                    @foreach (var category in Model.Categories)
                    {
                        var categoryKey = category.Replace(" ", "_").Replace(".", "_").Replace("-", "_");
                        <div class="flex items-center w-auto h-full min-h-[50px]">
                            <input id="@categoryKey" type="checkbox" value="@category"  name="@nameof(Model.SelectedCategories)" class="hidden peer">
                            <label for="@categoryKey" class="ml-2 text-sm font-medium text-white 
            bg-blue-dark border-gray-light border rounded-xl px-1 py-2 w-full 
            peer-checked:text-blue-600 peer-checked:dark:bg-green text-center justify-center">
                                @category
                            </label>
                        </div>
                    }
                </div>
            </div></div>


        <div :class="{ 'opacity-50 pointer-events-none': schedule !== 'Weekly' }" class=" mt-2 border-neutral-400 dark:border-neutral-600 border rounded-lg" >
            <h4
                class="px-5 py-1 bg-neutral-500 bg-opacity-10 rounded-lg font-body text-primary dark:text-white w-full flex justify-between items-center cursor-pointer"
               >
                <span class="flex flex-row items-center space-x-1 ">
                    Day of Week to Send On
                    
                  
                </span>
               
            </h4>

        <div class="grid grid-cols-3 sm:grid-cols-[repeat(auto-fit,minmax(80px,1fr))] my-2 w-full lg:w-1/2" x-show="schedule === 'Weekly'">
            @foreach (var day in Model.DaysOfWeek)
            {
                var checkedDay = day.ToString() == Model.Day ? "checked" : "";
                <div class="flex items-center w-auto h-full min-h-[50px]">
                    <input id="@day" type="radio" value="@day" name="day" @checkedDay class="hidden peer">
                    <label for="@day" class="ml-2 text-sm font-medium text-white 
            bg-blue-dark border-gray-light border rounded-xl px-1 py-2 w-full 
            peer-checked:text-blue-600 peer-checked:dark:bg-green text-center justify-center">
                        @day.ToString()
                    </label>
                </div>
            }
        </div>

            </div>
        <div :class="{ 'opacity-50 pointer-events-none': schedule !== 'Monthly' }" class=" mt-2 border-neutral-400 dark:border-neutral-600 border rounded-lg" >
            <h4
                class="px-5 py-1 bg-neutral-500 bg-opacity-10 rounded-lg font-body text-primary dark:text-white w-full flex justify-between items-center cursor-pointer">
                <span class="flex flex-row items-center space-x-1 ">
                    Day of Month to Send On
                </span>
            </h4>
            <div class="grid grid-cols-[repeat(auto-fit,minmax(35px,1fr))] w-full mx-2" x-show="schedule === 'Monthly'">
                @for(int i=1; i<32; i++)
                {
                    var checkedMonthDay = i == Model.DayOfMonth ? "checked" : "";
                    <div class="flex items-center w-auto my-2 h-full min-h-[35px]">
                        <input id="Day_@i" type="radio" value="@i" name="daypfmonth" @checkedMonthDay class="hidden peer">
                        <label for="Day_@i" class="ml-2 text-sm font-medium text-white 
            bg-blue-dark border-gray-light border rounded-xl px-1 py-2 w-full 
            peer-checked:text-blue-600 peer-checked:dark:bg-green text-center justify-center">
                             @i.GetOrdinal()
                        </label>
                    </div>
                }
            </div>
        </div>
        @* Action Buttons *@
        <div class="flex flex-row gap-2 mt-4">
            <button type="submit" class="btn btn-primary">Subscribe</button>
            <button type="reset" class="btn-warning btn">Reset</button>
        </div>
    </div>
</form>
Usted puede ver que esto es bastante simple como va. Utiliza Alpine.js para manejar todas las interacciones de usuario y un elemento UI común para todas las seleccionesM SK2
<div class="grid grid-cols-2 sm:grid-cols-[repeat(auto-fit,minmax(100px,1fr))] w-full lg:w-1/3">
 @{
var frequency = Enum.GetValues(typeof(SubscriptionType)).Cast<SubscriptionType>().ToList();
 }
 @foreach (var freq in frequency)
{
<div class="flex items-center w-auto h-full min-h-[30px] lg:mb-0 mb-3">
     <input x-model="schedule" id="@freq" type="radio" value="@freq.ToString()" name="SubscriptionType" class="hidden peer">
      <label for="@freq" class="ml-2 text-sm font-medium text-white 
                bg-blue-dark border-gray-light border rounded-xl px-1 py-2 w-full 
                peer-checked:text-blue-600 peer-checked:dark:bg-green text-center justify-center">
                            @freq.EnumDisplayName()
      </label>
</div>
}
</div>

Usted puede ver que esto es basado en CSS, utilizando el marco de Tailwind CSS 's peer Utilidad CSS para especificar que cuando se haga clic en el etiquetado se debe establecer la propiedad comprobada de entrada's y cambiarla

Utilizo esto más tarde en la página para determinar qué selector (Día de semana /Dia del mesM SK2 hacer disponible a los usuarios SSK3 mostrar los elementos que permiten la selección.

<div :class="{ 'opacity-50 pointer-events-none': schedule !== 'Monthly' }" class=" mt-2 border-neutral-400 dark:border-neutral-600 border rounded-lg" >
   <h4
       class="px-5 py-1 bg-neutral-500 bg-opacity-10 rounded-lg font-body text-primary dark:text-white w-full flex justify-between items-center cursor-pointer">
       <span class="flex flex-row items-center space-x-1 ">
           Day of Month to Send On
       </span>
   </h4>
   <div class="grid grid-cols-[repeat(auto-fit,minmax(35px,1fr))] w-full mx-2" x-show="schedule === 'Monthly'">
       @for(int i=1; i<32; i++)
       {
           var checkedMonthDay = i == Model.DayOfMonth ? "checked" : "";
           <div class="flex items-center w-auto my-2 h-full min-h-[35px]">
               <input id="Day_@i" type="radio" value="@i" name="daypfmonth" @checkedMonthDay class="hidden peer">
               <label for="Day_@i" class="ml-2 text-sm font-medium text-white 
   bg-blue-dark border-gray-light border rounded-xl px-1 py-2 w-full 
   peer-checked:text-blue-600 peer-checked:dark:bg-green text-center justify-center">
                    @i.GetOrdinal()
               </label>
           </div>
       }
   </div>
</div>

Usted puede ver que tengo una clase de plantilla Alpine.js css que establece la opacidad del elemento a 50% y desactiva los eventos del indicador si el calendario no está fijado en MonthlyM SK2 Esta es una manera sencilla de ocultar elementos que no son necesarios.

:class="{ 'opacity-50 pointer-events-none': schedule !== 'Monthly' }" 

También oculta el seleccionador de días monetarios si el calendario no está fijado en mes.

x-show="schedule === 'Monthly'"

Así que ' es la jist de la página del calendario . I' cubrirá el backend en el siguiente post

El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer.

En el siguiente post I'll (que me finish bulding itM SK2 publicar las nuevas modificaciones estructurales del proyecto para permitirme usar una aplicación web separada para Hanfgire y el servicio de envío de correo electrónico . Esto es un cambio sustancial ya que voy a partir de un solo proyecto Mostlylucid a un número de proyectos que permitan compartir servicios:

  1. Mostlylucid - El proyecto principal de página web.

  2. Mostlylucid.SchedulerService - Este es el principal proyecto Hangfire que entrará en la Base de datos, construir los correos electrónicos y enviarlosM SK2

  3. Mostlylucid.Services En el párrafo 2 del artículo 5 de la Constitución se estipula que "todos los ciudadanos tienen derecho a la libertad de opinión y expresión".

  4. Mostlylucid.Shared - Ayudadores y Constantas utilizadas por todos los proyectosM SK1

  5. Mostlylucid.DbContext La Comisión Consultiva en Asuntos Administrativos y de Presupuesto recomienda a la Asamblea General que apruebe el siguiente proyecto de resolución:

Como se puede ver, esto incrementa considerablemente la complejidad de la arquitectura del sistema; pero en este caso es necesario' mantener el proyecto mantenible y escalable . I'Podré describir cómo lo he hecho en el resto de esta serie.

El Comité recomienda al Estado Parte que adopte todas las medidas necesarias para garantizar la igualdad entre los géneros y el empoderamiento de la mujer.

Sin embargo, en la mayoría de los casos se trata de un proyecto que no tiene por objeto resolver el problema de las minas antipersonal.

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.