Cómo Crear Un Verificador De Seguridad De Contraseña Con Vue

Apuesto a que ha notado que la mayoría de las aplicaciones actuales requieren que establezca una contraseña que cumpla con un conjunto específico de reglas. Las reglas pueden tener una longitud mínima, incluyendo o excluyendo caracteres especiales, letras mayúsculas o minúsculas, etc. En la mayoría de los casos, esas pocas reglas son suficientes para asegurarse de que su contraseña sea segura. Pero podemos ir un paso más allá y usar una biblioteca llamada zxcvbnpara verificar la seguridad de nuestra contraseña.

¿Qué es zxcvbn?

zxcvbnes un estimador de seguridad de contraseñas inspirado en los crackers de contraseñas. Mediante coincidencia de patrones y estimación conservadora, reconoce y pondera 40.000 contraseñas comunes, nombres comunes apellidos, palabras populares de Wikipedia, palabras comunes en diferentes idiomas y diferentes países, y otros patrones comunes, como fechas, repeticiones ( aaa), secuencias ( abcd), patrones de teclado ( qwertyuiop), y más.

Aquí hay algunas cosas que hace el verificador de contraseñas que cubriremos en esta publicación:

  • Permitir al usuario ingresar cualquier contraseña
  • Verifique la puntuación de la contraseña en cada cambio de entrada
  • Proporcione comentarios visuales usando una barra de progreso de color y un mensaje
  • Habilite el botón Enviar cuando se alcance una puntuación específica

Qué encontrarás en este artículo

En este artículo, me gustaría mostrarle cómo:

  1. Cree una plantilla de formulario básica con Tailwind CSS
  2. Cree el componente de puntaje de contraseña conzxcvbn
  3. Manejar el estado del botón
  4. Agregar una barra de progreso animada codificada por colores al formulario

He creado una demostración en StackBlitz para que puedas ver a lo que apuntamos.

Ok, eso es lo que queremos, ¡así que hagamos que suceda!

Paso 1: Cree una plantilla de formulario básica con Tailwind CSS

Comencemos por crear una plantilla básica para el formulario. Usaremos Tailwind CSS para hacer que el estilo sea más fácil y rápido.

En la sección de plantilla de nuestro PasswordInputFormcomponente, agregue un inputy un button:

<!-- PasswordInputForm.vue -->
<template>
  <div class="container mx-auto w-64">
    <input
      class="block w-full my-1 p-2 border border-grey-30 rounded leading-normal text-grey-80"
      type="text"
    />
    <button
      class="mt-6 px-6 py-1 leading-lg select-none bg-blue-400 text-white font-semibold border border-blue-500 rounded"
    >
      Submit
    </button>
  </div>
</template>

Ahora que tenemos algunas marcas con las que trabajar, agreguemos algunas propiedades a nuestro componente que nos permitirán hacerlo más interactivo. En la scriptsección de nuestro componente, agregue las propiedades passwordy isPasswordStrong, que son objetos reactivos y mutablesref .

// PasswordInputForm.vue
<script>
import { ref } from "vue";

export default {
  setup() {
    const password = ref("");
    const isPasswordStrong = ref(false);

    return { password, isPasswordStrong };
  },
};
</script>

Lo último que debemos hacer en esta etapa es vincular las propiedades recién creadas a la plantilla. Vinculamos nuestra passwordpropiedad al inputelemento usando la v-modeldirectiva , que nos permite rastrear el valor actual cada vez que un usuario cambia la entrada y asignamos ese valor a nuestra passwordreferencia reactiva.

<!-- PasswordInputForm.vue -->
<input
  class="block w-full my-1 p-2 border border-grey-30 rounded leading-normal text-grey-80"
  type="text"
  v-model="password"
/>

También podemos usar isPasswordStrongpara habilitar o deshabilitar el botón azul Enviar en nuestra demostración según el valor de la propiedad. Podemos hacerlo configurando condicionalmente las clases apropiadas para el botón.

<!-- PasswordInputForm.vue -->
<button
  class="mt-6 px-6 py-1 leading-lg select-none bg-blue-400 text-white font-semibold border border-blue-500 rounded"
  :class="[
    {
      'cursor-not-allowed opacity-50 pointer-events-hover': !isPasswordStrong,
    },
  ]"
>
  Submit
</button>

Con eso hecho, terminamos con una plantilla básica que se ve así:

https://stackblitz.com/edit/maz-calculator-ybhecr?embed=1&file=src/App.vue

Paso 2: Cree el componente de puntaje de contraseña conzxcvbn

Nuestra entrada está lista. Cuando cambiamos la entrada, refleja la propiedad apropiada en la instancia del componente. Implementemos la lógica del código que nos permitirá obtener la puntuación de nuestra contraseña.

Encerraremos toda esa lógica en un componente separado llamado PasswordScore. En este paso, también le mostraremos al usuario un mensaje que indica la seguridad de la contraseña actual.

Igual que antes, comenzaremos con una plantilla simple para nuestro componente.

<!-- PasswordScore.vue -->
<template>
  <div class="relative select-none">
    <p class="absolute mt-1 text-sm">
      // Here we will show the message to the user
    </p>
  </div>
</template>

En la scriptsección, agregue una opción de accesorios que defina lo que nuestro componente aceptará del mundo exterior. Solo necesitamos un valueaccesorio que nos diga cuál es la entrada del usuario actual, por lo que podemos marcar esa propiedad como required; esto nos obligará a pasar siempre esa propiedad del componente principal al componente secundario.

<!-- PasswordScore.vue -->
<script>
export default {
  props: {
    value: {
      type: String,
      required: true,
    },
  }
}
</script>

Tenemos el valor en el componente. Ahora, necesitamos usar la zxcvbnbiblioteca para recuperar la puntuación de ese valor.

El primer paso es importar los elementos de biblioteca requeridos en nuestro componente. Lo hacemos en la parte superior de nuestra scriptsección.

<!-- PasswordScore.vue -->
<script>
import { zxcvbn, zxcvbnOptions } from "@zxcvbn-ts/core";
import zxcvbnCommonPackage from "@zxcvbn-ts/language-common";
import zxcvbnEnPackage from "@zxcvbn-ts/language-en";

export default {
  ...
}
</script>

A continuación, debemos inicializar la biblioteca configurando las opciones apropiadas. Queremos inicializar la biblioteca inmediatamente cuando se crea el componente. Para activar la lógica en la creación de componentes, solo necesitamos ponerla dentro de la setupfunción de ese componente. Para obtener una descripción detallada de las opciones disponibles que puede pasar azxcvbn , recomiendo consultar la documentación de zxcvbn.

// PasswordScore.vue
export default {
  ...

  setup() {
    const options = {
        dictionary: {
          ...zxcvbnCommonPackage.dictionary,
          ...zxcvbnEnPackage.dictionary,
        },
        graphs: zxcvbnCommonPackage.adjacencyGraphs,
        translations: zxcvbnEnPackage.translations,
      };
      zxcvbnOptions.setOptions(options);
    }
}
</script>

Uso de la biblioteca de partituras zxcvbn

Bien, estamos listos para comenzar a usar la biblioteca de partituras. Detengámonos y pensemos por un segundo en lo que queremos hacer: obtener la puntuación del valor de entrada cada vez que cambia el valor.

La mejor manera de obtener un valor basado en otro valor reactivo es usar una propiedad calculada . Entonces, definamos una propiedad calculada llamada score. Importe un computedayudante de Vue y asigne un valor a un constuso de ese ayudante.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    const score = computed(() => {
      const hasValue = props.value && props.value.length > 0;

      if (!hasValue) {
        return 0;
      }

      return zxcvbn(props.value).score + 1;
    });
    ...
  }
  ...
}

En la propiedad calculada, primero verifique si el valor existe o si es una cadena vacía. Si es esto último true, podemos ahorrarnos algo de tiempo y regresar 0.

Si el valor no está vacío, usamos zxcvbn, le pasamos nuestro value. Observe cómo usamos los accesorios aquí: los accesorios se pasan a la setupfunción como primer argumento y luego se recuperan usando props.xyz. zxcvbn luego devolverá un objeto con una scorepropiedad.

¡Genial! Nuestra scorepropiedad calculada volverá a calcular cada vez que cambie el valor de nuestra entrada y nos devolverá un valor de puntuación. Pero, ¿cómo podemos mostrar ese valor a los usuarios?

Visualización del valor de puntuación zxcvbn

Implementemos dos propiedades computadas más para ayudarnos a mostrar un mensaje al usuario que indicará el puntaje actual.

El primero contendrá todas las posibles descripciones y códigos de color que podemos mostrar al usuario.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    const descriptions = computed(() => [
      {
        color: "bg-red-600",
        label: "Weak, my 2 years old son can break it!",
      },
      { color: "bg-red-300", label: "Still weak, keep on trying!" },
      { color: "bg-yellow-400", label: "We are getting there..." },
      { color: "bg-green-200", label: "Nice, but you can still do better" },
      {
        color: "bg-green-400",
        label: "Congratulations, you made it!",
      },
    ]);
    ...
  }
  ...
}

El segundo extrae y devuelve la descripción que queremos mostrar al usuario. Esto funciona igual que arriba: primero, verificamos si el valor existe y no es una cadena vacía; luego, si existe, devolvemos el elemento apropiado de la matriz de descripciones. Si no existe, devolvemos un mensaje genérico que puede alentar al usuario a usar la entrada.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    const description = computed(() =>
      props.value && props.value.length > 0
        ? descriptions.value[score.value - 1]
        : {
            color: "bg-transparent",
            label: "Start typing to check your password",
          }
    );
    ...
  }
  ...
}

Bien, ahora que tenemos la descripción lista, todavía tenemos que mostrársela al usuario. Usemos la sintaxis de plantilla de Vue para hacerlo.

<!-- PasswordScore.vue -->
<template>
  <div class="relative select-none">
    <p class="absolute mt-1 text-sm">
      {{ description.label }}
    </p>
  </div>
</template>

Hay una cosa más que debemos recordar: cada propiedad definida en la función de configuración que queremos usar en nuestra plantilla también debe ser devuelta por la función de configuración.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    return { description };
    ...
  }
  ...
}

Ya que queremos usar nuestro PasswordScorecomponente en el PasswordInputFormcomponente, necesitamos importar el PasswordScorecomponente de la misma manera que importamos la biblioteca de partituras y registrarlo usando la componentsopción , que lo hace disponible para la instancia del componente.

<!-- PasswordInputForm.vue -->
<script>
...
import PasswordScore from './PasswordScore.vue';

export default {
  components: {
    PasswordScore,
  },
  ...
};
</script>

Luego, podemos usar ese componente en la sección de plantilla, como se muestra a continuación.

<!-- PasswordInputForm.vue -->
<template>
  <div class="container mx-auto w-64">
    ...
    <PasswordScore
      :value="password"
      class="mt-2 mb-6"
    />
    ...
  </div>
</template>

¡Eso es todo por el paso dos! Después de este paso, deberíamos ver algo como esto:

https://stackblitz.com/edit/maz-calculator-nza3p9?embed=1&file=src/components/PasswordScore.vue

En el siguiente paso, trabajaremos con el botón Enviar para que se pueda hacer clic en él cuando la puntuación sea lo suficientemente buena para nuestros estándares.

Paso 3: manejar el estado del botón

En este paso, habilitaremos el botón Enviar cuando la puntuación tenga un valor de ≥ 4y lo deshabilitaremos nuevamente cuando esté por debajo de ese umbral.

Para hacer esto, necesitamos detectar cuándo se alcanza nuestro umbral. ¡Esto también es algo que podemos hacer usando una propiedad calculada!

Esta vez, lo llamaremos isPasswordStrong, una convención de nomenclatura que recomiendo encarecidamente usar para todas las variables de tipo booleano, ya que hace que la codificación y la lectura del código sean mucho más fáciles a largo plazo.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    const isPasswordStrong = computed(() => score.value >= 4);
    ...
  }
  ...
}

Ahora que tenemos ese valor, debemos comunicarnos con el componente principal para que el valor cambie y el botón debe habilitarse o deshabilitarse según el umbral que establezcamos. Podemos hacer esto emitiendo un evento .

Para emitir un evento, primero debemos definirlo con la emitspropiedad en nuestro componente. En última instancia, definiremos dos eventos:

  1. Cuando la contraseña se vuelve segura ( passed)
  2. Cuando la contraseña se vuelve débil ( failed)
// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    emits: ["passed", "failed"],
    ...
  }
  ...
}

Sigamos configurando para que emitamos esos eventos cuando isPasswordStrongcambie el valor de. No podemos hacer eso dentro de la propiedad computada porque las propiedades computadas nunca deberían causar efectos secundarios y, en nuestro caso, emitir un evento y cambiar el estado de un botón es un efecto secundario.

Uso de observadores Vue

Pero, ¡no temas! Vue viene con la herramienta adecuada para ese caso: un observador . Los observadores buscan cambios en las propiedades reactivas de nuestro componente y nos permiten ejecutar cualquier lógica cuando se produce ese cambio.

Primero, necesitamos importar un asistente de Vue, que se logra de la misma manera que importamos nuestras propiedades calculadas.

// PasswordScore.vue
export default {
  import { computed, watch } from "vue";
  ...
}

Luego, definimos nuestro observador dentro de la setupfunción.

// PasswordScore.vue
export default {
  import { computed, watch } from "vue";
  ...

  setup(props, { emit }) {
    ...
    watch(isPasswordStrong, (value) => {
      value ? emit("passed") : emit("failed");
    });
    ...
  }
  ...
}

Al definir un observador, le pasamos dos argumentos:

  1. La propiedad reactiva que queremos observar
  2. Una devolución de llamada que queremos ejecutar cuando cambia el valor de esa propiedad

La devolución de llamada tiene acceso a los valores actuales y anteriores de la propiedad que estamos viendo, pero en nuestro caso, solo necesitamos el valor actual.

Con el valor actual disponible, ahora podemos emitir el evento apropiado al componente principal en nuestra devolución de llamada.

¿De dónde emitviene el método?

Hay una cosa más que debo señalar: el emitmétodo proviene de un segundo parámetro que se pasa a la setupfunción. El segundo parámetro es un contextobjeto, que contiene algunos elementos más útiles, pero te dejaré que profundices en él por tu cuenta. 🙂

Entonces, emitimos el evento a nuestro componente principal. Ahora, necesitamos capturar ese evento y manejarlo en el componente principal.

Ya observamos eventos en cualquier componente secundario usando la v-ondirectiva incorporada (o @abreviatura). En cambio, observemos los dos eventos emitidos por el PasswordScorecomponente.

<!-- PasswordInputForm.vue -->
<template>
  <div class="container mx-auto w-64">
    ...
    <PasswordScore
      :value="password"
      class="mt-2 mb-6"
      @passed="isPasswordStrong = true"
      @failed="isPasswordStrong = false"
    />
    ...
  </div>
</template>

Cuando detectamos que ha ocurrido un evento apropiado, establecemos el valor de nuestra isPasswordStrongpropiedad reactiva. Eso desencadenará un cambio en las clases aplicadas al botón, lo que dará como resultado que el botón se deshabilite o se habilite según corresponda.

<!-- PasswordInputForm.vue -->
<button
  class="mt-6 px-6 py-1 leading-lg select-none bg-blue-400 text-white font-semibold border border-blue-500 rounded"
  :class="[
    {
      'cursor-not-allowed opacity-50 pointer-events-hover': !isPasswordStrong,
    },
  ]"
>
  Submit
</button>

Bien, ahora tenemos un formulario que verifica la puntuación de la entrada, muestra el resultado al usuario en forma de mensaje de cuadro de texto y habilita el botón cuando la contraseña es lo suficientemente segura. Debería verse algo como esto:

https://stackblitz.com/edit/maz-calculator-dakpfq?embed=1&file=src/components/PasswordScore.vue

Esto sería suficiente, pero queremos hacerlo un poco más pegadizo. A continuación, agregaremos una bonita barra de progreso que se anima y cambia de color cada vez que cambia la puntuación.

Paso 4: agregue una barra de progreso animada codificada por colores al formulario

Comencemos con la plantilla para nuestra barra de progreso. Lo mantendremos todo en un componente separado llamado BaseProgressBar.

En la sección de plantilla de nuestro nuevo componente, agregue dos divelementos:

  1. Un contenedor estático que mostrará el borde de nuestra barra de progreso.
  2. Un contenedor más dinámico que cambiará:
    1. Su ancho basado en una widthpropiedad calculada
    2. Su color, basado en una colorpropiedad pasada del PasswordScorecomponente.
<template>
  <div class="flex h-2 border border-grey-30 rounded">
    <div
      :style="{ width: `${width}%` }"
      :class="[color]"
      class="progress-bar flex h-full"
    />
  </div>
</template>

Para establecer el valor widthde nuestra barra de progreso, usamos un enlace de estilo en línea y asignamos un valor porcentual basado en nuestro valor de puntaje actual a una widthpropiedad de estilo sin formato de nuestro divelemento. Para el color, usamos el enlace de clase HTML y asignamos una clase Tailwind que es responsable de cambiar el color de fondo de nuestro archivo div.

En la scriptsección, agregamos otra opción de accesorios que define tres propiedades:

  1. max: El valor máximo permitido para nuestra valuepropiedad
  2. value: El valor actual que queremos mostrar en relación con el maxvalor
  3. color: El color de fondo Clase Tailwind que se usa para cambiar el color de nuestra barra de progreso

Ahora, en la setupfunción, definimos una propiedad calculada que es responsable de calcular el ancho actual de la barra en función de las propiedades maxy value.

<!-- BaseProgressBar.vue -->
<script>
import { computed } from 'vue';

export default {
  props: {
    max: {
      type: Number,
      required: true,
    },

    value: {
      type: Number,
      required: true,
    },

    color: {
      type: String,
      default: 'bg-transparent',
    },
  },

  setup(props) {
    const width = computed(() => (props.value / props.max) * 100);
    return { width };
  },
};
</script>

Eso es todo, ¡nuestra barra de progreso está lista! Ahora, necesitamos usarlo en el PasswordScorecomponente.
Igual que antes, importamos el componente y lo registramos:

<!-- PasswordScore.vue -->
<script>
...
import BaseProgressBar from './BaseProgressBar.vue';

export default {
  components: {
    BaseProgressBar,
  },
  ...
}
</script>

Por último, usamos ese componente en la sección de plantilla. Pase las propiedades al componente mediante el enlace de atributos :

  • value: Nuestro scorevalor
  • max: El valor de puntuación máxima, que podemos obtener de la duración de nuestrodescriptions
  • color: Nuestro color de descripción actual
<!-- PasswordScore.vue -->
<template>
  <div class="relative select-none">
    <BaseProgressBar
      :value="score"
      :max="descriptions.length"
      :color="description.color"
    />
    <p class="absolute mt-1 text-sm">
      {{ description.label }}
    </p>
  </div>
</template>

https://stackblitz.com/edit/maz-calculator-qdhnqx?embed=1&file=src/App.vue

Y ahí vamos. ¡Nuestro verificador de puntuación de contraseñas está listo!

Resumen

Recapitulemos lo que acabamos de lograr. Creamos dos componentes: uno para un formulario de verificación de contraseña y otro que usa nuestra contraseña y zxcvbnpara obtener el puntaje de esa contraseña. Luego implementamos una lógica que habilita o deshabilita nuestro botón Enviar según el puntaje. Finalmente, agregamos una barra de progreso que proporciona información al usuario sobre el puntaje actual.

¡Uf, cubrimos mucho! Con suerte, esto le brinda un nuevo truco en su caja de herramientas, así como un caso de uso práctico para Vue. 

Fuente: https://blog.logrocket.com/create-password-strength-checker-vue/

#vue 

What is GEEK

Buddha Community

Cómo Crear Un Verificador De Seguridad De Contraseña Con Vue

Cómo Crear Un Verificador De Seguridad De Contraseña Con Vue

Apuesto a que ha notado que la mayoría de las aplicaciones actuales requieren que establezca una contraseña que cumpla con un conjunto específico de reglas. Las reglas pueden tener una longitud mínima, incluyendo o excluyendo caracteres especiales, letras mayúsculas o minúsculas, etc. En la mayoría de los casos, esas pocas reglas son suficientes para asegurarse de que su contraseña sea segura. Pero podemos ir un paso más allá y usar una biblioteca llamada zxcvbnpara verificar la seguridad de nuestra contraseña.

¿Qué es zxcvbn?

zxcvbnes un estimador de seguridad de contraseñas inspirado en los crackers de contraseñas. Mediante coincidencia de patrones y estimación conservadora, reconoce y pondera 40.000 contraseñas comunes, nombres comunes apellidos, palabras populares de Wikipedia, palabras comunes en diferentes idiomas y diferentes países, y otros patrones comunes, como fechas, repeticiones ( aaa), secuencias ( abcd), patrones de teclado ( qwertyuiop), y más.

Aquí hay algunas cosas que hace el verificador de contraseñas que cubriremos en esta publicación:

  • Permitir al usuario ingresar cualquier contraseña
  • Verifique la puntuación de la contraseña en cada cambio de entrada
  • Proporcione comentarios visuales usando una barra de progreso de color y un mensaje
  • Habilite el botón Enviar cuando se alcance una puntuación específica

Qué encontrarás en este artículo

En este artículo, me gustaría mostrarle cómo:

  1. Cree una plantilla de formulario básica con Tailwind CSS
  2. Cree el componente de puntaje de contraseña conzxcvbn
  3. Manejar el estado del botón
  4. Agregar una barra de progreso animada codificada por colores al formulario

He creado una demostración en StackBlitz para que puedas ver a lo que apuntamos.

Ok, eso es lo que queremos, ¡así que hagamos que suceda!

Paso 1: Cree una plantilla de formulario básica con Tailwind CSS

Comencemos por crear una plantilla básica para el formulario. Usaremos Tailwind CSS para hacer que el estilo sea más fácil y rápido.

En la sección de plantilla de nuestro PasswordInputFormcomponente, agregue un inputy un button:

<!-- PasswordInputForm.vue -->
<template>
  <div class="container mx-auto w-64">
    <input
      class="block w-full my-1 p-2 border border-grey-30 rounded leading-normal text-grey-80"
      type="text"
    />
    <button
      class="mt-6 px-6 py-1 leading-lg select-none bg-blue-400 text-white font-semibold border border-blue-500 rounded"
    >
      Submit
    </button>
  </div>
</template>

Ahora que tenemos algunas marcas con las que trabajar, agreguemos algunas propiedades a nuestro componente que nos permitirán hacerlo más interactivo. En la scriptsección de nuestro componente, agregue las propiedades passwordy isPasswordStrong, que son objetos reactivos y mutablesref .

// PasswordInputForm.vue
<script>
import { ref } from "vue";

export default {
  setup() {
    const password = ref("");
    const isPasswordStrong = ref(false);

    return { password, isPasswordStrong };
  },
};
</script>

Lo último que debemos hacer en esta etapa es vincular las propiedades recién creadas a la plantilla. Vinculamos nuestra passwordpropiedad al inputelemento usando la v-modeldirectiva , que nos permite rastrear el valor actual cada vez que un usuario cambia la entrada y asignamos ese valor a nuestra passwordreferencia reactiva.

<!-- PasswordInputForm.vue -->
<input
  class="block w-full my-1 p-2 border border-grey-30 rounded leading-normal text-grey-80"
  type="text"
  v-model="password"
/>

También podemos usar isPasswordStrongpara habilitar o deshabilitar el botón azul Enviar en nuestra demostración según el valor de la propiedad. Podemos hacerlo configurando condicionalmente las clases apropiadas para el botón.

<!-- PasswordInputForm.vue -->
<button
  class="mt-6 px-6 py-1 leading-lg select-none bg-blue-400 text-white font-semibold border border-blue-500 rounded"
  :class="[
    {
      'cursor-not-allowed opacity-50 pointer-events-hover': !isPasswordStrong,
    },
  ]"
>
  Submit
</button>

Con eso hecho, terminamos con una plantilla básica que se ve así:

https://stackblitz.com/edit/maz-calculator-ybhecr?embed=1&file=src/App.vue

Paso 2: Cree el componente de puntaje de contraseña conzxcvbn

Nuestra entrada está lista. Cuando cambiamos la entrada, refleja la propiedad apropiada en la instancia del componente. Implementemos la lógica del código que nos permitirá obtener la puntuación de nuestra contraseña.

Encerraremos toda esa lógica en un componente separado llamado PasswordScore. En este paso, también le mostraremos al usuario un mensaje que indica la seguridad de la contraseña actual.

Igual que antes, comenzaremos con una plantilla simple para nuestro componente.

<!-- PasswordScore.vue -->
<template>
  <div class="relative select-none">
    <p class="absolute mt-1 text-sm">
      // Here we will show the message to the user
    </p>
  </div>
</template>

En la scriptsección, agregue una opción de accesorios que defina lo que nuestro componente aceptará del mundo exterior. Solo necesitamos un valueaccesorio que nos diga cuál es la entrada del usuario actual, por lo que podemos marcar esa propiedad como required; esto nos obligará a pasar siempre esa propiedad del componente principal al componente secundario.

<!-- PasswordScore.vue -->
<script>
export default {
  props: {
    value: {
      type: String,
      required: true,
    },
  }
}
</script>

Tenemos el valor en el componente. Ahora, necesitamos usar la zxcvbnbiblioteca para recuperar la puntuación de ese valor.

El primer paso es importar los elementos de biblioteca requeridos en nuestro componente. Lo hacemos en la parte superior de nuestra scriptsección.

<!-- PasswordScore.vue -->
<script>
import { zxcvbn, zxcvbnOptions } from "@zxcvbn-ts/core";
import zxcvbnCommonPackage from "@zxcvbn-ts/language-common";
import zxcvbnEnPackage from "@zxcvbn-ts/language-en";

export default {
  ...
}
</script>

A continuación, debemos inicializar la biblioteca configurando las opciones apropiadas. Queremos inicializar la biblioteca inmediatamente cuando se crea el componente. Para activar la lógica en la creación de componentes, solo necesitamos ponerla dentro de la setupfunción de ese componente. Para obtener una descripción detallada de las opciones disponibles que puede pasar azxcvbn , recomiendo consultar la documentación de zxcvbn.

// PasswordScore.vue
export default {
  ...

  setup() {
    const options = {
        dictionary: {
          ...zxcvbnCommonPackage.dictionary,
          ...zxcvbnEnPackage.dictionary,
        },
        graphs: zxcvbnCommonPackage.adjacencyGraphs,
        translations: zxcvbnEnPackage.translations,
      };
      zxcvbnOptions.setOptions(options);
    }
}
</script>

Uso de la biblioteca de partituras zxcvbn

Bien, estamos listos para comenzar a usar la biblioteca de partituras. Detengámonos y pensemos por un segundo en lo que queremos hacer: obtener la puntuación del valor de entrada cada vez que cambia el valor.

La mejor manera de obtener un valor basado en otro valor reactivo es usar una propiedad calculada . Entonces, definamos una propiedad calculada llamada score. Importe un computedayudante de Vue y asigne un valor a un constuso de ese ayudante.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    const score = computed(() => {
      const hasValue = props.value && props.value.length > 0;

      if (!hasValue) {
        return 0;
      }

      return zxcvbn(props.value).score + 1;
    });
    ...
  }
  ...
}

En la propiedad calculada, primero verifique si el valor existe o si es una cadena vacía. Si es esto último true, podemos ahorrarnos algo de tiempo y regresar 0.

Si el valor no está vacío, usamos zxcvbn, le pasamos nuestro value. Observe cómo usamos los accesorios aquí: los accesorios se pasan a la setupfunción como primer argumento y luego se recuperan usando props.xyz. zxcvbn luego devolverá un objeto con una scorepropiedad.

¡Genial! Nuestra scorepropiedad calculada volverá a calcular cada vez que cambie el valor de nuestra entrada y nos devolverá un valor de puntuación. Pero, ¿cómo podemos mostrar ese valor a los usuarios?

Visualización del valor de puntuación zxcvbn

Implementemos dos propiedades computadas más para ayudarnos a mostrar un mensaje al usuario que indicará el puntaje actual.

El primero contendrá todas las posibles descripciones y códigos de color que podemos mostrar al usuario.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    const descriptions = computed(() => [
      {
        color: "bg-red-600",
        label: "Weak, my 2 years old son can break it!",
      },
      { color: "bg-red-300", label: "Still weak, keep on trying!" },
      { color: "bg-yellow-400", label: "We are getting there..." },
      { color: "bg-green-200", label: "Nice, but you can still do better" },
      {
        color: "bg-green-400",
        label: "Congratulations, you made it!",
      },
    ]);
    ...
  }
  ...
}

El segundo extrae y devuelve la descripción que queremos mostrar al usuario. Esto funciona igual que arriba: primero, verificamos si el valor existe y no es una cadena vacía; luego, si existe, devolvemos el elemento apropiado de la matriz de descripciones. Si no existe, devolvemos un mensaje genérico que puede alentar al usuario a usar la entrada.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    const description = computed(() =>
      props.value && props.value.length > 0
        ? descriptions.value[score.value - 1]
        : {
            color: "bg-transparent",
            label: "Start typing to check your password",
          }
    );
    ...
  }
  ...
}

Bien, ahora que tenemos la descripción lista, todavía tenemos que mostrársela al usuario. Usemos la sintaxis de plantilla de Vue para hacerlo.

<!-- PasswordScore.vue -->
<template>
  <div class="relative select-none">
    <p class="absolute mt-1 text-sm">
      {{ description.label }}
    </p>
  </div>
</template>

Hay una cosa más que debemos recordar: cada propiedad definida en la función de configuración que queremos usar en nuestra plantilla también debe ser devuelta por la función de configuración.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    return { description };
    ...
  }
  ...
}

Ya que queremos usar nuestro PasswordScorecomponente en el PasswordInputFormcomponente, necesitamos importar el PasswordScorecomponente de la misma manera que importamos la biblioteca de partituras y registrarlo usando la componentsopción , que lo hace disponible para la instancia del componente.

<!-- PasswordInputForm.vue -->
<script>
...
import PasswordScore from './PasswordScore.vue';

export default {
  components: {
    PasswordScore,
  },
  ...
};
</script>

Luego, podemos usar ese componente en la sección de plantilla, como se muestra a continuación.

<!-- PasswordInputForm.vue -->
<template>
  <div class="container mx-auto w-64">
    ...
    <PasswordScore
      :value="password"
      class="mt-2 mb-6"
    />
    ...
  </div>
</template>

¡Eso es todo por el paso dos! Después de este paso, deberíamos ver algo como esto:

https://stackblitz.com/edit/maz-calculator-nza3p9?embed=1&file=src/components/PasswordScore.vue

En el siguiente paso, trabajaremos con el botón Enviar para que se pueda hacer clic en él cuando la puntuación sea lo suficientemente buena para nuestros estándares.

Paso 3: manejar el estado del botón

En este paso, habilitaremos el botón Enviar cuando la puntuación tenga un valor de ≥ 4y lo deshabilitaremos nuevamente cuando esté por debajo de ese umbral.

Para hacer esto, necesitamos detectar cuándo se alcanza nuestro umbral. ¡Esto también es algo que podemos hacer usando una propiedad calculada!

Esta vez, lo llamaremos isPasswordStrong, una convención de nomenclatura que recomiendo encarecidamente usar para todas las variables de tipo booleano, ya que hace que la codificación y la lectura del código sean mucho más fáciles a largo plazo.

// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    const isPasswordStrong = computed(() => score.value >= 4);
    ...
  }
  ...
}

Ahora que tenemos ese valor, debemos comunicarnos con el componente principal para que el valor cambie y el botón debe habilitarse o deshabilitarse según el umbral que establezcamos. Podemos hacer esto emitiendo un evento .

Para emitir un evento, primero debemos definirlo con la emitspropiedad en nuestro componente. En última instancia, definiremos dos eventos:

  1. Cuando la contraseña se vuelve segura ( passed)
  2. Cuando la contraseña se vuelve débil ( failed)
// PasswordScore.vue
export default {
  import { computed } from "vue";
  ...

  setup(props) {
    ...
    emits: ["passed", "failed"],
    ...
  }
  ...
}

Sigamos configurando para que emitamos esos eventos cuando isPasswordStrongcambie el valor de. No podemos hacer eso dentro de la propiedad computada porque las propiedades computadas nunca deberían causar efectos secundarios y, en nuestro caso, emitir un evento y cambiar el estado de un botón es un efecto secundario.

Uso de observadores Vue

Pero, ¡no temas! Vue viene con la herramienta adecuada para ese caso: un observador . Los observadores buscan cambios en las propiedades reactivas de nuestro componente y nos permiten ejecutar cualquier lógica cuando se produce ese cambio.

Primero, necesitamos importar un asistente de Vue, que se logra de la misma manera que importamos nuestras propiedades calculadas.

// PasswordScore.vue
export default {
  import { computed, watch } from "vue";
  ...
}

Luego, definimos nuestro observador dentro de la setupfunción.

// PasswordScore.vue
export default {
  import { computed, watch } from "vue";
  ...

  setup(props, { emit }) {
    ...
    watch(isPasswordStrong, (value) => {
      value ? emit("passed") : emit("failed");
    });
    ...
  }
  ...
}

Al definir un observador, le pasamos dos argumentos:

  1. La propiedad reactiva que queremos observar
  2. Una devolución de llamada que queremos ejecutar cuando cambia el valor de esa propiedad

La devolución de llamada tiene acceso a los valores actuales y anteriores de la propiedad que estamos viendo, pero en nuestro caso, solo necesitamos el valor actual.

Con el valor actual disponible, ahora podemos emitir el evento apropiado al componente principal en nuestra devolución de llamada.

¿De dónde emitviene el método?

Hay una cosa más que debo señalar: el emitmétodo proviene de un segundo parámetro que se pasa a la setupfunción. El segundo parámetro es un contextobjeto, que contiene algunos elementos más útiles, pero te dejaré que profundices en él por tu cuenta. 🙂

Entonces, emitimos el evento a nuestro componente principal. Ahora, necesitamos capturar ese evento y manejarlo en el componente principal.

Ya observamos eventos en cualquier componente secundario usando la v-ondirectiva incorporada (o @abreviatura). En cambio, observemos los dos eventos emitidos por el PasswordScorecomponente.

<!-- PasswordInputForm.vue -->
<template>
  <div class="container mx-auto w-64">
    ...
    <PasswordScore
      :value="password"
      class="mt-2 mb-6"
      @passed="isPasswordStrong = true"
      @failed="isPasswordStrong = false"
    />
    ...
  </div>
</template>

Cuando detectamos que ha ocurrido un evento apropiado, establecemos el valor de nuestra isPasswordStrongpropiedad reactiva. Eso desencadenará un cambio en las clases aplicadas al botón, lo que dará como resultado que el botón se deshabilite o se habilite según corresponda.

<!-- PasswordInputForm.vue -->
<button
  class="mt-6 px-6 py-1 leading-lg select-none bg-blue-400 text-white font-semibold border border-blue-500 rounded"
  :class="[
    {
      'cursor-not-allowed opacity-50 pointer-events-hover': !isPasswordStrong,
    },
  ]"
>
  Submit
</button>

Bien, ahora tenemos un formulario que verifica la puntuación de la entrada, muestra el resultado al usuario en forma de mensaje de cuadro de texto y habilita el botón cuando la contraseña es lo suficientemente segura. Debería verse algo como esto:

https://stackblitz.com/edit/maz-calculator-dakpfq?embed=1&file=src/components/PasswordScore.vue

Esto sería suficiente, pero queremos hacerlo un poco más pegadizo. A continuación, agregaremos una bonita barra de progreso que se anima y cambia de color cada vez que cambia la puntuación.

Paso 4: agregue una barra de progreso animada codificada por colores al formulario

Comencemos con la plantilla para nuestra barra de progreso. Lo mantendremos todo en un componente separado llamado BaseProgressBar.

En la sección de plantilla de nuestro nuevo componente, agregue dos divelementos:

  1. Un contenedor estático que mostrará el borde de nuestra barra de progreso.
  2. Un contenedor más dinámico que cambiará:
    1. Su ancho basado en una widthpropiedad calculada
    2. Su color, basado en una colorpropiedad pasada del PasswordScorecomponente.
<template>
  <div class="flex h-2 border border-grey-30 rounded">
    <div
      :style="{ width: `${width}%` }"
      :class="[color]"
      class="progress-bar flex h-full"
    />
  </div>
</template>

Para establecer el valor widthde nuestra barra de progreso, usamos un enlace de estilo en línea y asignamos un valor porcentual basado en nuestro valor de puntaje actual a una widthpropiedad de estilo sin formato de nuestro divelemento. Para el color, usamos el enlace de clase HTML y asignamos una clase Tailwind que es responsable de cambiar el color de fondo de nuestro archivo div.

En la scriptsección, agregamos otra opción de accesorios que define tres propiedades:

  1. max: El valor máximo permitido para nuestra valuepropiedad
  2. value: El valor actual que queremos mostrar en relación con el maxvalor
  3. color: El color de fondo Clase Tailwind que se usa para cambiar el color de nuestra barra de progreso

Ahora, en la setupfunción, definimos una propiedad calculada que es responsable de calcular el ancho actual de la barra en función de las propiedades maxy value.

<!-- BaseProgressBar.vue -->
<script>
import { computed } from 'vue';

export default {
  props: {
    max: {
      type: Number,
      required: true,
    },

    value: {
      type: Number,
      required: true,
    },

    color: {
      type: String,
      default: 'bg-transparent',
    },
  },

  setup(props) {
    const width = computed(() => (props.value / props.max) * 100);
    return { width };
  },
};
</script>

Eso es todo, ¡nuestra barra de progreso está lista! Ahora, necesitamos usarlo en el PasswordScorecomponente.
Igual que antes, importamos el componente y lo registramos:

<!-- PasswordScore.vue -->
<script>
...
import BaseProgressBar from './BaseProgressBar.vue';

export default {
  components: {
    BaseProgressBar,
  },
  ...
}
</script>

Por último, usamos ese componente en la sección de plantilla. Pase las propiedades al componente mediante el enlace de atributos :

  • value: Nuestro scorevalor
  • max: El valor de puntuación máxima, que podemos obtener de la duración de nuestrodescriptions
  • color: Nuestro color de descripción actual
<!-- PasswordScore.vue -->
<template>
  <div class="relative select-none">
    <BaseProgressBar
      :value="score"
      :max="descriptions.length"
      :color="description.color"
    />
    <p class="absolute mt-1 text-sm">
      {{ description.label }}
    </p>
  </div>
</template>

https://stackblitz.com/edit/maz-calculator-qdhnqx?embed=1&file=src/App.vue

Y ahí vamos. ¡Nuestro verificador de puntuación de contraseñas está listo!

Resumen

Recapitulemos lo que acabamos de lograr. Creamos dos componentes: uno para un formulario de verificación de contraseña y otro que usa nuestra contraseña y zxcvbnpara obtener el puntaje de esa contraseña. Luego implementamos una lógica que habilita o deshabilita nuestro botón Enviar según el puntaje. Finalmente, agregamos una barra de progreso que proporciona información al usuario sobre el puntaje actual.

¡Uf, cubrimos mucho! Con suerte, esto le brinda un nuevo truco en su caja de herramientas, así como un caso de uso práctico para Vue. 

Fuente: https://blog.logrocket.com/create-password-strength-checker-vue/

#vue 

Luna  Mosciski

Luna Mosciski

1600583123

8 Popular Websites That Use The Vue.JS Framework

In this article, we are going to list out the most popular websites using Vue JS as their frontend framework.

Vue JS is one of those elite progressive JavaScript frameworks that has huge demand in the web development industry. Many popular websites are developed using Vue in their frontend development because of its imperative features.

This framework was created by Evan You and still it is maintained by his private team members. Vue is of course an open-source framework which is based on MVVM concept (Model-view view-Model) and used extensively in building sublime user-interfaces and also considered a prime choice for developing single-page heavy applications.

Released in February 2014, Vue JS has gained 64,828 stars on Github, making it very popular in recent times.

Evan used Angular JS on many operations while working for Google and integrated many features in Vue to cover the flaws of Angular.

“I figured, what if I could just extract the part that I really liked about Angular and build something really lightweight." - Evan You

#vuejs #vue #vue-with-laravel #vue-top-story #vue-3 #build-vue-frontend #vue-in-laravel #vue.js

Teresa  Bosco

Teresa Bosco

1598685221

Vue File Upload Using vue-dropzone Tutorial

In this tutorial, I will show you how to upload a file in Vue using vue-dropzone library. For this example, I am using Vue.js 3.0. First, we will install the Vue.js using Vue CLI, and then we install the vue-dropzone library. Then configure it, and we are ready to accept the file. DropzoneJS is an open source library that provides drag and drops file uploads with image previews. DropzoneJS is lightweight doesn’t depend on any other library (like jQuery) and is  highly customizable. The  vue-dropzone is a vue component implemented on top of Dropzone.js. Let us start Vue File Upload Using vue-dropzone Tutorial.

Dropzone.js is an open-source library providing drag-and-drop file uploads with image previews. DropzoneJS is lightweight, doesn’t depend on any other library (like jQuery), and is highly customizable.

The vue-dropzone is a vue component implemented on top of Dropzone.js.

First, install the Vue using Vue CLI.

Step 1: Install Vue.js using Vue CLI.

Go to your terminal and hit the following command.

npm install -g @vue/cli
         or
yarn global add @vue/cli

If you face any error, try running the command as an administrator.

Now, we need to generate the necessary scaffold. So type the following command.

vue create vuedropzone

It will install the scaffold.

Open the project in your favorite editor. Mine is Visual Studio Code.

cd vuedropzone
code .

Step 2: Install vue-dropzone.

I am using the Yarn package manager. So let’s install using Yarn. You can use NPM, also. It does not matter.

yarn add vue2-dropzone

or

npm install vue2-dropzone

Okay, now we need to add one css file with the above package. Now, vue cli uses css loader, so we can directly import in the src >>  main.js entry file.

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App)
}).$mount('#app')

import 'vue2-dropzone/dist/vue2Dropzone.css'

If importing css is not working for you, then you need to install that CSS file manually.

Copy this vue2Dropzone.css file’s content.

Create one file inside the src  >>  assets folder, create one css file called vuedropzone.css and paste the content there.

Import this css file inside src  >>  App.vue file.

<style lang="css">
  @import './assets/vuedropzone.css';
</style>

Now, it should include in our application.

Step 3: Upload an Image.

Our primary boilerplate has one ready-made component called HelloWorld.vue inside src  >>  components folder. Now, create one more file called FileUpload.vue.

Add the following code to FileUpload.vue file.

// FileUpload.vue

<template>
  <div id="app">
    <vue-dropzone id="upload" :options="config"></vue-dropzone>
  </div>
</template>

<script>
import vueDropzone from "vue2-dropzone";

export default {
  data: () => ({
    config: {
      url: "https://appdividend.com"
    }
  }),
  components: {
    vueDropzone
  }
};
</script>

Here, our API endpoint is https://appdividend.com. It is the point where we will hit the POST route and store our image, but it is my blog’s homepage, so it will not work anyway. But let me import this file into App.vue component and see what happens.

// App.vue

<template>
  <div id="app">
    <FileUpload />
  </div>
</template>

<script>
import FileUpload from './components/FileUpload.vue'

export default {
  name: 'app',
  components: {
    FileUpload
  }
}
</script>

<style lang="css">
  @import './assets/vuedropzone.css';
</style>

Now, start the development server using the following command. It will open up URL: http://localhost:8080.

npm run serve

Now, after uploading the image, we can see that the image upload is failed due to the wrong POST request endpoint.

Step 4: Create Laravel API for the endpoint.

Install the Laravel.

After that, we configure the database in the .env file and use MySQL database.

We need to create one model and migration file to store the image. So let us install the following command inside the Laravel project.

php artisan make:model Image -m

It will create both the Image model and create_images_table.php migrations file.

Now, open the migrations file and add the schema to it.

// create_images_table.php

public function up()
    {
        Schema::create('images', function (Blueprint $table) {
            $table->increments('id');
            $table->string('image_name');
            $table->timestamps();
        });
    }

Now, migrate the database table using the following command.

php artisan migrate

It creates the table in the database.

Now, we need to add a laravel-cors package to prevent cross-site-allow-origin errors. Go to the Laravel root and enter the following command to install it.

composer require barryvdh/laravel-cors

Configure it in the config  >>  app.php file.

Barryvdh\Cors\ServiceProvider::class,

Add the middleware inside app >>  Http  >>  Kernel.php file.

// Kernel.php

protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
        \Barryvdh\Cors\HandleCors::class,
];

Step 5: Define the API route and method to store the image.

First, create an ImageController.php file using the following command.

php artisan make:controller ImageController

Define the store method. Also, create one images folder inside the public directory because we will store an image inside it.

Right now, I have written the store function that handles one image at a time. So do not upload multiple photos at a time; otherwise, it will break.

// ImageController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Image;

class ImageController extends Controller
{
    public function store(Request $request)
    {
       if($request->file('file'))
       {
          $image = $request->file('file');
          $name = time().$image->getClientOriginalName();
          $image->move(public_path().'/images/', $name); 
        }

       $image= new Image();
       $image->image_name = $name;
       $image->save();

       return response()->json(['success' => 'You have successfully uploaded an image'], 200);
     }
}

Go to the routes   >>  api.php file and add the following route.

// api.php

Route::post('image', 'ImageController@store');

Step 6: Edit FileUpload.vue component.

We need to add the correct Post request API endpoint in FileUpload.vue component.

// FileUpload.vue

<template>
  <div id="app">
    <vue-dropzone id="drop1" :options="config" @vdropzone-complete="afterComplete"></vue-dropzone>
  </div>
</template>

<script>
import vueDropzone from "vue2-dropzone";

export default {
  data: () => ({
    config: {
      url: "http://localhost:8000/api/image",
      
    }
  }),
  components: {
    vueDropzone
  },
  methods: {
    afterComplete(file) {
      console.log(file);
    }
  }
};
</script>

Now, save the file and try to upload an image. If everything is okay, then you will be able to save the image on the Laravel web server as well as save the name in the database as well.

You can also verify on the server side by checking the database entry and the images folder in which we have saved the image.

Step 7: More vue-dropzone configuration.

The only required options are url, but there are many more you can use.

For example, let’s say you want:

  • A maximum of 4 files
  • 2 MB max file size
  • Sent in chunks of 500 bytes
  • Set a custom thumbnail size of 150px
  • Make the uploaded items cancelable and removable (by default, they’re not)
export default {
  data: () => ({
    dropOptions: {
      url: "https://httpbin.org/post",
      maxFilesize: 5, // MB
      maxFiles: 5,
      chunking: true,
      chunkSize: 400, // Bytes
      thumbnailWidth: 100, // px
      thumbnailHeight: 100,
      addRemoveLinks: true
    }
  })
  // ...
}

Happy Coding !!!

Originally published at https://appdividend.com 

#vue #vue-dropzone #vue.js #dropzone.js #dropzonejs #vue cli

Saul  Alaniz

Saul Alaniz

1660971600

Cómo Crear Un Temporizador De Cuenta Atrás animado Con Vue

Las aplicaciones de temporizador están en todas partes y cada una tiene su apariencia y diseño únicos. Algunos optan por un diseño minimalista, usando solo texto para indicar el tiempo restante, mientras que otros intentan ser más visuales mostrando una forma circular que disminuye lentamente o incluso reproduciendo audio a intervalos regulares para notificar el tiempo restante.

Bueno, este es el tipo de temporizador que construiremos en este artículo:

El temporizador animado que construiremos para el artículo.

Indica el tiempo restante con longitud, texto y color, lo que lo hace muy demostrativo.

Usaremos Vue, así que configure su proyecto y ¡comencemos!

Crear el anillo del temporizador

Comenzaremos creando el anillo del temporizador usando un elemento svg . Contendrá un elemento circular que usaremos para crear el anillo del temporizador. El círculo se dibujará en el centro del svgcontenedor, con un radio de 45 píxeles.

src/components/AppTimer.vue

<template>
  <div class="root">
    <svg class="svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
      <g class="circle">
        <circle class="time-elapsed-path" cx="50" cy="50" r="45" />
      </g>
    </svg>
  </div>
</template>

Envolveremos el circleelemento en un gelemento para que podamos agruparlo circlecon otros elementos que se agregarán más adelante en el tutorial.

Hemos creado el marcado HTML básico, ahora agreguemos CSS que mostrará el anillo.

src/components/AppTimer.vue

...
<style>
/* Sets the container's height and width */
.root {
  height: 300px;
  width: 300px;
  position: relative;
}

/* Removes SVG styling that would hide the time label */
.circle {
  fill: none;
  stroke: none;
}

/* The SVG path that displays the timer's progress */
.time-elapsed-path {
  stroke-width: 7px;
  stroke: #424242;
}
</style>

Registremos el AppTimercomponente App.vuey mostrémoslo:

src/App.vue

<template>
  <AppTimer />
</template>

<script>
import AppTimer from './components/AppTimer.vue';

export default {
  name: 'App',
  components: {
    AppTimer,
  },
};
</script>

Así que esto es lo que tenemos ahora. Solo un anillo básico. Sigamos moviéndonos.

Un anillo circular.

Visualización de la etiqueta del temporizador

Lo siguiente que debe hacer después de crear el anillo del temporizador es mostrar la etiqueta que indica cuánto tiempo queda.

src/components/AppTimer.vue

<template>
  <div class="root">
    ...
    <div class="time-left-container">
      <span class="time-left-label">{{ timeLeftString }}</span>
    </div>
  </div>
</template>

<script>
export default {
  methods: {
    padToTwo(num) {
      // e.g. 4 -> '04'
      return String(num).padStart(2, '0');
    },
  },
  computed: {
    // e.g. timeLeft of 100 -> '01:40'
    timeLeftString() {
      const timeLeft = this.timeLeft;
      const minutes = Math.floor(timeLeft / 60);
      const seconds = timeLeft % 60;
      return `${this.padToTwo(minutes)}:${this.padToTwo(seconds)}`;
    },
    timeLeft() {
      return this.limit - this.elapsed;
    },
  },
  // Register props to be set from App.vue
  props: {
    elapsed: {
      type: Number,
      required: true,
    },
    limit: {
      type: Number,
      required: true,
    },
  },
};
</script>
...

El AppTimerahora tiene dos puntales. La elapsedpropiedad se usará para establecer cuánto tiempo ha transcurrido y la limitpropiedad especificará el tiempo total.

timeLeft()es una propiedad calculada que se actualizará automáticamente cuando elapsedcambie.

timeLeftString()es otra propiedad calculada que devolverá una cadena en el MM:SSformato que indica el tiempo restante. Sus valores se actualizarán cada vez que timeLeft()cambie.

Agreguemos el siguiente CSS a AppTimer.vue, que le dará estilo a la etiqueta y la superpondrá sobre el anillo del temporizador:

src/components/AppTimer.vue

...
<style>
...
.time-left-container {
  /* Size should be the same as that of parent container */
  height: inherit;
  width: inherit;

  /* Place container on top of circle ring */
  position: absolute;
  top: 0;

  /* Center content (label) vertically and horizontally  */
  display: flex;
  align-items: center;
  justify-content: center;
}

.time-left-label {
  font-size: 70px;
  font-family: 'Segoe UI';
  color: black;
}
</style>

Configuremos los AppTimeraccesorios que creamos, desde App.vue:

src/App.vue

<template>
  <AppTimer :elapsed="0" :limit="10" />
</template>
...

Ahora podemos ver la etiqueta.

El temporizador ahora tiene una etiqueta.

Habilitación de la cuenta regresiva del temporizador

Un temporizador no sirve de nada si no puede contar hacia atrás, agreguemos algo de lógica para habilitar esta funcionalidad.

Usaremos una variable de estado ( timeElapsed) para realizar un seguimiento del tiempo total transcurrido hasta ahora en segundos. Usando el setInterval()método, incrementaremos esta variable en 1 cada 1000 milisegundos (1 segundo). También nos aseguraremos de detener los incrementos regulares una vez que haya transcurrido todo el tiempo, utilizando el clearInterval()método.

Toda esta lógica estará contenida en el startTimer()método. Llamaremos startTimer()al mounted()gancho, para que la cuenta regresiva comience inmediatamente después de que se cargue la página.

src/App.vue

<template>
  <AppTimer
    :elapsed="timeElapsed"
    :limit="timeLimit"
  />
</template>

<script>
import AppTimer from './components/AppTimer.vue';

export default {
  name: 'App',
  data() {
    return {
      timeElapsed: 0,
      timerInterval: undefined,
      timeLimit: 10,
    };
  },
  methods: {
    startTimer() {
      this.timerInterval = setInterval(() => {
        // Stop counting when there is no more time left
        if (++this.timeElapsed === this.timeLimit) {
          clearInterval(this.timerInterval);
        }
      }, 1000);
    },
  },
  // Start timer immediately
  mounted() {
    this.startTimer();
  },
  components: {
    AppTimer,
  },
};
</script>

Y ahora tenemos un temporizador funcional.

Creación del anillo de progreso del temporizador

Ahora necesitamos agregar un anillo que se animará para visualizar el tiempo restante. Le daremos a este anillo un color distintivo y lo colocaremos sobre el anillo gris. A medida que pasa el tiempo, se animará para revelar más y más del anillo gris hasta que solo se vea el anillo gris cuando no quede tiempo.

Crearemos el anillo usando un elemento de ruta y le daremos estilo con CSS:

src/components/AppTimer.vue

<template>
  <div class="root">
    <svg
      class="svg"
      viewBox="0 0 100 100"
      xmlns="http://www.w3.org/2000/svg"
    >
      <g class="circle">
        ...
        <path
          class="time-left-path"
          d="
            M 50, 50
            m -45, 0
            a 45,45 0 1,0 90,0
            a 45,45 0 1,0 -90,0
          "
        ></path>
      </g>
    </svg>
    ...
  </div>
</template>

<script>
...
</script>

<style>
...
.time-left-path {
  /* Same thickness as the original ring */
  stroke-width: 7px;

  /* Rounds the path endings  */
  stroke-linecap: round;

  /* Makes sure the animation starts at the top of the circle */
  transform: rotate(90deg);
  transform-origin: center;

  /* One second aligns with the speed of the countdown timer */
  transition: 1s linear all;

  /* Colors the ring */
  stroke: blue;
}

.svg {
  /* Flips the svg and makes the animation to move left-to-right */
  transform: scaleX(-1);
}
</style>

Así que ahora este anillo azul cubre el anillo gris.

El anillo azul del temporizador ahora se convierte en el anillo gris.

Animación del anillo de progreso del temporizador

Para animar el anillo, vamos a usar el atributo stroke-dasharray del path.

Así es como se verá el anillo con diferentes stroke-dasharrayvalores:

Cómo se verá el anillo del temporizador azul con diferentes valores de trazo-raya.

Podemos ver que establecer stroke-dasharrayun solo valor crea un patrón de guiones (los arcos azules) y espacios (espacios entre los guiones) que tienen la misma longitud. stroke-dasharrayagrega tantos guiones como sea posible para llenar toda la longitud de la ruta.

Como sugiere su nombre, stroke-dasharraytambién puede tomar varios valores. Veamos qué sucede cuando especificamos dos:

Especifique dos valores para trazo-raya.

stroke-dasharray:10 30

Cuando se especifican dos valores, el primer valor determinará la longitud de los guiones y el segundo valor determinará la longitud de los espacios.

Podemos usar este comportamiento para hacer que el camino azul visualice el tiempo restante. Para hacer esto, primero, calculemos la longitud total del círculo formado por el camino azul usando la fórmula de la circunferencia del círculo ( 2πr):

Full path length = 2 x π x r = 2 x π x 45 = 282.6 ≈ 283

Entonces, para mostrar el tiempo restante con la ruta, especificaremos dos valores, el primer valor comenzará en 283y se reducirá gradualmente a 0, mientras que el segundo valor será constante en 283. Esto asegura que solo haya un guión y un espacio en todo momento, ya 283que es tan largo como la ruta completa.

Así es como la ruta cambiará en longitud a medida que cambie el primer valor:

Cómo cambia la longitud de la ruta azul a medida que cambia el valor del primer trazo-raya.

Implementemos esto en nuestro código:

src/components/AppTimer.vue

<template>
  <div class="root">
    <svg
      class="svg"
      viewBox="0 0 100 100"
      xmlns="http://www.w3.org/2000/svg"
    >
      <g class="circle">
        ...
        <path
          class="time-left-path"
          v-if="timeLeft > 0"
          d="
            M 50, 50
            m -45, 0
            a 45,45 0 1,0 90,0
            a 45,45 0 1,0 -90,0
          "
          :style="{ strokeDasharray }"
        ></path>
      </g>
    </svg>
    ...
  </div>
</template>

<script>
export default {
  ...
  computed: {
    ...
    strokeDasharray() {
      const radius = 45;
      const totalLength = 2 * Math.PI * radius;
      const timeFraction = this.timeLeft / this.limit;
      const elapsedDash = Math.floor(timeFraction * totalLength);
      return `${elapsedDash} ${totalLength}`;
    },
  },
  ...
};
</script>

<style>
...
</style>

Usamos una propiedad calculada ( strokeDasharray) para calcular el nuevo valor del stroke-dasharrayatributo cada vez que cambia el tiempo restante.

Solemos v-ifdejar de mostrar el anillo azul por completo cuando no queda más tiempo.

Y ahora el anillo azul se anima en línea con la etiqueta para indicar el tiempo restante.

El anillo azul se anima en línea con la etiqueta ahora.

Sin embargo, hay un problema: si observa de cerca, el anillo azul desaparece repentinamente cuando el temporizador llega a cero.

El camino azul desaparece repentinamente en esta longitud cuando el temporizador llega a cero.

Esto sucede porque la duración de la animación se establece en un segundo. Cuando el valor del tiempo restante se establece en cero, aún se necesita un segundo para animar el anillo azul a cero.

Para solucionar esto, podemos usar una fórmula que reducirá la longitud de un anillo en una cantidad adicional (separada de la animación) cada vez que pase un segundo. Vamos a modificar AppTimer.vuepara hacer esto:

src/AppTimer.vue

<template>
...
</template>

<script>
export default {
  ...
  computed: {
    ...
    strokeDasharray() {
      const radius = 45;
      const total = 2 * Math.PI * radius;
      const timeFraction = this.timeLeft / this.limit;
      const adjTimeFraction = timeFraction - (1 - timeFraction) / this.limit;
      const elapsedDash = Math.floor(adjTimeFraction * total);
      return `${elapsedDash} ${total}`;
    },
  },
  ...
};
</script>

<style>
...
</style>

Ahora el anillo azul se reduce hasta el final antes de ser eliminado por v-if:

El anillo azul se reduce hasta el final antes de ser eliminado por v-if.

Crear el fondo

Ya hemos terminado con el temporizador, por lo que debemos trabajar en segundo plano. Lo crearemos y le daremos estilo en App.vue:

src/App.vue

<template>
  <div class="background">
    <div
      class="elapsed"
      :style="{ height: '100%', backgroundColor: 'blue' }"
    ></div>
  </div>
  <AppTimer
    :elapsed="timeElapsed"
    :limit="timeLimit"
  />
</template>

<script>
...
</script>

<style scoped>
.background {
  height: 100%;
  position: absolute;
  top: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: end;
  background-color: black;
}

.background .elapsed {
  /* For the height animation */
  transition: all 1s linear;
}
</style>

<style>
html,
body,
#app {
  height: 100%;
  margin: 0;
}

#app {

  /* Center timer vertically and horizontally */
  display: flex;
  justify-content: center;
  align-items: center;

  position: relative;
}
</style>

Dado que configuramos el color de fondo en azul, necesitaremos cambiar el color del anillo del temporizador y la etiqueta del temporizador para que sigan siendo visibles.

Usaremos blanco:

src/components/AppTimer.vue

...
<style>
...
.time-left-label {
  ...
  color: white;
}

.time-left-path {
  ...
  /* Colors the ring */
  stroke: white;
}
...
</style>

Ahora podemos ver el fondo:

Ahora podemos ver el fondo.

Animando el Fondo

El fondo es agradable, pero es solo estático. Agreguemos algo de código para animar su altura a medida que pasa el tiempo.

src/App.vue

<template>
  <div class="background">
    <div
      class="elapsed"
      :style="{ height: backgroundHeight, backgroundColor: 'blue' }"
      v-if="timeLeft > 0"
    ></div>
  </div>
  <AppTimer
    :elapsed="timeElapsed"
    :limit="timeLimit"
  />
</template>

<script>
...
export default {
  ...
  computed: {
    timeLeft() {
      return this.timeLimit - this.timeElapsed;
    },
    timeFraction() {
      return this.timeLeft / this.timeLimit;
    },
    backgroundHeight() {
      const timeFraction = this.timeFraction;

      // Adjust time fraction to prevent lag when the time left
      // is 0, like we did for the time left progress ring
      const adjTimeFraction =
        timeFraction - (1 - timeFraction) / this.timeLimit;

      const height = Math.floor(adjTimeFraction * 100);

      return `${height}%`;
    },
  },
  ...
};
</script>
...

Y ahora tenemos una animación de fondo, que sirve como otro indicador del tiempo restante.

Animando la altura del fondo.

Cambiar el color de fondo en ciertos puntos en el tiempo

Sería genial si también pudiéramos usar el color para indicar el tiempo restante.

Definiremos ciertos puntos en el tiempo en los que cambiará el color de fondo, usando una thresholdsmatriz. El color de fondo será azul al comienzo de la cuenta regresiva. Cambiará a naranja al 50 % del tiempo total y a rojo al 20 % del tiempo total.

src/components/App.vue

...
<script>
...
export default {
  ...
  data() {
    return {
      ...
      thresholds: [
        {
          color: 'blue',
          threshold: 1,
        },
        {
          color: 'orange',
          threshold: 0.5,
        },
        {
          color: 'red',
          threshold: 0.2,
        },
      ],
    };
  },
  ...
};
</script>
...

Usaremos el método reduce() para obtener el color de la hora actual de la thresholdsmatriz.

src/components/App.vue

<template>
  <div class="background">
    <div
      class="elapsed"
      :style="{ height: backgroundHeight, backgroundColor }"
      v-if="timeLeft > 0"
    ></div>
  </div>
  ...
</template>

<script>
...
export default {
  ...
  computed: {
    ...
    backgroundColor() {
      return this.thresholds.reduce(
        (color, item) =>
          item.threshold >= this.timeFraction ? item.color : color,
        undefined
      );
    },
  },
  ...
};
</script>
...

¡Y hemos terminado! Tenemos un temporizador funcional, que cuenta hacia atrás y muestra cuánto tiempo queda de 4 maneras diferentes.

Explore el código fuente de esta aplicación

Puede ver el código fuente completo de esta miniaplicación aquí en GitHub.

 Fuente: https://codingbeautydev.com/animated-countdown-timer-vue/

#vue 

joe biden

1617255938

¿Cómo migrar los buzones de correo de Exchange a la nube de Office 365?

Si tiene problemas para migrar los buzones de correo de Exchange a Office 365, debe leer este artículo para saber cómo migrar los buzones de correo de Exchange EDB a Office 365. Al migrar a Office 365, los usuarios pueden acceder a sus buzones de correo desde cualquier lugar y desde cualquier dispositivo.

En esta publicación, explicaremos las razones detrás de esta migración y una solución profesional para migrar de Exchange a Office 365.

Razones para migrar Exchange Server a la nube de Office 365

Office 365 apareció por primera vez en 2011 y, dado que se considera la mejor plataforma para aquellas organizaciones que desean administrar todo su sistema de correo electrónico en la nube. Estas son las características clave de Office 365:

  1. Permite trabajar desde cualquier lugar y desde cualquier lugar.
  2. No se preocupe por el spam y el malware.
  3. La seguridad proporcionada por Office 365 es altamente confiable.
  4. Controla el costo total y brinda flexibilidad financiera.
  5. Todas las actualizaciones y mejoras son administradas por Microsoft.

¿Cómo migrar los buzones de correo de Exchange a Office 365?

Hay varias formas manuales de migrar los buzones de correo de Exchange EDB a Office 365, pero para evitar estos complicados y prolongados procedimientos, presentamos una solución de terceros, es decir, la herramienta de migración de Exchange, que es automatizada y directa para la migración de Exchange a Office 365. La herramienta funciona rápidamente y migra todos los elementos del buzón de Exchange Server a Office 365.

La herramienta de migración de Datavare Exchange es demasiado fácil de usar y ofrece pasos sencillos para migrar EDB a Office 365:

  1. Descargue e instale el software en su sistema.
  2. Agregue el archivo EDB de Exchange con el botón Examinar.
  3. Seleccione exportar a buzones de correo de Office 365.
  4. Proporcione los detalles de inicio de sesión de la cuenta de Office 365.
  5. Seleccione la carpeta y presione el botón Finalizar.

Por lo tanto, todos sus buzones de correo de Exchange EDB ahora se migran a Office 365.
Nota: puede usar filtros para migrar los elementos de datos deseados de la cuenta de Exchange a la de Office 365

Líneas finales

Este blog le indica una solución profesional para la migración de buzones de correo de Exchange a la cuenta de Office 365. Dado que las soluciones manuales son complicadas, sugerimos la herramienta de migración de Exchange, que es demasiado simple de usar. Los usuarios no se enfrentan a problemas al operar el programa. La mejor parte de este software es que no necesita habilidades técnicas para realizar la migración. Se puede comprender el funcionamiento del software descargando la versión de demostración que permite la migración de los primeros 50 elementos por carpeta.

Más información:- https://www.datavare.com/software/edb-migration.html

#herramienta de migración de intercambio #migración de intercambio #migrar buzones de correo de exchange