A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Implementaci贸n de plugin de Ads: Desplegando en pantalla

40/42
Recursos

Aportes 89

Preguntas 12

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

Estuve un buen rato arreglando un problema de que no se mostraba el ad, todo estaba bien, hab铆a seguidotodos los pasos, pero no sal铆a, 驴adivinen c贸mo lo arregl茅?

Desactivando el adBlocker 馃う鈥嶁檪锔

adsContainer:

this.adsContainer.innerHTML = ` <div class="ads">
      <a  class="ads__link" href="${this.currentAd.url}" target="_blank">
        <img class="ads__img" src="${this.currentAd.imageUrl}" />
        <div class="ads__info">
          <h5 class="ads__title">${this.currentAd.title}</h5>
          <p class="ads__body">${this.currentAd.body}</p>
        </div>
      </a>
    </div>`;

Para los que se les ve el Ad debajo del v铆deo y no dentro: Deben agregar a los estilos:

.ads {
  padding: 4px;
  padding-right: 8px;
  background: white;
  width: 80%;

  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
}

.ads__link {
  display: flex;
  color: inherit;
  text-decoration: inherit;
}

.ads__img {
  width: 80px;
  min-width: 80px;
  height: 80px;
  margin-right: 16px;
}

.ads__info {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.ads__title {
  margin: 0;
}
.ads__body {
  margin: 0;
}

Desactiven al addBlocker y agreguen el css de los Ads !

Me tocara repetir el curso o ver otros materiales para entender mejor

Tengo pensado hacer muchas cosas con este plugin 馃槀

Node.insertBefore()

El m茅todo Node.insertBefore() inserta un nodo antes del nodo de referencia como hijo de un nodo padre indicado. Si el nodo hijo es una referencia a un nodo ya existente en el documento, insertBefore() lo mueve de la posici贸n actual a la nueva posici贸n (no hay necesidad de eliminar el nodo de su nodo padre antes de agregarlo al alg煤n nodo nuevo).

Esto significa que el nodo no puede estar en dos puntos del documento al simult谩neamente. Por lo que si el nodo ya tiene un padre, primero se elimina el nodo, y luego se inserta en la nueva posici贸n. Node.cloneNode() puede utilizarse para hacer una copia de un nodo antes de insertarlo en un nuevo padre. Ten en cuenta que las copias hechas con cloneNode() no se mantendr谩n sincronizadas autom谩ticamente.

Si el nodo de referencia es null, el nodo indicado se a帽adir谩 al final de la lista de hijos del nodo padre especificado.

Si el hijo proporcionado es un DocumentFragment, el contenido completo del DocumentFragment se mover谩 a la lista de hijos del nodo padre indicado.

Sintaxis

var _insertedNode_ = _parentNode_.insertBefore(_newNode_, _referenceNode_);
  • insertedNode El nodo que esta siendo insertado, es decir, newNode
  • parentNode El padre del nodo reci茅n insertado.
  • newNode El nodo a insertar.
  • referenceNode El nodo antes del cual se inserta newNode.

Si referenceNode es null, el newNode se insertar谩 al final de la lista de nodos hijos.

referenceNode no es un par谩metro opcional 鈥 debes pasar expl铆citamente un Node o null. No proporcion谩ndolo o pasando valores no v谩lidos podr铆a provocar un comportamiento distinto en diferentes versiones de navegadores.

Valor devuelto

El valor devuelto es el hijo a帽adido excepto cuando newNode es un DocumentFragment, en cuyo caso se devuelve un DocumentFragment.

element.innerHTML

Resumen

La propiedad Element.innerHTML devuelve o establece la sintaxis HTML describiendo los descendientes del elemento.

Al establecerse se reemplaza la sintaxis HTML del elemento por la nueva.

Nota: Si un nodo tiene un texto secundario que incluye los caracteres (&), (<), o (>), innerHTML devuelve estos caracteres como &amp, &lt y &gt respectivamente. Use Node.textContent para conseguir una copia correcta del contenido de estos nodos de texto.

Para insertar el c贸digo HTML en el documento en lugar de cambiar el contenido de un elemento, use el m茅todo insertAdjacentHTML().

Estuve unos 20 minutos buscando el porque no se me mostraba los datos aunque aparecia el div y era porque tenia el uBlockOrigin activo 馃ぃ馃ぃ馃ぃ馃ぃ馃ぃ馃ぃ馃ぃ馃ぃ馃ぃ馃ぃ馃ぃ馃ぃ

Exito. 100% Real no fake 馃槂

Por si lo necesitan

  private renderAd(){
    if (this.currentAd) {
      return 
    }
    const ad = this.ads.getAd()
    this.currentAd = ad
    this.adsContainer.innerHTML = `
      <div class="ads">
        <a class="ads__link" href="${this.currentAd.url}" target="_blank">
          <img class="ads__img" src="${this.currentAd.imageUrl}" />
          <div class="ads__info">
            <h5 class="ads__title">${this.currentAd.title}</h5>
            <p class="ads__body">${this.currentAd.body}</p>
          </div>
        </a>
      </div>
    `
  }

Uhh genial, todo me funcion贸 bien expeto鈥 que no se de d贸nde agarrar los estilos xD Me aparecen los ads debajo del video pero todo bien jaja

Despu茅s de un rato repasando el curso y leer el media API puede terminar un reproductor bastante b谩sico, les muestro mi resultado final.

El repositorio: https://github.com/darkOwlWood/MediaPlayer
El sitio web: https://ecstatic-mclean-b27f5d.netlify.app/

PD: En celulares no sirve tambi茅n ya que no uso eventos touch :p .

<div class="ads">
      <a  class="ads__link" href="${this.currentAd.url}" target="_blank">
        <img class="ads__img" src="${this.currentAd.imageUrl}" />
        <div class="ads__info">
          <h5 class="ads__title">${this.currentAd.title}</h5>
          <p class="ads__body">${this.currentAd.body}</p>
        </div>
      </a>
    </div>

Que increible, pero que desiluci贸n que el media player tenga controles jajaja, mis botones ahora no sirven para mucho :c

Estuve como 10 minutos buscando porque no se mostraban los ads as铆 que decid铆 leer los comentarios a ver si alguno le pasaba y le铆 que ten铆an activado el addBlock鈥 advienen a quien le paso lo mismo .-.

Yo pensando hacerlo con html y css, pero aqui a PELO nivel hard

#NuncaParesDeAprender

Alguien sabe como hizo el profe para que se muestre el control para adelantar el video?

SI tienen AdBlocker Los ads No se ven, Una hora tratando de arreglar eso, por no leer comentarios

Estuve un par de horas viendo porqu茅 no me aparec铆a el anuncio de nuevo luego de los 10 segundos鈥 era porque el v铆deo que agregu茅 duraba 28 segundos 馃ぃ馃ぃ

AdsContainer


<div class="ads">
	<a class="ads__links" href="${this.currentAd.url}" target="_blank"> 
		<img class="ads__img" src="${this.currentAd.imageUrl}"/> 
		<div class="ads__info"> 
			<h5 class="ads__title">${this.currentAd.title}</h5> 
			<p class="ads__body">${this.currentAd.body}</p> 
		</div> 
	</a> 
</div>
 private renderAd(){
        if(this.currentAdd){
            return;
        }
        const ad = this.ads.getAd();
        this.currentAdd = ad;
        this.adsContainer.innerHTML = `
        <div class="ads">
        <a class="ads__link" href="${this.currentAdd.url}" target="_blank">
          <img class="ads__img" src="${this.currentAdd.imageUrl}" />
          <div class="ads__info">
            <h5 class="ads__title">${this.currentAdd.title}</h5>
            <p class="ads__body">${this.currentAdd.body}</p>
          </div>
        </a>
      </div>
      `;
      setTimeout(() => {
        this.currentAdd = null;       
        this.adsContainer.innerHTML = ''; 
    }, 
    10000);
    }

Tal cual, el codigo de los estilos del contenedir de los ads:

* {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    box-sizing: border-box;
}

body {
background: #eeeeee;
color: #030303;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
    Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}

header {
text-align: center;
padding: 3rem 0;
background-image: linear-gradient(120deg, #f093fb 0%, #f5576c 100%);
color: white;
}

header > h1 {
font-weight: normal;
font-style: italic;
}

main {
padding: 1rem 0;
}

.container {
max-width: 960px;
width: 100%;
margin: 0 auto;
}

.movie {
width: 100%;
}

.ads {
padding: 4px;
padding-right: 8px;
background: white;
width: 80%;

position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
}

.ads__link {
display: flex;
color: inherit;
text-decoration: inherit;
}

.ads__img {
width: 80px;
min-width: 80px;
height: 80px;
margin-right: 16px;
}

.ads__info {
display: flex;
flex-direction: column;
justify-content: center;
}

.ads__title {
margin: 0;
}
.ads__body {
margin: 0;
}

funciono despu茅s de quitar el adblock xd

Creo que a varios les pudo ocurrir que la etiqueta a del hiperv铆nculo en el container no ten铆a el cierre 鈥>鈥 lo cual ocasionaba que no se mostrara la imagen en el banner del ad.

Alguien sabe porque si se ven mis Ads pero se ven abajo del video y no sobre el video?

Despu茅s de pasar d铆as con este error, por fin pude solucionar

La 煤ltima actualizaci贸n de Babel est谩 generando errores en el intercambio de datos con parcel-bundler.
Referencia => Aqu铆

Segu铆 muchos pasos que indican los compa帽eros ah铆, pero ninguno me ayud贸. Al final la unica soluci贸n que encontr茅, fue copiar un proyecto anterior (donde si me levantaba el servidor tranquilamente) y llevar los archivos de este proyecto para la nueva copia.
Lo que se me hace extra帽o es que en el proyecto anterior si corre, en el proyecto nuevo intent茅 replicar la configuraci贸n y no me permite levantar el servidor, solo encontr茅 soluci贸n copiando el proyecto antiguo.

Mucho texto, pero dejo esto aqu铆 por si alguien est谩 sufriendo con este error.

En el navegador Firefox si me funciona pero en Chrome no! 馃槴
S贸lo se me ve una l铆nea blanca鈥 A alguien m谩s le pasa?

Esta super genial este curso, me agrada mucho el resultado

jajaja horas revisando mi c贸digo viendo por que mis anuncios sal铆an por debajo del video y no sobre el video hasta que revise el css del los archivos del enlace me di cuenta que hab铆an estilos que no tenia.

Hola, tengo el siguiente error en consola, si bien entiendo cu谩l es el problema, no logro solucionarlo.

Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause(). https://goo.gl/LdLk22

驴Alguien puede ayudarme?

Les comparto la liga donde estoy tranajando la practica, todo lo arme en CodeSanbox

https://tv8d9.csb.app/

Me pas贸 algo interesante y no quiero que les pase. Cuando llaman los m茅todos de inicializaci贸n, aseg煤rence de inicializar primero el de _initPlayer() de otra forma no ver谩n los div generados desde c贸digo.

Ac谩 vamos, mucho contenido, mucho que aprender. Continuemos

este curso fue dificil y muchos veces bastante confuso, pero nucna habia aprendido tanto 馃槂 #neverStopLearning

Modicaciones de los archivos:
Assets/plugins/Ads/Index.ts:

    constructor() {
        this.ads = Ads.getInstance();
        this.adsContainer = document.createElement('div');
    }

    run(player: MediaPlayer){
        this.player = player;
        this.player.container.appendChild(this.adsContainer);
        this.media = this.player.media;
        this.media.addEventListener('timeupdate',this.handlerTimeUpdate);
    }
private renderAd(){
        if(this.currentAd) return;
        const ad = this.ads.getAd();
        this.currentAd = ad;
        this.adsContainer.innerHTML = `
        <div class="ads">
            <a  class="ads__link" href="${this.currentAd.url}" target="_blank">
                <img class="ads__img" src="${this.currentAd.imageUrl}" />
                <div class="ads__info">
                <h5 class="ads__title">${this.currentAd.title}</h5>
                <p class="ads__body">${this.currentAd.body}</p>
                </div>
            </a>
        </div>
        `;
        setTimeout(
            ()=>{
                this.currentAd = null;
                this.adsContainer.innerHTML = ``;
            },
            10000
        )
    }

Pero que belleza este curso :鈥)

Este curso es una joyita

Si no les sale el contenedor de avisos encima del video aca les dejo los estilos:

.ads {
  padding: 2px;
  background: rgba(255, 255, 255, 0.3);
  inline-size: 80%;
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
}

.ads__link {
  text-decoration: none;
  color: #030303;
  display: flex;
  align-items: center;
}

.ads__link > img {
  block-size: 100px;
  inline-size: 100px;
}

.ads__info {
  margin-inline-start: 8px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

Hice mi propia implementaci贸n del m茅todo getAd, donde utiliz贸 el mismo array ALL_ADS y un 铆ndice para no tener que crear un array nuevo he ir haciendo pop, ya que considero que es muy costoso. El 铆ndice es circular, es decir cuando llega al ALL_ADS.length entonces vuelve a 0;


getAd(): any {
        this.index = (++this.index) % this.ALL_ADS.length;
        return this.ALL_ADS[this.index];
    }

Wow, quien lo diria, la clase MediaPlayer usaba el patron Decorator todo este tiempo! 馃槀

por un momento me asuste de donde saco los controles jajaja, estupendo repase este curso tres veces es estupendo muchas gracias por todo richard 馃槃

Hola, no me aparece el <div> del minuto 4:44. Hasta ese momento mi HTML queda asi:

Sin embargo, al colocar la linea:

this.player.container.appendChild(this.adsContainer);

El HTML queda de este modo

JJahajaahha Que comico lo del bloqueador de anuncios, estuve 30m buscando el problema y era eso

Me ocurre que cuando implemento Ads en index.ts me dice que el constructor de esta es privado y no se puede acceder a 茅l. Pero si estamos trabajando con Singletones entonces no entiendo qu茅 pasa鈥

![](

Y el c贸digo de la clase Ads

export interface Ad {
  imageUrl: string;
  title: string;
  body: string;
  url: string;
}

const ALL_ADS: Ad[] = [
  {
    imageUrl:
      "https://static.platzi.com/media/achievements/badge-profesional-javascript-13538df2-24ce-433f-9aa6-e34eed608e70.png",
    title: "Curso Profesional de JavaScript",
    body:
      "Mejora tus habilidades en Javascript. Conoce Typescript y c贸mo puedes ocuparlo para mejorar el control de tus variables.",
    url: "https://platzi.com/cursos/javascript-profesional/"
  },

  {
    imageUrl:
      "https://static.platzi.com/media/achievements/badge-frontend-developer-8a49e681-3e22-408d-b886-2f47dfc9953a.png",
    title: "Curso de Frontend Developer",
    body:
      "Domina las bases de HTML y CSS. Define la arquitectura de tu c贸digo y construye un sitio web usando componentes est谩ticos. ",
    url: "https://platzi.com/cursos/frontend-developer/"
  },

  {
    imageUrl:
      "https://static.platzi.com/media/achievements/badge-backend-node-8e6aa8a9-f7cd-42b7-bf4a-e1ee916a942b.png",
    title: "Curso de Backend con Node.js",
    body:
      "Crea aplicaciones backend utilizando Node.js, Express y Mongo. Entiende c贸mo funciona Javascript en un servidor y escribe aplicaciones con Node.js.",
    url: "https://platzi.com/cursos/backend-nodejs/"
  },

  {
    imageUrl:
      "https://static.platzi.com/media/achievements/badge-prework-da6b0493-9908-40f3-ad53-f5d330b995b8.png",
    title:
      "Comienza tus proyectos de desarrollo para JavaScript configurando un entorno de desarrollo c贸modo y adaptado a tus necesidades.",
    body:
      "Mejora tus habilidades en Javascript. Conoce Typescript y c贸mo puedes ocuparlo para mejorar el control de tus variables.",
    url: "https://platzi.com/cursos/prework/"
  },

  {
    imageUrl:
      "https://static.platzi.com/media/achievements/badge-autenticacion-passport-6d45426a-2b24-4757-8927-7bfaf54529dd.png",
    title: "Curso de Autenticaci贸n con Passport.js",
    body:
      "Genera estrategias de autenticaci贸n Sign-In y Sign-Out usando Passport.js. Agrega autenticaci贸n con Facebook, Twitter y Google a tus desarrollos.",
    url: "https://platzi.com/cursos/passport/"
  },

  {
    imageUrl:
      "https://static.platzi.com/media/achievements/badge-backend-frontend-02b2ac18-331a-4959-85bf-0bd3c2aa009c.png",
    title: "Curso de Backend for Frontend",
    body:
      "La ingenier铆a de software evoluciona d铆a a d铆a, no te quedes atr谩s. Ahora que eres un Desarrollador FullStack JavaScript necesitas evolucionar con el software, construye arquitecturas de software modernas.",
    url: "https://platzi.com/cursos/bff/"
  },

  {
    imageUrl:
      "https://static.platzi.com/media/achievements/badge-react-adec89d0-1c35-4c9c-847e-18c284dc79dd.png",
    title: "Curso Pr谩ctico de React JS",
    body:
      "React es una de las librer铆as m谩s utilizadas hoy para crear aplicaciones web. Aprende a trav茅s de la creaci贸n de la interfaz de PlatziVideo todo lo que necesitas para crear incre铆bles componentes con React.      ",
    url: "https://platzi.com/cursos/react-ejs/"
  },

  {
    imageUrl:
      "https://static.platzi.com/media/achievements/badge-react-redux-2ca3c0a5-fc53-437f-bfba-69e9ddd5a803.png",
    title: "Curso de React Router y Redux",
    body:
      "Aprende de forma pr谩ctica a implementar React Router para manejar rutas en tus proyectos de frontend como un profesional.",
    url: "https://platzi.com/cursos/react-router-redux/"
  }
];

class Ads {
  private static instance: Ads;
  private ads: Ad[];

  private constructor() {
    this.initAds();
  }

  static getInstance() {
    if (!Ads.instance) {
      Ads.instance = new Ads();
    }

    return Ads.instance;
  }

  private initAds() {
    this.ads = [...ALL_ADS];
  }

  getAd() {
    if (this.ads.length === 0) {
      this.initAds();
    }

    return this.ads.pop();
  }
}

export default Ads;

Se puede concluir que los plugins son una forma de implementar el patron decorator ?

estoy muy emocionado ahhhhhhhhhhh

pero una cosa, al renderizar el ad, a veces se puede ver como el html se intenta acomodar, hay alguna forma de optiizar nuestro c贸digo para que esto no pase?

genial

A pesar de que descargu茅 el index.css del proyecto final, me aparece as铆 el ad

Me sucede algo muy curioso, tengo el c贸digo igual, (obvio pueden haber algunos errores nunca faltan)
Pero lo que sucede es que tengo el html en el inspector igual a Richard,(con los div donde deben estar) pero a la hora de que los Ads aparezcan el div contenedor se ampl铆a, luego cuando acaba el tiempo del Ads vuelve a su valor usual.

Super 煤til

Excelente clase!!

Por fin terminado!! :DD
Comparto mi MediaPlayer, tengo muchas ideas para hacerle cambios jeje

Super genial 馃槂

Wauu me gust贸 mucho este proyecto.

Super 煤til eso

Muy buen curso, muy 煤til!!!

WOW qu茅 genial esto.

Por qu茅 en este ejercicio no utiliz贸 nextSibling al momento de usar insertBefore, como en el index.ts de decorator?

Hola, no me aparece el <div> del minuto 4:44. Hasta ese momento mi HTML quedas as铆:
![](A:\Nahuel Bonader\Im谩genes\Screenshots\Recortes\1)

Sin embargo, al colocar la linea

this.player.container.appendChild(this.adsContainer);

El HTML queda de este modo:
![](A:\Nahuel Bonader\Im谩genes\Screenshots\Recortes\2)

Muy interesante, tenemos que tener en cuenta que a trav茅s de los plugins podemos extender la funcionalidad base de MediaPlayer, sin necesidad de meternos en su c贸digo interno.

class Ads {
    private static instance: Ads;
    private ads: Ad[];

    private constructor() {
        this.initAds();
    }

    static getInstance() {
        if(!Ads.instance) {
            Ads.instance = new Ads();
        }

        return Ads.instance;
    }

    private initAds() {
        this.ads = [...ALL_ADS];
    }

    getAd() {
        if(this.ads.length === 0) {
            this.initAds();
        }

        return this.ads.pop();
    }
}

export default Ads;

Que maravilloso curso!!!

Si dan click derecho en el reproductor de platzi, tambien muestra los controles predefinidos por HTML5鈥

Yo quer铆a hacer los controles personalizados, pero con esto, ya tenemos la base para lograrlo, si alguien quiere desarrollar el resto de controles, comenten para poder hacerlo鈥

Puede ser una excelente practica para todos 馃槃

Excelente!

S煤per!

Quede fue loco!

A alguien m谩s le salen 3 divs?
Por qu茅?

alguien m谩s tiene este problema? Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().

S煤peeeer. Gracias!!

Super Genial !!!

No entiendo el import del Ads, la ruta que especifica 鈥./plugins/Ads鈥 no hace referencia a una carpeta???
Por otro lado, hace 鈥渘ew Ads()鈥 cuando el constructor es privado.
Con una importaci贸n ya obtiene las exportaciones de dos archivos de la carpeta???

馃槃

Hola!, Cree una soluci贸n un tanto distinta, con un bot贸n para cerrar los anuncios, les comparto el c贸digo por si alguien le quiere echar un ojo 馃槃


Otra forma de evitar el bloqueo de ads es cambiar el nombre de las clases de las etiquetas de html. Yo las renombr茅 de ads a pub 鈥榩ublicidad鈥. Despu茅s de esto, logr茅 ver los banner con el adblocker activado.

Adjunto el index.css (al nivel de MediaPlayer.ts)

* {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  box-sizing: border-box;
}

body {
  background: #eeeeee;
  color: #030303;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
    Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}

header {
  text-align: center;
  padding: 3rem 0;
  background-image: linear-gradient(120deg, #f093fb 0%, #f5576c 100%);
  color: white;
}

header > h1 {
  font-weight: normal;
  font-style: italic;
}

main {
  padding: 1rem 0;
}

.container {
  max-width: 960px;
  width: 100%;
  margin: 0 auto;
}

.movie {
  width: 100%;
}

.ads {
  padding: 4px;
  padding-right: 8px;
  background: white;
  width: 80%;

  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
}

.ads__link {
  display: flex;
  color: inherit;
  text-decoration: inherit;
}

.ads__img {
  width: 80px;
  min-width: 80px;
  height: 80px;
  margin-right: 16px;
}

.ads__info {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.ads__title {
  margin: 0;
}
.ads__body {
  margin: 0;
}

Justo estoy haciendo una p谩ina para una agrupaci贸n de baile, me cae a pelo para que parezca m谩s profesional

muy pro este profe, un par de veces m谩s este curso para acercarme algo a tener sus conocimientos xd

esta clase fue super mega buena, quede como con un hambre de hacer el curso de manipulacion del dom. y de react ajajaja

muy interesante este capitulo.

Vamos!! 馃榾

se cayeron los links de la im谩genes de los ads

<div class=鈥渁ds鈥>
<a class=鈥渁ds__links鈥 href="${this.currentAd.url}" target="_blank">
<img class=鈥渁ds__img鈥 src="${this.currentAd.imageUrl}"/>
<div class=鈥渁ds__info鈥>
<h5 class=鈥渁ds__title鈥>${this.currentAd.title}</h5>
<p class=鈥渁ds__body鈥>${this.currentAd.body}</p>
</div>
</a>
</div>

Excelente Curso! El mejor que he visto en Platzi.

Que pro.

Buena clase.

,