1660208700
Lors de la programmation, les développeurs rencontrent des problèmes nécessitant la réutilisation du code, ce qui entraîne une programmation répétitive qui peut faire perdre du temps et réduire la productivité. Cela donne lieu au besoin d'un code source réutilisable appelé "extraits de code". Ces extraits empêchent le code répétitif pendant la programmation, peuvent être enregistrés pour une utilisation future et sont partageables.
Dans ce didacticiel, nous allons créer un site Web pour aider les utilisateurs à enregistrer des extraits de code quotidiens à l'aide du cadre de développement Web Next.js et alimenté par la base de données Fauna pour gérer le stockage, la manipulation et l'affichage des extraits de code. En travaillant sur ce projet amusant, nous apprendrons également à créer une application CRUD de base avec Next.js et FaunaDB qui pourrait également être utilisée pour créer d'autres projets similaires.
Une version de travail de ce projet est disponible sur GitHub . Pour suivre, vous aurez besoin de Node installé sur votre machine , ainsi que d'un compte FaunaDB et d'un compte Google (pour l'authentification).
Dans cette section, nous verrons comment installer Next.js à l'aide de la npx create-next-app
commande. Cela initialisera la Next CLI et créera une nouvelle application Next.js.
Nous installerons également les dépendances que nous utiliserons pour le back-end - FaunaDB et SWR - via la ligne de commande. SWR (state-while-revalidate) est un crochet Next.js pour récupérer des données. Nous aborderons cela en profondeur plus tard dans ce tutoriel.
Pour installer Next.js, saisissez la commande suivante dans la CLI :
npx create-next-app snippetapp
La commande ci-dessus crée un répertoire de projet appelé snippetapp
avec le modèle de démarrage Next.js, qui contient les fichiers requis pour le codage avec Next. Une fois l'installation de Next terminée, accédez au répertoire nouvellement créé :
cd snippetapp
Pour installer Fauna, nous utiliserons la commande suivante dans la CLI :
npm install --save faunadb
Ensuite pour installer SWR :
npm install swr@0.3.8
Avec cela, nous avons installé toutes les dépendances que nous utiliserons pour construire notre application et pouvons maintenant procéder à la configuration de notre base de données sur Fauna.
FaunaDB est une base de données en temps réel sans serveur. Il transforme une base de données traditionnelle en une API de données flexible qui conserve les capacités d'une base de données et ses performances tout en offrant un accès sécurisé et évolutif aux données des applications.
Ici, nous allons créer un compte utilisateur et configurer la base de données pour stocker les données que nous utiliserons dans notre application d'extrait de code.
Pour créer un compte utilisateur, accédez à la page d'inscription Fauna et créez un compte.
Après avoir créé un compte utilisateur, vous serez redirigé vers le tableau de bord.
Ici, nous allons créer une base de données avec les collections nécessaires pour gérer les extraits de code de notre application. Cliquez sur CRÉER UNE BASE DE DONNÉES . Nous allons créer une base de données appelée snippets
.
Sur la nouvelle page qui s'ouvre, cliquez sur NOUVELLE COLLECTION et créez une collection appelée codesnippet
.
Après avoir créé une collection, nous obtenons une page où nous pouvons créer un document.
Ici, vous cliquerez sur NOUVEAU DOCUMENT . Un document JSON s'ouvrira, dans lequel vous pourrez entrer les détails, comme illustré ci-dessous.
{
name: "Prompt User",
description: "prompts the user",
language: "javascript",
code: "prompt('would you like to continue')"
}
Ici, nous définissons un extrait avec les attributs : name
, description
et language
. code
Cliquez sur ENREGISTRER pour enregistrer la nouvelle collection. Nous avons ajouté avec succès un extrait à notre base de données. Nous pouvons maintenant procéder à l'obtention de nos identifiants d'accès à utiliser sur notre application.
Sur le tableau de bord, cliquez sur Sécurité . Cela ouvre une nouvelle page pour créer notre clé de sécurité.
Ici, nous allons définir le rôle sur "serveur" au lieu de "admin", et vous pouvez donner un nom à la clé. Cliquez sur le bouton SAVE pour générer votre clé.
.env
fichierNous allons maintenant créer un .env
fichier dans le répertoire de notre projet. Ce fichier stockera notre clé secrète générée. Dans le .env
fichier nous avons ceci :
FAUNA_SECRET = paste your key here
Dans cette section, nous allons créer la page d'affichage et de téléchargement des extraits de code, et y ajouter des fonctionnalités.
Ouvrez le répertoire du projet dans votre éditeur de code et accédez au index.js
fichier dans votre dossier de pages. Ici, nous allons effacer le code et commencer à créer notre application :
import Head from "next/head"
import Image from "next/image"
import styles from "../styles/Home.module.css"
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>View Snippet</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>Re-usuable Code Snippets</h1>
<p className={styles.info}>Add your code snippets here...</p>
<button>Create new snippet</button>
</main>
</div>
)
}
Nous allons maintenant créer un fichier de composant qui affichera nos extraits. Créez un dossier nommé component
dans votre répertoire de travail et créez un fichier nommé Snippets.js
à l'intérieur avec le code suivant :
import React from "react"
import styles from "../styles/Home.module.css"
function Snippets() {
return (
<div className={styles.cont}>
<p className={styles.lang}>language</p>
<h3 className={styles.name}>name of snippet</h3>
<p className={styles.descp}>description of snippet</p>
{/* Code will be displayed here*/}
<div className={styles.links}>
<a>Edit</a>
<a>Delete</a>
</div>
</div>
)
}
export default Snippets
Nous allons maintenant ajouter des importations pour ce fichier dans notreindex.js
:
import Snippets from "../components/Snippets"
Et utilisez-le dans notre application :
<button>Create new snippet</button>
<Snippets/>
Nous pouvons maintenant styliser notre page. Accédez au Home.module.css
fichier dans le styles
dossier et remplacez les styles par ce qui suit :
.container{
display: flex;
height: 100%;
min-height: 100vh;
background: rgb(48, 48, 255);
flex-direction: column;
align-items: center;
color: #fff;
font-family: Montserrat;
}
.cont{
color: #333;
margin-top: 5px;
background: rgb(214, 214, 214);
border-radius: 15px;
padding: 10px 15px;
}
.main button{
width: fit-content;
flex-grow: unset;
display: inline-block;
padding: 5px 10px;
outline: none;
border: none;
border-radius: 5%;
font-weight: bold;
color: rgb(48, 48, 255);
}
.main button:hover{
cursor: pointer;
}
.links{
margin-top: 10px;
}
.links a{
margin-left: 5px;
}
.links a:hover{
cursor: pointer;
}
À ce stade, vous devriez pouvoir démarrer le serveur de développement avec npm run dev
, visiter http://localhost:3000 et voir le squelette de notre application.
Ensuite, nous allons créer la section d'affichage pour l'extrait de code. Créez un nouveau fichier appelé Code.js
dans le dossier des composants et importez-le dans Snippets.js
:
import React from 'react'
import styles from '../styles/Home.module.css'
import Code from "./Code";
function Snippets() {
return (
<div className={styles.cont}>
<p className={styles.lang}>language</p>
<h3 className={styles.name}>name of snippet</h3>
<p className={styles.descp}>description of snippet</p>
{/* Code will be displayed here*/}
<Code />
<div className={styles.links}>
<a>Edit</a>
<a>Delete</a>
</div>
</div>
)
}
export default Snippets
Pour la coloration syntaxique du code, nous utiliserons deux packages, à savoir react-syntax-highlighter et react-copy-to-clipboard . Nous pouvons le télécharger via la CLI :
npm install react-syntax-highlighter react-copy-to-clipboard --save
Puis dans Code.js
:
import React from "react"
import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"
import {atomDark} from "react-syntax-highlighter/dist/cjs/styles/prism"
import { CopyToClipboard } from "react-copy-to-clipboard"
import styles from "../styles/Home.module.css"
function Code() {
const codeString = "npm install import react from 'react'"
const [show, setshow] = React.useState(false)
return (
<div>
<button onClick={() => setshow(!show)}>Show Code</button>
{show ? (
<div>
<CopyToClipboard text={codeString}>
<button className={styles.btn}>Copy</button>
</CopyToClipboard>
<SyntaxHighlighter language="javascript" style={atomDark}>
{codeString}
</SyntaxHighlighter>
</div>
) : null}
</div>
)
}
export default Code
Ici, nous avons créé un composant pour afficher le code avec la coloration syntaxique. Nous avons également ajouté des fonctionnalités de copie et de basculement d'affichage. Maintenant dans le styles
fichier :
.btn{
left: 80%;
position: relative;
}
Pour afficher cette modification, vous pouvez exécuter npm run dev
la ligne de commande et l'afficher dans votre navigateur. Nous avons la chaîne "npm install import react from 'react'" affichée avec la coloration syntaxique en tant que bloc de code. Il y a aussi un bouton pour masquer et afficher l'extrait de code, et un bouton qui nous permet de copier le code du bloc de code.
Dans cette section, nous allons récupérer les données de notre base de données FaunaDB vers notre application. Créez un fichier appelé Fauna.js
dans votre répertoire de projet :
const faunadb = require("faunadb")
const faunaClient = new faunadb.Client({
secret: process.env.FAUNA_SECRET
})
const q = faunadb.query
const getResponse = async () => {
const { data } = await faunaClient.query(
q.Map(
q.Paginate(q.Documents(q.Collection("codesnippet"))),
q.Lambda("doc", q.Get(q.Var("doc")))
)
)
const snippets = data.map((snippet) => {
snippet.id = snippet.ref.id
delete snippet.ref
return snippet
})
return snippets
}
module.exports = {
getResponse,
}
Ici, nous avons initialisé FaunaDB avec notre clé secrète. Nous avons également mis en place une async
requête pour interroger notre collection et renvoyer les données. Nous avons stocké les données renvoyées dans une variable nommée snippets
et supprimé la référence pour mieux structurer les données. D'autres fonctionnalités de création, de mise à jour et de suppression de snippets seront ajoutées ultérieurement dans ce tutoriel.
Notez que si vous obtenez une erreur non autorisée dans la console, vous devrez peut-être spécifier le nom de domaine du point de terminaison cible. La valeur par défaut est db.fauna.com
, mais depuis l'introduction des groupes de régions , trois domaines cloud sont disponibles. Utilisez le domaine correct pour le groupe de régions de votre base de données :
db.fauna.com
db.us.fauna.com
db.eu.fauna.com
Exemple de code :
const faunaClient = new faunadb.Client({
secret: process.env.FAUNA_SECRET,
domain: "db.eu.fauna.com"
})
Nous allons également créer un fichier pour gérer notre requête API pour notre base de données. Dans le api
dossier de pages
, créez un fichier appelé snippets.js
avec le code suivant :
import { getResponse } from "../../Fauna.js"
export default async function handler(req, res) {
console.log(req)
if (req.method !== "GET") {
return res.status(405)
}
try {
const snippets = await getResponse()
return res.status(200).json(snippets)
} catch (err) {
console.log(err)
res.status(500).json({ msg: "Something went wrong." })
}
}
Ci-dessus, nous avons simplement mis en place une fonction pour gérer les requêtes de notre base de données. Les extraits sont renvoyés au fur et à mesure Json
et consigneront les erreurs le cas échéant. Dans Next.js, tout fichier stocké dans le api
dossier est traité comme des points de terminaison d'API plutôt que comme une page et est rendu côté serveur.
Comme indiqué précédemment, SWR (state-while-revalidate) est un crochet Next.js pour récupérer des données. C'est une solution parfaite pour récupérer des données fréquemment mises à jour et convient parfaitement à notre application.
Nous l'utiliserons pour récupérer les données de FaunaDB. Pour l'utiliser, nous devons l'importer dans index.js
:
import useSWR from "swr"
export default function Home() {
const { data:snippets, mutate }=useSWR("api/snippets")
...
})
Ici, nous avons importé SWR et l'avons utilisé pour récupérer les données telles que configurées dans snippets.js
. Nous avons ensuite stocké ces extraits dans la snippets
variable et les afficherons à partir de là. Nous allons maintenant passer le snippets
à notre Snippets
composant pour afficher :
- <Snippets />
+ {snippets &&
+ snippets.map((snippet) => (
+ <Snippets
+ key={snippet.id}
+ snippet={snippet}
+ snippetDeleted={mutate}
+ />
+ ))
+ }
Ci-dessus, nous avons transmis la clé et l'extrait à Snippets
. Nous avons également configuré une mutate
propriété pour mettre à jour (récupérer à nouveau) les extraits lorsqu'un extrait est supprimé. Pour utiliser les données transmises, nous modifions le Snippets
composant avec ce qui suit :
function Snippets({snippet}) {
return (
<div className={styles.cont}>
<p className={styles.lang}>{snippet.data.language}</p>
<h3 className={styles.name}>{snippet.data.name}</h3>
<p className={styles.descp}>{snippet.data.description}</p>
<Code snippet={snippet}/>
<div className={styles.links}>
<a>Edit</a>
<a>Delete</a>
</div>
</div>
)
}
Ci-dessus, nous avons inséré le langage de l'extrait, le nom et la description reçus de FaunaDB dans notre code. Pour obtenir le code de Fauna dans notre application, nous avons également dû transmettre l'extrait de code au Code
composant.
Puis dans le Code
composant :
function Code({snippet}){
...
<div>
<CopyToClipboard text={snippet.data.code}>
<button className={styles.btn}>Copy</button>
</CopyToClipboard>
<SyntaxHighlighter language="javascript" style={atomDark}>
{snippet.data.code}
</SyntaxHighlighter>
</div>
...
}
Nous en avons maintenant terminé avec la GetSnippet
fonctionnalité. Si nous revenons à FaunaDB et créons un nouvel extrait, nous voyons ce qui est illustré ci-dessous.
{
"name": "console.log()",
"language": "javascript",
"description": "logs out data",
"code": "console.log('Hello, world!')"'
}
Pour exécuter dans la CLI :
npm run dev
Si vous ouvrez la page dans votre navigateur, vous aurez un résultat similaire à l'image ci-dessous.
Nous avons créé avec succès une page d'affichage d'extrait de code avec des fonctionnalités permettant d'afficher et de masquer le code et de copier l'extrait de code.
Nous devrons créer un lien vers la page de téléchargement à partir de notre composant d'accueil. Next.js a des dispositions qui facilitent le routage sans que vous ayez à installer react-router
et d'autres dépendances comme vous le feriez si vous utilisiez du code React natif.
Dans index.js
, nous importerons le Link
module depuis next
:
import Link from "next/link"
Ajoutez-le ensuite à notre bouton Créer un nouvel extrait :
- <button>Create new snippet</button>
+ <Link href="/upload">
+ <button>Create new snippet</button>
+ </Link>
Nous allons créer une nouvelle page dans notre pages
dossier et la nommer upload.js
.
De retour dans notre Fauna.js
fichier, nous allons créer et également exporter une fonction pour créer des extraits dans notre application :
const createSnippet = async (code, language, description, name) => {
return await faunaClient.query(q.Create(q.Collection("codesnippet"), {
data:{code, language, description, name}
}))
}
module.exports = {
getResponse,
createSnippet,
}
Ici, nous avons créé la fonction createSnippet
, qui prendra certains paramètres et les transmettra en tant que données dans le nouveau document qui sera créé dans la base de données.
Nous allons également configurer notre point de terminaison pour créer des extraits. Créez un nouveau fichier appelé createSnippet.js
dans le api
dossier et remplissez-le avec le code suivant :
import { createSnippet } from "../../Fauna"
export default async function handler(req, res) {
const { code, language, description, name } = req.body
if (req.method !== "POST") {
return res.status(405).json({msg:"unauthorized"})
}
try {
const createdSnippet = await createSnippet(code, language, description, name)
return res.status(200).json(createdSnippet)
} catch (error) {
console.log(error)
res.status(500).json({msg:"unauthorized"})
}
}
Nous allons maintenant créer la page de téléchargement dans notre upload.js
fichier. Pour que notre formulaire crée des extraits, nous utiliserons le react-hook-form . Nous allons l'installer via la CLI :
npm install react-hook-form
Ensuite, dans notre upload.js
dossier :
import React from "react"
import { useForm } from "react-hook-form"
import { useRouter } from "next/router"
import style from "../styles/form.module.css"
import { Link } from "next/link"
function upload({ snippet }) {
const { register, handleSubmit, errors, reset } = useForm()
const router = useRouter()
const createSnippet = async (data) => {
const { code, language, description, name } = data
console.log(data)
try {
// code here to push to Fauna
} catch (error) {
console.log(error)
}
}
return (
<div className={style.cont}>
<form
className={style.form}
onSubmit={handleSubmit(snippet ? updateSnippet : createSnippet)}
>
<div>
<label htmlFor="name">Name</label>
<input
className={style.input}
type="text"
id="name"
{...register("name", { required: true })}
/>
</div>
<div>
<label className={style.label} htmlFor="language">
language
</label>
<select
className={style.select}
type="text"
id="language"
{...register("language", { required: true })}
>
<option>Javascript</option>
<option>Html</option>
<option>CSS</option>
</select>
</div>
<div>
<label className={style.label} htmlFor="description">
description
</label>
<textarea
className={style.input}
rows={7}
type="text"
id="description"
placeholder="snippet description"
{...register("description", { required: true })}
/>
</div>
<div>
<label className={style.label} htmlFor="code">
Code
</label>
<textarea
className={style.input}
rows={8}
columns={8}
type="text"
id="code"
{...register("code", { required: true })}
placeholder="background: none;"
/>
</div>
<div>
<button className={style.button}>Submit</button>
<button className={style.button}>Cancel</button>
</div>
</form>
</div>
)
}
export default upload
Ci-dessus, nous avons créé notre formulaire en utilisant le react-hook-form
package. Nous avons utilisé la handleSubmit
fonction useForm()
dans l'opérateur ternaire. Lors de la soumission du formulaire, il détermine si la soumission effectuée consiste à créer ou à mettre à jour un extrait de code existant. Avec register
, nous avons ajouté la propriété requise à chaque champ de notre formulaire. Nous avons également ajouté des importations pour une feuille de style nommée form.module.css
où nous avons les styles suivants pour notre formulaire :
.form {
max-width: 800px;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.cont{
background: rgb(48, 48, 255);
height: 100%;
min-height: 100vh;
padding: 10px 0 0 0;
display: flex;
justify-content: center;
align-items: center;
}
.select,
.input {
display: block;
box-sizing: border-box;
width: 100%;
border-radius: 4px;
border: 1px solid black;
padding: 10px 15px;
margin-bottom: 15px;
font-size: 14px;
}
.label{
line-height: 2;
text-align: left;
display: block;
margin: 5px;
color: white;
font-size: 14px;
font-weight: 200;
}
.button {
background : #fff;
color: #444;
border: none;
border-radius: 5%;
margin-right: 8px;
}
Pour envoyer les données de notre formulaire vers la base de données FaunaDB, ajoutez le code suivant au try...catch
bloc dans la createSnippet
fonction dans upload.js
:
try {
await fetch("/api/createSnippet", {
method: "POST",
body: JSON.stringify({ code, language, description, name }),
headers: {
"Content-type": "application/json"
},
})
router.push("/")
} catch (error) {
console.log(error)
}
Exécutez le code et accédez à la page de téléchargement. Maintenant, si nous ajoutons un nouvel extrait au formulaire et cliquons sur Soumettre , nous verrons ce qui est illustré ci-dessous.
Lorsque nous naviguons vers notre composant d'accueil, nous pouvons voir l'extrait de code créé.
Pour créer notre fonctionnalité d'édition d'extrait de code, de retour dans le Fauna.js
fichier, nous allons créer et exporter une fonction pour gérer cette tâche :
const updateSnippet = async (id, code, language, description, name) => {
return await faunaClient.query(q.Update(q.Ref(q.Collection("codesnippet"), id), {
data: {code, language, name, description},
}))
}
module.exports = {
...
updateSnippet,
}
Cette fonction est similaire à la createSnippet
fonction , mais elle prend également un paramètre de id
. Il utilise cet ID pour identifier les extraits à modifier. Si le id
correspond, nous mettons à jour les données avec les autres paramètres. Nous allons également créer un fichier de point de terminaison dans le api
répertoire appelé updateSnippet.js
pour gérer les mises à jour :
import { updateSnippet } from "../../Fauna"
export default async function handler(req, res) {
const { id, code, language, description, name } = req.body
if (req.method !== "PUT") {
return res.status(405).json({ msg: "unauthorized" })
}
try {
const updated = await updateSnippet(
id,
code,
language,
description,
name
)
return res.status(200).json(updated)
}
catch (error) {
console.log(error)
res.status(500).json({ msg: "unauthorized" })
}
}
Maintenant, passez au Snippets
composant et modifiez ce composant pour utiliser cette fonction. Tout d'abord, nous allons importer le Link
module :
...
import Link from "next/link"
Nous modifions également notre edit
bouton :
- <a>Edit</a>
+ <Link href={`/edit/${snippet.id}`}>
+ <a>Edit</a>
+ </Link>
Lorsqu'il est cliqué, il envoie une requête à la page edit
avec l' id
extrait de code sélectionné. Dans le pages
dossier, créez un dossier nommé edit
avec un fichier [id].js
à l'intérieur :
import { getSnippetById } from "../../Fauna"
import Upload from "../upload"
export default function Home({ snippet }) {
const email = ""
const user = ""
return (
<div>
<h3>Update a snippet</h3>
<Upload snippet={snippet} email={email} user={user}/>
</div>
)
}
export async function getServerSideProps(context) {
try {
//get and update record
const id = context.params.id
}
catch (error) {
console.log(error)
context.res.statusCode = 302
context.res.setHeader("Location", "/")
return {props: {}}
}
}
Dans [id].js
, nous transmettons l'extrait de code props
à la page de téléchargement d'extraits. Cependant, cette fois, la page de téléchargement contiendra les données stockées dans l'extrait de code référencé par le id
. Pour récupérer l'extrait par ID, nous devrons créer la getSnippetById
fonction dans le Fauna.js
fichier :
const getSnippetById = async (id) => {
const snippet = await faunaClient.query(q.Get(q.Ref(q.Collection("codesnippet"),id)))
snippet.id = snippet.ref.id
delete snippet.ref
return snippet
}
module.exports = {
getResponse,
createSnippet,
updateSnippet,
getSnippetById,
}
Lorsque nous exportons la fonction, de retour dans le [id].js
fichier, nous pouvons l'utiliser pour récupérer un extrait particulier avec son ID :
try {
const id = context.params.id;
const snippet = await getSnippetById(id);
return {
props: { snippet },
};
} catch (error) {
// as before
}
Maintenant, dans le upload.js
fichier, nous allons le modifier pour pouvoir accéder aux données stockées si un extrait doit être modifié :
- const { register, handleSubmit, errors, reset } = useForm()
+ const { register, handleSubmit, errors, reset } = useForm({
+ defaultValues: {
+ code: snippet ? snippet.data.code : "",
+ language: snippet ? snippet.data.language : "",
+ description: snippet ? snippet.data.description : "",
+ name: snippet ? snippet.data.name : "",
+ }
+ })
Le code ci-dessus vérifie si l'extrait contient des données stockées. S'il renvoie true, il renvoie les données aux paramètres : code
, language
et description
. code
S'il renvoie false
, il renvoie une chaîne vide.
Ensuite, nous allons créer une fonction pour mettre à jour l'extrait de code :
const createSnippet = async (data) => { ... }
const updateSnippet = async (data) => {
const { code, language, description, name } = data
const id = snippet.id
try {
await fetch("/api/updateSnippet", {
method: "PUT",
body: JSON.stringify({ code, language, description, name, id }),
headers: {
"Content-Type": "application/json",
},
})
router.push("/")
}
catch (error) {
console.log(error)
}
}
return ( ,,, )
Si nous exécutons notre code, nous pouvons modifier les extraits de code créés précédemment en cliquant sur le bouton Modifier , en modifiant les données du formulaire et en cliquant sur Soumettre .
Maintenant, si nous revenons au Home
composant dans notre navigateur, nous pouvons éditer et mettre à jour des extraits de code. Nous pouvons enfin ajouter la fonctionnalité finale pour supprimer notre extrait de code. Créez et exportez une nouvelle fonction — deleteSnippet
— dans le Fauna.js
fichier :
const deleteSnippet = async (id) => {
return await faunaClient.query(q.Delete(q.Ref(q.Collection("codesnippet"),id)))
}
module.exports = {
...
deleteSnippet,
}
Nous allons créer un autre point de terminaison pour cette fonction dans notre api
dossier appelé deleteSnippet.js
et le remplir avec le code suivant :
import { deleteSnippet } from "../../Fauna"
export default async function handler(req, res) {
if (req.method !== "DELETE") {
return res.status(405).json({ msg: "unauthorized" })
}
const { id } = req.body
try {
const deleted = await deleteSnippet(id)
return res.status(200).json(deleted)
}
catch (error) {
console.log(error)
res.status(500).join({ msg: "error occured" })
}
}
Ensuite, nous modifions le Snippets.js
fichier pour ajouter la nouvelle fonctionnalité :
function Snippets({ snippet, snippetDeleted }) {
...
}
Créez ensuite une deleteSnippet
fonction pour récupérer le point de terminaison à partir de api
et supprimez l'extrait de code référencé par l'ID :
function Snippets({snippet, snippetDeleted}) {
const deleteSnippet = async () => {
try {
await fetch("/api/deleteSnippet", {
method: "DELETE",
body: JSON.stringify({ id: snippet.id }),
headers: {
"Content-Type": "application/json",
},
});
snippetDeleted();
} catch (e) {
console.log(e);
}
};
return (
<div className={styles.cont}>
<p className={styles.lang}>{snippet.data.language}</p>
<h3 className={styles.name}>{snippet.data.name}</h3>
<p className={styles.descp}>{snippet.data.description}</p>
<Code snippet={snippet}/>
<div className={styles.links}>
<Link href={`/edit/${snippet.id}`}>
<a>Edit</a>
</Link>
<a onClick={deleteSnippet}>Delete</a>
</div>
</div>
)
}
Nous avons également mis à jour l'élément d'ancrage pour appeler la deleteSnippet
fonction lorsqu'il est cliqué.
Nous avons ajouté une fonctionnalité pour supprimer des extraits de code. Nous pouvons maintenant supprimer des extraits en cliquant sur le bouton Supprimer dans notre application.
Ceci conclut les fonctionnalités de l'application d'extrait de code. Nous allons maintenant ajouter des mesures d'authentification à notre application pour permettre uniquement aux utilisateurs autorisés de créer ou de modifier des extraits de code dans notre application.
Pourquoi avons-nous besoin d'une authentification ? Actuellement, les utilisateurs peuvent créer des extraits, mais ils peuvent également supprimer et modifier des extraits qu'ils n'ont pas créés. Nous devrons fournir un moyen d'autoriser les utilisateurs à accéder à notre site - et donc le besoin d'authentification des utilisateurs.
Nous allons installer next-auth pour l'authentification via notre CLI :
npm i next-auth
Nous utiliserons un jeton JWT pour notre authentification. JWT est une norme utilisée pour créer des jetons d'accès pour une application.
Créez un dossier nommé auth
dans votre api
dossier et à l'intérieur de celui-ci, créez un fichier [...nextauth].js
contenant le code suivant :
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
export default NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth?prompt=consent&access_type=offline&response_type=code",
})
],
jwt: {
encryption: true
},
secret: process.env.secret,
callbacks: {
async jwt(token, account) {
if (account ?.accessToken) {
token.accessToken = account.accessToken
}
return token
},
redirect: async (url, _baseUrl)=>{
if (url === "/profile") {
return Promise.resolve("/")
}
return Promise.resolve("/")
}
}
})
Après cela, nous allons encapsuler nos composants dans le _app.js
fichier :
import '../styles/globals.css'
import {Provider} from "next-auth/client"
function MyApp({ Component, pageProps }) {
return (
<Provider session={pageProps.session}>
<Component {...pageProps} />
</Provider>
)
}
export default MyApp
Nous modifierons notre Home
composant en index.js
pour revenir à notre composant si l'utilisateur est authentifié, sinon il renvoie un bouton qui mène à la page d'authentification :
import {signIn, signOut, useSession} from "next-auth/client"
...
Puis dans Home
:
export default function Home() {
const { data:snippets, mutate }=useSWR("api/snippets")
const [session, loadingSession] = useSession()
if (loadingSession) {
<>
<p>...authenticating</p>
</>
}
...
}
Le code ci-dessus vérifie si l'application est loadingSession
. Si vrai, il renvoie le p
bloc de balises, sinon il renvoie le reste de notre application s'il y a session
. Ensuite, nous afficherons la "connexion" s'il n'y a pas de session :
return (
<div className={styles.container}>
<Head> ... </Head>
{!session && (
<>
<h1>Sign in to access snippet app</h1>
<button onClick={() => signIn()}>Sign In</button>
</>
)}
{session && (
<>
<main className={styles.main}>
<h3>welcome {session.user.email}</h3>
<button onClick={() => signOut()}>Sign Out</button>
...
</main>
</>
)}
</div>
)
Pour utiliser le "service de connexion Google", nous avons besoin d'informations d'identification d'accès à partir de la console cloud de Google. Pour l'obtenir, connectez-vous à votre compte Google et accédez à la console Google Cloud . Cliquez sur CRÉER UN PROJET sur la page, entrez le nom de votre projet et cliquez sur Créer .
Sur la nouvelle page qui s'ouvre, cliquez sur + CRÉER DES IDENTIFIANTS dans la barre de menu supérieure et enfin sélectionnez ID client OAuth dans le menu déroulant.
Sur la page qui s'ouvre, vous recevrez une notification avec un bouton vous demandant de "Configurer l'écran de consentement". Cliquez sur ce bouton.
Sur la page suivante, sélectionnez Externe sous le type d'utilisateur et cliquez sur Créer . Entrez les champs requis pour votre "Nom de l'application" et "Email" et cliquez sur Enregistrer et continuer .
Dans les sections Portées et Tester les utilisateurs , faites défiler vers le bas et cliquez sur Enregistrer et continuer .
Enfin, cliquez sur Revenir au tableau de bord et cliquez sur le bouton Publier .
Maintenant, nous pouvons créer notre clé en cliquant sur Credentials dans le menu latéral, puis sur Create Credentials dans la barre de menu supérieure. Sélectionnez Oauth Client ID dans la liste déroulante et vous obtiendrez une page demandant le type d'application.
Sélectionnez Web Application puis, sous « Authorized JavaScript origins », cliquez sur Add URI et saisissez http://localhost
. Enfin, sous « Authorized redirect URIs », cliquez sur Add URI et entrez http://localhost/api/auth/callback/google
dans le champ, avant de cliquer sur Create .
Copiez l'ID client et le secret client depuis la fenêtre contextuelle qui s'ouvre et ajoutez-les au .env
fichier :
GOOGLE_CLIENT_ID=id
GOOGLE_CLIENT_SECRET=secret
Nous pouvons maintenant nous connecter en utilisant l'authentification Google à notre application. De plus, nous allons configurer notre upload.js
fichier en tant que route protégée afin que les utilisateurs non autorisés ne puissent pas créer de nouveaux extraits :
import { getSession } from "next-auth/client"
function Upload({ snippet, user }) { ... }
export async function getServerSideProps(context) {
const session = await getSession(context)
if (!session) {
context.res.writeHead(302, { Location: "/" })
context.res.end()
return {}
}
return {
props: {
user: session.user,
}
}
}
export default Upload;
Si nous exécutons notre application avec la npm run dev
commande, nous aurons d'abord une page nous demandant de "se connecter". Nous ne pouvons pas accéder à la page de téléchargement via le /upload
chemin dans notre URL. Nous ne pouvons accéder à notre application que lorsque nous utilisons la fonction de connexion Google pour nous connecter à notre application.
Enfin, nous modifierons la createSnippet
fonctionnalité pour ajouter l'e-mail de l'utilisateur à la base de données, puis nous n'afficherons les boutons Modifier et Supprimer que si l'e-mail correspond.
Dans Fauna.js
, modifiez la createSnippet
fonction comme ceci :
const createSnippet = async (code, language, description, name, mail) => {
return await faunaClient.query(q.Create(q.Collection("codesnippet"), {
data:{code, language, description, name, mail}
}))
}
Dans le createSnippet.js
fichier, apportez les modifications suivantes :
- const { code, language, description, name } = req.body;
+ const { code, language, description, name, mail } = req.body;
- const createdSnippet = await createSnippet(code, language, description, name);
+ const createdSnippet = await createSnippet(code, language, description, name, mail);
Dans upload.js
:
function upload({ snippet, user }) {
+ const email = user.email;
...
}
Et modifiez la createSnippet
fonction et la updateSnippet
fonction, comme suit :
const createSnippet = async (data) => {
const { code, language, description, name, mail } = data;
console.log(data)
try {
await fetch("/api/createSnippet", {
method: "POST",
body: JSON.stringify({ code, language, description, name, mail:email }),
headers: {
"Content-type": "application/json"
},
})
router.push("/")
} catch (error) {
console.log(error)
}
}
const updateSnippet = async (data) => {
const { code, language, description, name } = data
const id = snippet.id
try {
await fetch("/api/updateSnippet", {
method: "PUT",
body: JSON.stringify({ code, language, description, name, mail:email }),
headers: {
"Content-Type": "application/json",
},
})
router.push("/")
}
catch (error) {
console.log(error)
}
}
Nous pouvons maintenant procéder à l' affichage des boutons Modifier et Supprimer uniquement si l'e-mail correspond.
Tout d'abord, nous passons les user.mail
as props au Snippet
composant in index.js
:
<Snippets
key={snippet.id}
snippet={snippet}
snippetDeleted={mutate}
+ email={session.user.email}
/>
Puis dans Snippet.js
:
function Snippets({ snippet, snippetDeleted, email }) {
...
{email == snippet.data.mail && (
<>
<div className={styles.links}>
<Link href={`/edit/${snippet.id}`}>
<a>Edit</a>
</Link>
<a onClick={deleteSnippet}>Delete</a>
</div>
</>
)}
...
}
Exécutez npm run dev
dans la CLI et ouvrez l'application dans votre navigateur. Désormais, si vous créez un nouvel extrait, l'e-mail de l'utilisateur est ajouté à la base de données. Si l'e-mail ne correspond pas, les boutons Modifier et Supprimer ne s'affichent pas sur la page d'affichage de l'extrait. Vous pouvez tester cela en vous connectant avec une adresse e-mail différente de celle utilisée pour créer les extraits de code.
Nous sommes enfin arrivés à la fin de ce tutoriel. Nous avons appris à créer une application CRUD avec Next.js et FaunaDB, et à effectuer des opérations CRUD basées sur l'authentification de l'utilisateur.
Pour consulter le code complet, visitez le dépôt GitHub .
Source : https://www.sitepoint.com/nextjs-faunadb-build-code-snippet-app/
1632537859
Not babashka. Node.js babashka!?
Ad-hoc CLJS scripting on Node.js.
Experimental. Please report issues here.
Nbb's main goal is to make it easy to get started with ad hoc CLJS scripting on Node.js.
Additional goals and features are:
Nbb requires Node.js v12 or newer.
CLJS code is evaluated through SCI, the same interpreter that powers babashka. Because SCI works with advanced compilation, the bundle size, especially when combined with other dependencies, is smaller than what you get with self-hosted CLJS. That makes startup faster. The trade-off is that execution is less performant and that only a subset of CLJS is available (e.g. no deftype, yet).
Install nbb
from NPM:
$ npm install nbb -g
Omit -g
for a local install.
Try out an expression:
$ nbb -e '(+ 1 2 3)'
6
And then install some other NPM libraries to use in the script. E.g.:
$ npm install csv-parse shelljs zx
Create a script which uses the NPM libraries:
(ns script
(:require ["csv-parse/lib/sync$default" :as csv-parse]
["fs" :as fs]
["path" :as path]
["shelljs$default" :as sh]
["term-size$default" :as term-size]
["zx$default" :as zx]
["zx$fs" :as zxfs]
[nbb.core :refer [*file*]]))
(prn (path/resolve "."))
(prn (term-size))
(println (count (str (fs/readFileSync *file*))))
(prn (sh/ls "."))
(prn (csv-parse "foo,bar"))
(prn (zxfs/existsSync *file*))
(zx/$ #js ["ls"])
Call the script:
$ nbb script.cljs
"/private/tmp/test-script"
#js {:columns 216, :rows 47}
510
#js ["node_modules" "package-lock.json" "package.json" "script.cljs"]
#js [#js ["foo" "bar"]]
true
$ ls
node_modules
package-lock.json
package.json
script.cljs
Nbb has first class support for macros: you can define them right inside your .cljs
file, like you are used to from JVM Clojure. Consider the plet
macro to make working with promises more palatable:
(defmacro plet
[bindings & body]
(let [binding-pairs (reverse (partition 2 bindings))
body (cons 'do body)]
(reduce (fn [body [sym expr]]
(let [expr (list '.resolve 'js/Promise expr)]
(list '.then expr (list 'clojure.core/fn (vector sym)
body))))
body
binding-pairs)))
Using this macro we can look async code more like sync code. Consider this puppeteer example:
(-> (.launch puppeteer)
(.then (fn [browser]
(-> (.newPage browser)
(.then (fn [page]
(-> (.goto page "https://clojure.org")
(.then #(.screenshot page #js{:path "screenshot.png"}))
(.catch #(js/console.log %))
(.then #(.close browser)))))))))
Using plet
this becomes:
(plet [browser (.launch puppeteer)
page (.newPage browser)
_ (.goto page "https://clojure.org")
_ (-> (.screenshot page #js{:path "screenshot.png"})
(.catch #(js/console.log %)))]
(.close browser))
See the puppeteer example for the full code.
Since v0.0.36, nbb includes promesa which is a library to deal with promises. The above plet
macro is similar to promesa.core/let
.
$ time nbb -e '(+ 1 2 3)'
6
nbb -e '(+ 1 2 3)' 0.17s user 0.02s system 109% cpu 0.168 total
The baseline startup time for a script is about 170ms seconds on my laptop. When invoked via npx
this adds another 300ms or so, so for faster startup, either use a globally installed nbb
or use $(npm bin)/nbb script.cljs
to bypass npx
.
Nbb does not depend on any NPM dependencies. All NPM libraries loaded by a script are resolved relative to that script. When using the Reagent module, React is resolved in the same way as any other NPM library.
To load .cljs
files from local paths or dependencies, you can use the --classpath
argument. The current dir is added to the classpath automatically. So if there is a file foo/bar.cljs
relative to your current dir, then you can load it via (:require [foo.bar :as fb])
. Note that nbb
uses the same naming conventions for namespaces and directories as other Clojure tools: foo-bar
in the namespace name becomes foo_bar
in the directory name.
To load dependencies from the Clojure ecosystem, you can use the Clojure CLI or babashka to download them and produce a classpath:
$ classpath="$(clojure -A:nbb -Spath -Sdeps '{:aliases {:nbb {:replace-deps {com.github.seancorfield/honeysql {:git/tag "v2.0.0-rc5" :git/sha "01c3a55"}}}}}')"
and then feed it to the --classpath
argument:
$ nbb --classpath "$classpath" -e "(require '[honey.sql :as sql]) (sql/format {:select :foo :from :bar :where [:= :baz 2]})"
["SELECT foo FROM bar WHERE baz = ?" 2]
Currently nbb
only reads from directories, not jar files, so you are encouraged to use git libs. Support for .jar
files will be added later.
The name of the file that is currently being executed is available via nbb.core/*file*
or on the metadata of vars:
(ns foo
(:require [nbb.core :refer [*file*]]))
(prn *file*) ;; "/private/tmp/foo.cljs"
(defn f [])
(prn (:file (meta #'f))) ;; "/private/tmp/foo.cljs"
Nbb includes reagent.core
which will be lazily loaded when required. You can use this together with ink to create a TUI application:
$ npm install ink
ink-demo.cljs
:
(ns ink-demo
(:require ["ink" :refer [render Text]]
[reagent.core :as r]))
(defonce state (r/atom 0))
(doseq [n (range 1 11)]
(js/setTimeout #(swap! state inc) (* n 500)))
(defn hello []
[:> Text {:color "green"} "Hello, world! " @state])
(render (r/as-element [hello]))
Working with callbacks and promises can become tedious. Since nbb v0.0.36 the promesa.core
namespace is included with the let
and do!
macros. An example:
(ns prom
(:require [promesa.core :as p]))
(defn sleep [ms]
(js/Promise.
(fn [resolve _]
(js/setTimeout resolve ms))))
(defn do-stuff
[]
(p/do!
(println "Doing stuff which takes a while")
(sleep 1000)
1))
(p/let [a (do-stuff)
b (inc a)
c (do-stuff)
d (+ b c)]
(prn d))
$ nbb prom.cljs
Doing stuff which takes a while
Doing stuff which takes a while
3
Also see API docs.
Since nbb v0.0.75 applied-science/js-interop is available:
(ns example
(:require [applied-science.js-interop :as j]))
(def o (j/lit {:a 1 :b 2 :c {:d 1}}))
(prn (j/select-keys o [:a :b])) ;; #js {:a 1, :b 2}
(prn (j/get-in o [:c :d])) ;; 1
Most of this library is supported in nbb, except the following:
:syms
.-x
notation. In nbb, you must use keywords.See the example of what is currently supported.
See the examples directory for small examples.
Also check out these projects built with nbb:
See API documentation.
See this gist on how to convert an nbb script or project to shadow-cljs.
Prequisites:
To build:
bb release
Run bb tasks
for more project-related tasks.
Download Details:
Author: borkdude
Download Link: Download The Source Code
Official Website: https://github.com/borkdude/nbb
License: EPL-1.0
#node #javascript
1660208700
Lors de la programmation, les développeurs rencontrent des problèmes nécessitant la réutilisation du code, ce qui entraîne une programmation répétitive qui peut faire perdre du temps et réduire la productivité. Cela donne lieu au besoin d'un code source réutilisable appelé "extraits de code". Ces extraits empêchent le code répétitif pendant la programmation, peuvent être enregistrés pour une utilisation future et sont partageables.
Dans ce didacticiel, nous allons créer un site Web pour aider les utilisateurs à enregistrer des extraits de code quotidiens à l'aide du cadre de développement Web Next.js et alimenté par la base de données Fauna pour gérer le stockage, la manipulation et l'affichage des extraits de code. En travaillant sur ce projet amusant, nous apprendrons également à créer une application CRUD de base avec Next.js et FaunaDB qui pourrait également être utilisée pour créer d'autres projets similaires.
Une version de travail de ce projet est disponible sur GitHub . Pour suivre, vous aurez besoin de Node installé sur votre machine , ainsi que d'un compte FaunaDB et d'un compte Google (pour l'authentification).
Dans cette section, nous verrons comment installer Next.js à l'aide de la npx create-next-app
commande. Cela initialisera la Next CLI et créera une nouvelle application Next.js.
Nous installerons également les dépendances que nous utiliserons pour le back-end - FaunaDB et SWR - via la ligne de commande. SWR (state-while-revalidate) est un crochet Next.js pour récupérer des données. Nous aborderons cela en profondeur plus tard dans ce tutoriel.
Pour installer Next.js, saisissez la commande suivante dans la CLI :
npx create-next-app snippetapp
La commande ci-dessus crée un répertoire de projet appelé snippetapp
avec le modèle de démarrage Next.js, qui contient les fichiers requis pour le codage avec Next. Une fois l'installation de Next terminée, accédez au répertoire nouvellement créé :
cd snippetapp
Pour installer Fauna, nous utiliserons la commande suivante dans la CLI :
npm install --save faunadb
Ensuite pour installer SWR :
npm install swr@0.3.8
Avec cela, nous avons installé toutes les dépendances que nous utiliserons pour construire notre application et pouvons maintenant procéder à la configuration de notre base de données sur Fauna.
FaunaDB est une base de données en temps réel sans serveur. Il transforme une base de données traditionnelle en une API de données flexible qui conserve les capacités d'une base de données et ses performances tout en offrant un accès sécurisé et évolutif aux données des applications.
Ici, nous allons créer un compte utilisateur et configurer la base de données pour stocker les données que nous utiliserons dans notre application d'extrait de code.
Pour créer un compte utilisateur, accédez à la page d'inscription Fauna et créez un compte.
Après avoir créé un compte utilisateur, vous serez redirigé vers le tableau de bord.
Ici, nous allons créer une base de données avec les collections nécessaires pour gérer les extraits de code de notre application. Cliquez sur CRÉER UNE BASE DE DONNÉES . Nous allons créer une base de données appelée snippets
.
Sur la nouvelle page qui s'ouvre, cliquez sur NOUVELLE COLLECTION et créez une collection appelée codesnippet
.
Après avoir créé une collection, nous obtenons une page où nous pouvons créer un document.
Ici, vous cliquerez sur NOUVEAU DOCUMENT . Un document JSON s'ouvrira, dans lequel vous pourrez entrer les détails, comme illustré ci-dessous.
{
name: "Prompt User",
description: "prompts the user",
language: "javascript",
code: "prompt('would you like to continue')"
}
Ici, nous définissons un extrait avec les attributs : name
, description
et language
. code
Cliquez sur ENREGISTRER pour enregistrer la nouvelle collection. Nous avons ajouté avec succès un extrait à notre base de données. Nous pouvons maintenant procéder à l'obtention de nos identifiants d'accès à utiliser sur notre application.
Sur le tableau de bord, cliquez sur Sécurité . Cela ouvre une nouvelle page pour créer notre clé de sécurité.
Ici, nous allons définir le rôle sur "serveur" au lieu de "admin", et vous pouvez donner un nom à la clé. Cliquez sur le bouton SAVE pour générer votre clé.
.env
fichierNous allons maintenant créer un .env
fichier dans le répertoire de notre projet. Ce fichier stockera notre clé secrète générée. Dans le .env
fichier nous avons ceci :
FAUNA_SECRET = paste your key here
Dans cette section, nous allons créer la page d'affichage et de téléchargement des extraits de code, et y ajouter des fonctionnalités.
Ouvrez le répertoire du projet dans votre éditeur de code et accédez au index.js
fichier dans votre dossier de pages. Ici, nous allons effacer le code et commencer à créer notre application :
import Head from "next/head"
import Image from "next/image"
import styles from "../styles/Home.module.css"
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>View Snippet</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>Re-usuable Code Snippets</h1>
<p className={styles.info}>Add your code snippets here...</p>
<button>Create new snippet</button>
</main>
</div>
)
}
Nous allons maintenant créer un fichier de composant qui affichera nos extraits. Créez un dossier nommé component
dans votre répertoire de travail et créez un fichier nommé Snippets.js
à l'intérieur avec le code suivant :
import React from "react"
import styles from "../styles/Home.module.css"
function Snippets() {
return (
<div className={styles.cont}>
<p className={styles.lang}>language</p>
<h3 className={styles.name}>name of snippet</h3>
<p className={styles.descp}>description of snippet</p>
{/* Code will be displayed here*/}
<div className={styles.links}>
<a>Edit</a>
<a>Delete</a>
</div>
</div>
)
}
export default Snippets
Nous allons maintenant ajouter des importations pour ce fichier dans notreindex.js
:
import Snippets from "../components/Snippets"
Et utilisez-le dans notre application :
<button>Create new snippet</button>
<Snippets/>
Nous pouvons maintenant styliser notre page. Accédez au Home.module.css
fichier dans le styles
dossier et remplacez les styles par ce qui suit :
.container{
display: flex;
height: 100%;
min-height: 100vh;
background: rgb(48, 48, 255);
flex-direction: column;
align-items: center;
color: #fff;
font-family: Montserrat;
}
.cont{
color: #333;
margin-top: 5px;
background: rgb(214, 214, 214);
border-radius: 15px;
padding: 10px 15px;
}
.main button{
width: fit-content;
flex-grow: unset;
display: inline-block;
padding: 5px 10px;
outline: none;
border: none;
border-radius: 5%;
font-weight: bold;
color: rgb(48, 48, 255);
}
.main button:hover{
cursor: pointer;
}
.links{
margin-top: 10px;
}
.links a{
margin-left: 5px;
}
.links a:hover{
cursor: pointer;
}
À ce stade, vous devriez pouvoir démarrer le serveur de développement avec npm run dev
, visiter http://localhost:3000 et voir le squelette de notre application.
Ensuite, nous allons créer la section d'affichage pour l'extrait de code. Créez un nouveau fichier appelé Code.js
dans le dossier des composants et importez-le dans Snippets.js
:
import React from 'react'
import styles from '../styles/Home.module.css'
import Code from "./Code";
function Snippets() {
return (
<div className={styles.cont}>
<p className={styles.lang}>language</p>
<h3 className={styles.name}>name of snippet</h3>
<p className={styles.descp}>description of snippet</p>
{/* Code will be displayed here*/}
<Code />
<div className={styles.links}>
<a>Edit</a>
<a>Delete</a>
</div>
</div>
)
}
export default Snippets
Pour la coloration syntaxique du code, nous utiliserons deux packages, à savoir react-syntax-highlighter et react-copy-to-clipboard . Nous pouvons le télécharger via la CLI :
npm install react-syntax-highlighter react-copy-to-clipboard --save
Puis dans Code.js
:
import React from "react"
import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"
import {atomDark} from "react-syntax-highlighter/dist/cjs/styles/prism"
import { CopyToClipboard } from "react-copy-to-clipboard"
import styles from "../styles/Home.module.css"
function Code() {
const codeString = "npm install import react from 'react'"
const [show, setshow] = React.useState(false)
return (
<div>
<button onClick={() => setshow(!show)}>Show Code</button>
{show ? (
<div>
<CopyToClipboard text={codeString}>
<button className={styles.btn}>Copy</button>
</CopyToClipboard>
<SyntaxHighlighter language="javascript" style={atomDark}>
{codeString}
</SyntaxHighlighter>
</div>
) : null}
</div>
)
}
export default Code
Ici, nous avons créé un composant pour afficher le code avec la coloration syntaxique. Nous avons également ajouté des fonctionnalités de copie et de basculement d'affichage. Maintenant dans le styles
fichier :
.btn{
left: 80%;
position: relative;
}
Pour afficher cette modification, vous pouvez exécuter npm run dev
la ligne de commande et l'afficher dans votre navigateur. Nous avons la chaîne "npm install import react from 'react'" affichée avec la coloration syntaxique en tant que bloc de code. Il y a aussi un bouton pour masquer et afficher l'extrait de code, et un bouton qui nous permet de copier le code du bloc de code.
Dans cette section, nous allons récupérer les données de notre base de données FaunaDB vers notre application. Créez un fichier appelé Fauna.js
dans votre répertoire de projet :
const faunadb = require("faunadb")
const faunaClient = new faunadb.Client({
secret: process.env.FAUNA_SECRET
})
const q = faunadb.query
const getResponse = async () => {
const { data } = await faunaClient.query(
q.Map(
q.Paginate(q.Documents(q.Collection("codesnippet"))),
q.Lambda("doc", q.Get(q.Var("doc")))
)
)
const snippets = data.map((snippet) => {
snippet.id = snippet.ref.id
delete snippet.ref
return snippet
})
return snippets
}
module.exports = {
getResponse,
}
Ici, nous avons initialisé FaunaDB avec notre clé secrète. Nous avons également mis en place une async
requête pour interroger notre collection et renvoyer les données. Nous avons stocké les données renvoyées dans une variable nommée snippets
et supprimé la référence pour mieux structurer les données. D'autres fonctionnalités de création, de mise à jour et de suppression de snippets seront ajoutées ultérieurement dans ce tutoriel.
Notez que si vous obtenez une erreur non autorisée dans la console, vous devrez peut-être spécifier le nom de domaine du point de terminaison cible. La valeur par défaut est db.fauna.com
, mais depuis l'introduction des groupes de régions , trois domaines cloud sont disponibles. Utilisez le domaine correct pour le groupe de régions de votre base de données :
db.fauna.com
db.us.fauna.com
db.eu.fauna.com
Exemple de code :
const faunaClient = new faunadb.Client({
secret: process.env.FAUNA_SECRET,
domain: "db.eu.fauna.com"
})
Nous allons également créer un fichier pour gérer notre requête API pour notre base de données. Dans le api
dossier de pages
, créez un fichier appelé snippets.js
avec le code suivant :
import { getResponse } from "../../Fauna.js"
export default async function handler(req, res) {
console.log(req)
if (req.method !== "GET") {
return res.status(405)
}
try {
const snippets = await getResponse()
return res.status(200).json(snippets)
} catch (err) {
console.log(err)
res.status(500).json({ msg: "Something went wrong." })
}
}
Ci-dessus, nous avons simplement mis en place une fonction pour gérer les requêtes de notre base de données. Les extraits sont renvoyés au fur et à mesure Json
et consigneront les erreurs le cas échéant. Dans Next.js, tout fichier stocké dans le api
dossier est traité comme des points de terminaison d'API plutôt que comme une page et est rendu côté serveur.
Comme indiqué précédemment, SWR (state-while-revalidate) est un crochet Next.js pour récupérer des données. C'est une solution parfaite pour récupérer des données fréquemment mises à jour et convient parfaitement à notre application.
Nous l'utiliserons pour récupérer les données de FaunaDB. Pour l'utiliser, nous devons l'importer dans index.js
:
import useSWR from "swr"
export default function Home() {
const { data:snippets, mutate }=useSWR("api/snippets")
...
})
Ici, nous avons importé SWR et l'avons utilisé pour récupérer les données telles que configurées dans snippets.js
. Nous avons ensuite stocké ces extraits dans la snippets
variable et les afficherons à partir de là. Nous allons maintenant passer le snippets
à notre Snippets
composant pour afficher :
- <Snippets />
+ {snippets &&
+ snippets.map((snippet) => (
+ <Snippets
+ key={snippet.id}
+ snippet={snippet}
+ snippetDeleted={mutate}
+ />
+ ))
+ }
Ci-dessus, nous avons transmis la clé et l'extrait à Snippets
. Nous avons également configuré une mutate
propriété pour mettre à jour (récupérer à nouveau) les extraits lorsqu'un extrait est supprimé. Pour utiliser les données transmises, nous modifions le Snippets
composant avec ce qui suit :
function Snippets({snippet}) {
return (
<div className={styles.cont}>
<p className={styles.lang}>{snippet.data.language}</p>
<h3 className={styles.name}>{snippet.data.name}</h3>
<p className={styles.descp}>{snippet.data.description}</p>
<Code snippet={snippet}/>
<div className={styles.links}>
<a>Edit</a>
<a>Delete</a>
</div>
</div>
)
}
Ci-dessus, nous avons inséré le langage de l'extrait, le nom et la description reçus de FaunaDB dans notre code. Pour obtenir le code de Fauna dans notre application, nous avons également dû transmettre l'extrait de code au Code
composant.
Puis dans le Code
composant :
function Code({snippet}){
...
<div>
<CopyToClipboard text={snippet.data.code}>
<button className={styles.btn}>Copy</button>
</CopyToClipboard>
<SyntaxHighlighter language="javascript" style={atomDark}>
{snippet.data.code}
</SyntaxHighlighter>
</div>
...
}
Nous en avons maintenant terminé avec la GetSnippet
fonctionnalité. Si nous revenons à FaunaDB et créons un nouvel extrait, nous voyons ce qui est illustré ci-dessous.
{
"name": "console.log()",
"language": "javascript",
"description": "logs out data",
"code": "console.log('Hello, world!')"'
}
Pour exécuter dans la CLI :
npm run dev
Si vous ouvrez la page dans votre navigateur, vous aurez un résultat similaire à l'image ci-dessous.
Nous avons créé avec succès une page d'affichage d'extrait de code avec des fonctionnalités permettant d'afficher et de masquer le code et de copier l'extrait de code.
Nous devrons créer un lien vers la page de téléchargement à partir de notre composant d'accueil. Next.js a des dispositions qui facilitent le routage sans que vous ayez à installer react-router
et d'autres dépendances comme vous le feriez si vous utilisiez du code React natif.
Dans index.js
, nous importerons le Link
module depuis next
:
import Link from "next/link"
Ajoutez-le ensuite à notre bouton Créer un nouvel extrait :
- <button>Create new snippet</button>
+ <Link href="/upload">
+ <button>Create new snippet</button>
+ </Link>
Nous allons créer une nouvelle page dans notre pages
dossier et la nommer upload.js
.
De retour dans notre Fauna.js
fichier, nous allons créer et également exporter une fonction pour créer des extraits dans notre application :
const createSnippet = async (code, language, description, name) => {
return await faunaClient.query(q.Create(q.Collection("codesnippet"), {
data:{code, language, description, name}
}))
}
module.exports = {
getResponse,
createSnippet,
}
Ici, nous avons créé la fonction createSnippet
, qui prendra certains paramètres et les transmettra en tant que données dans le nouveau document qui sera créé dans la base de données.
Nous allons également configurer notre point de terminaison pour créer des extraits. Créez un nouveau fichier appelé createSnippet.js
dans le api
dossier et remplissez-le avec le code suivant :
import { createSnippet } from "../../Fauna"
export default async function handler(req, res) {
const { code, language, description, name } = req.body
if (req.method !== "POST") {
return res.status(405).json({msg:"unauthorized"})
}
try {
const createdSnippet = await createSnippet(code, language, description, name)
return res.status(200).json(createdSnippet)
} catch (error) {
console.log(error)
res.status(500).json({msg:"unauthorized"})
}
}
Nous allons maintenant créer la page de téléchargement dans notre upload.js
fichier. Pour que notre formulaire crée des extraits, nous utiliserons le react-hook-form . Nous allons l'installer via la CLI :
npm install react-hook-form
Ensuite, dans notre upload.js
dossier :
import React from "react"
import { useForm } from "react-hook-form"
import { useRouter } from "next/router"
import style from "../styles/form.module.css"
import { Link } from "next/link"
function upload({ snippet }) {
const { register, handleSubmit, errors, reset } = useForm()
const router = useRouter()
const createSnippet = async (data) => {
const { code, language, description, name } = data
console.log(data)
try {
// code here to push to Fauna
} catch (error) {
console.log(error)
}
}
return (
<div className={style.cont}>
<form
className={style.form}
onSubmit={handleSubmit(snippet ? updateSnippet : createSnippet)}
>
<div>
<label htmlFor="name">Name</label>
<input
className={style.input}
type="text"
id="name"
{...register("name", { required: true })}
/>
</div>
<div>
<label className={style.label} htmlFor="language">
language
</label>
<select
className={style.select}
type="text"
id="language"
{...register("language", { required: true })}
>
<option>Javascript</option>
<option>Html</option>
<option>CSS</option>
</select>
</div>
<div>
<label className={style.label} htmlFor="description">
description
</label>
<textarea
className={style.input}
rows={7}
type="text"
id="description"
placeholder="snippet description"
{...register("description", { required: true })}
/>
</div>
<div>
<label className={style.label} htmlFor="code">
Code
</label>
<textarea
className={style.input}
rows={8}
columns={8}
type="text"
id="code"
{...register("code", { required: true })}
placeholder="background: none;"
/>
</div>
<div>
<button className={style.button}>Submit</button>
<button className={style.button}>Cancel</button>
</div>
</form>
</div>
)
}
export default upload
Ci-dessus, nous avons créé notre formulaire en utilisant le react-hook-form
package. Nous avons utilisé la handleSubmit
fonction useForm()
dans l'opérateur ternaire. Lors de la soumission du formulaire, il détermine si la soumission effectuée consiste à créer ou à mettre à jour un extrait de code existant. Avec register
, nous avons ajouté la propriété requise à chaque champ de notre formulaire. Nous avons également ajouté des importations pour une feuille de style nommée form.module.css
où nous avons les styles suivants pour notre formulaire :
.form {
max-width: 800px;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.cont{
background: rgb(48, 48, 255);
height: 100%;
min-height: 100vh;
padding: 10px 0 0 0;
display: flex;
justify-content: center;
align-items: center;
}
.select,
.input {
display: block;
box-sizing: border-box;
width: 100%;
border-radius: 4px;
border: 1px solid black;
padding: 10px 15px;
margin-bottom: 15px;
font-size: 14px;
}
.label{
line-height: 2;
text-align: left;
display: block;
margin: 5px;
color: white;
font-size: 14px;
font-weight: 200;
}
.button {
background : #fff;
color: #444;
border: none;
border-radius: 5%;
margin-right: 8px;
}
Pour envoyer les données de notre formulaire vers la base de données FaunaDB, ajoutez le code suivant au try...catch
bloc dans la createSnippet
fonction dans upload.js
:
try {
await fetch("/api/createSnippet", {
method: "POST",
body: JSON.stringify({ code, language, description, name }),
headers: {
"Content-type": "application/json"
},
})
router.push("/")
} catch (error) {
console.log(error)
}
Exécutez le code et accédez à la page de téléchargement. Maintenant, si nous ajoutons un nouvel extrait au formulaire et cliquons sur Soumettre , nous verrons ce qui est illustré ci-dessous.
Lorsque nous naviguons vers notre composant d'accueil, nous pouvons voir l'extrait de code créé.
Pour créer notre fonctionnalité d'édition d'extrait de code, de retour dans le Fauna.js
fichier, nous allons créer et exporter une fonction pour gérer cette tâche :
const updateSnippet = async (id, code, language, description, name) => {
return await faunaClient.query(q.Update(q.Ref(q.Collection("codesnippet"), id), {
data: {code, language, name, description},
}))
}
module.exports = {
...
updateSnippet,
}
Cette fonction est similaire à la createSnippet
fonction , mais elle prend également un paramètre de id
. Il utilise cet ID pour identifier les extraits à modifier. Si le id
correspond, nous mettons à jour les données avec les autres paramètres. Nous allons également créer un fichier de point de terminaison dans le api
répertoire appelé updateSnippet.js
pour gérer les mises à jour :
import { updateSnippet } from "../../Fauna"
export default async function handler(req, res) {
const { id, code, language, description, name } = req.body
if (req.method !== "PUT") {
return res.status(405).json({ msg: "unauthorized" })
}
try {
const updated = await updateSnippet(
id,
code,
language,
description,
name
)
return res.status(200).json(updated)
}
catch (error) {
console.log(error)
res.status(500).json({ msg: "unauthorized" })
}
}
Maintenant, passez au Snippets
composant et modifiez ce composant pour utiliser cette fonction. Tout d'abord, nous allons importer le Link
module :
...
import Link from "next/link"
Nous modifions également notre edit
bouton :
- <a>Edit</a>
+ <Link href={`/edit/${snippet.id}`}>
+ <a>Edit</a>
+ </Link>
Lorsqu'il est cliqué, il envoie une requête à la page edit
avec l' id
extrait de code sélectionné. Dans le pages
dossier, créez un dossier nommé edit
avec un fichier [id].js
à l'intérieur :
import { getSnippetById } from "../../Fauna"
import Upload from "../upload"
export default function Home({ snippet }) {
const email = ""
const user = ""
return (
<div>
<h3>Update a snippet</h3>
<Upload snippet={snippet} email={email} user={user}/>
</div>
)
}
export async function getServerSideProps(context) {
try {
//get and update record
const id = context.params.id
}
catch (error) {
console.log(error)
context.res.statusCode = 302
context.res.setHeader("Location", "/")
return {props: {}}
}
}
Dans [id].js
, nous transmettons l'extrait de code props
à la page de téléchargement d'extraits. Cependant, cette fois, la page de téléchargement contiendra les données stockées dans l'extrait de code référencé par le id
. Pour récupérer l'extrait par ID, nous devrons créer la getSnippetById
fonction dans le Fauna.js
fichier :
const getSnippetById = async (id) => {
const snippet = await faunaClient.query(q.Get(q.Ref(q.Collection("codesnippet"),id)))
snippet.id = snippet.ref.id
delete snippet.ref
return snippet
}
module.exports = {
getResponse,
createSnippet,
updateSnippet,
getSnippetById,
}
Lorsque nous exportons la fonction, de retour dans le [id].js
fichier, nous pouvons l'utiliser pour récupérer un extrait particulier avec son ID :
try {
const id = context.params.id;
const snippet = await getSnippetById(id);
return {
props: { snippet },
};
} catch (error) {
// as before
}
Maintenant, dans le upload.js
fichier, nous allons le modifier pour pouvoir accéder aux données stockées si un extrait doit être modifié :
- const { register, handleSubmit, errors, reset } = useForm()
+ const { register, handleSubmit, errors, reset } = useForm({
+ defaultValues: {
+ code: snippet ? snippet.data.code : "",
+ language: snippet ? snippet.data.language : "",
+ description: snippet ? snippet.data.description : "",
+ name: snippet ? snippet.data.name : "",
+ }
+ })
Le code ci-dessus vérifie si l'extrait contient des données stockées. S'il renvoie true, il renvoie les données aux paramètres : code
, language
et description
. code
S'il renvoie false
, il renvoie une chaîne vide.
Ensuite, nous allons créer une fonction pour mettre à jour l'extrait de code :
const createSnippet = async (data) => { ... }
const updateSnippet = async (data) => {
const { code, language, description, name } = data
const id = snippet.id
try {
await fetch("/api/updateSnippet", {
method: "PUT",
body: JSON.stringify({ code, language, description, name, id }),
headers: {
"Content-Type": "application/json",
},
})
router.push("/")
}
catch (error) {
console.log(error)
}
}
return ( ,,, )
Si nous exécutons notre code, nous pouvons modifier les extraits de code créés précédemment en cliquant sur le bouton Modifier , en modifiant les données du formulaire et en cliquant sur Soumettre .
Maintenant, si nous revenons au Home
composant dans notre navigateur, nous pouvons éditer et mettre à jour des extraits de code. Nous pouvons enfin ajouter la fonctionnalité finale pour supprimer notre extrait de code. Créez et exportez une nouvelle fonction — deleteSnippet
— dans le Fauna.js
fichier :
const deleteSnippet = async (id) => {
return await faunaClient.query(q.Delete(q.Ref(q.Collection("codesnippet"),id)))
}
module.exports = {
...
deleteSnippet,
}
Nous allons créer un autre point de terminaison pour cette fonction dans notre api
dossier appelé deleteSnippet.js
et le remplir avec le code suivant :
import { deleteSnippet } from "../../Fauna"
export default async function handler(req, res) {
if (req.method !== "DELETE") {
return res.status(405).json({ msg: "unauthorized" })
}
const { id } = req.body
try {
const deleted = await deleteSnippet(id)
return res.status(200).json(deleted)
}
catch (error) {
console.log(error)
res.status(500).join({ msg: "error occured" })
}
}
Ensuite, nous modifions le Snippets.js
fichier pour ajouter la nouvelle fonctionnalité :
function Snippets({ snippet, snippetDeleted }) {
...
}
Créez ensuite une deleteSnippet
fonction pour récupérer le point de terminaison à partir de api
et supprimez l'extrait de code référencé par l'ID :
function Snippets({snippet, snippetDeleted}) {
const deleteSnippet = async () => {
try {
await fetch("/api/deleteSnippet", {
method: "DELETE",
body: JSON.stringify({ id: snippet.id }),
headers: {
"Content-Type": "application/json",
},
});
snippetDeleted();
} catch (e) {
console.log(e);
}
};
return (
<div className={styles.cont}>
<p className={styles.lang}>{snippet.data.language}</p>
<h3 className={styles.name}>{snippet.data.name}</h3>
<p className={styles.descp}>{snippet.data.description}</p>
<Code snippet={snippet}/>
<div className={styles.links}>
<Link href={`/edit/${snippet.id}`}>
<a>Edit</a>
</Link>
<a onClick={deleteSnippet}>Delete</a>
</div>
</div>
)
}
Nous avons également mis à jour l'élément d'ancrage pour appeler la deleteSnippet
fonction lorsqu'il est cliqué.
Nous avons ajouté une fonctionnalité pour supprimer des extraits de code. Nous pouvons maintenant supprimer des extraits en cliquant sur le bouton Supprimer dans notre application.
Ceci conclut les fonctionnalités de l'application d'extrait de code. Nous allons maintenant ajouter des mesures d'authentification à notre application pour permettre uniquement aux utilisateurs autorisés de créer ou de modifier des extraits de code dans notre application.
Pourquoi avons-nous besoin d'une authentification ? Actuellement, les utilisateurs peuvent créer des extraits, mais ils peuvent également supprimer et modifier des extraits qu'ils n'ont pas créés. Nous devrons fournir un moyen d'autoriser les utilisateurs à accéder à notre site - et donc le besoin d'authentification des utilisateurs.
Nous allons installer next-auth pour l'authentification via notre CLI :
npm i next-auth
Nous utiliserons un jeton JWT pour notre authentification. JWT est une norme utilisée pour créer des jetons d'accès pour une application.
Créez un dossier nommé auth
dans votre api
dossier et à l'intérieur de celui-ci, créez un fichier [...nextauth].js
contenant le code suivant :
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
export default NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth?prompt=consent&access_type=offline&response_type=code",
})
],
jwt: {
encryption: true
},
secret: process.env.secret,
callbacks: {
async jwt(token, account) {
if (account ?.accessToken) {
token.accessToken = account.accessToken
}
return token
},
redirect: async (url, _baseUrl)=>{
if (url === "/profile") {
return Promise.resolve("/")
}
return Promise.resolve("/")
}
}
})
Après cela, nous allons encapsuler nos composants dans le _app.js
fichier :
import '../styles/globals.css'
import {Provider} from "next-auth/client"
function MyApp({ Component, pageProps }) {
return (
<Provider session={pageProps.session}>
<Component {...pageProps} />
</Provider>
)
}
export default MyApp
Nous modifierons notre Home
composant en index.js
pour revenir à notre composant si l'utilisateur est authentifié, sinon il renvoie un bouton qui mène à la page d'authentification :
import {signIn, signOut, useSession} from "next-auth/client"
...
Puis dans Home
:
export default function Home() {
const { data:snippets, mutate }=useSWR("api/snippets")
const [session, loadingSession] = useSession()
if (loadingSession) {
<>
<p>...authenticating</p>
</>
}
...
}
Le code ci-dessus vérifie si l'application est loadingSession
. Si vrai, il renvoie le p
bloc de balises, sinon il renvoie le reste de notre application s'il y a session
. Ensuite, nous afficherons la "connexion" s'il n'y a pas de session :
return (
<div className={styles.container}>
<Head> ... </Head>
{!session && (
<>
<h1>Sign in to access snippet app</h1>
<button onClick={() => signIn()}>Sign In</button>
</>
)}
{session && (
<>
<main className={styles.main}>
<h3>welcome {session.user.email}</h3>
<button onClick={() => signOut()}>Sign Out</button>
...
</main>
</>
)}
</div>
)
Pour utiliser le "service de connexion Google", nous avons besoin d'informations d'identification d'accès à partir de la console cloud de Google. Pour l'obtenir, connectez-vous à votre compte Google et accédez à la console Google Cloud . Cliquez sur CRÉER UN PROJET sur la page, entrez le nom de votre projet et cliquez sur Créer .
Sur la nouvelle page qui s'ouvre, cliquez sur + CRÉER DES IDENTIFIANTS dans la barre de menu supérieure et enfin sélectionnez ID client OAuth dans le menu déroulant.
Sur la page qui s'ouvre, vous recevrez une notification avec un bouton vous demandant de "Configurer l'écran de consentement". Cliquez sur ce bouton.
Sur la page suivante, sélectionnez Externe sous le type d'utilisateur et cliquez sur Créer . Entrez les champs requis pour votre "Nom de l'application" et "Email" et cliquez sur Enregistrer et continuer .
Dans les sections Portées et Tester les utilisateurs , faites défiler vers le bas et cliquez sur Enregistrer et continuer .
Enfin, cliquez sur Revenir au tableau de bord et cliquez sur le bouton Publier .
Maintenant, nous pouvons créer notre clé en cliquant sur Credentials dans le menu latéral, puis sur Create Credentials dans la barre de menu supérieure. Sélectionnez Oauth Client ID dans la liste déroulante et vous obtiendrez une page demandant le type d'application.
Sélectionnez Web Application puis, sous « Authorized JavaScript origins », cliquez sur Add URI et saisissez http://localhost
. Enfin, sous « Authorized redirect URIs », cliquez sur Add URI et entrez http://localhost/api/auth/callback/google
dans le champ, avant de cliquer sur Create .
Copiez l'ID client et le secret client depuis la fenêtre contextuelle qui s'ouvre et ajoutez-les au .env
fichier :
GOOGLE_CLIENT_ID=id
GOOGLE_CLIENT_SECRET=secret
Nous pouvons maintenant nous connecter en utilisant l'authentification Google à notre application. De plus, nous allons configurer notre upload.js
fichier en tant que route protégée afin que les utilisateurs non autorisés ne puissent pas créer de nouveaux extraits :
import { getSession } from "next-auth/client"
function Upload({ snippet, user }) { ... }
export async function getServerSideProps(context) {
const session = await getSession(context)
if (!session) {
context.res.writeHead(302, { Location: "/" })
context.res.end()
return {}
}
return {
props: {
user: session.user,
}
}
}
export default Upload;
Si nous exécutons notre application avec la npm run dev
commande, nous aurons d'abord une page nous demandant de "se connecter". Nous ne pouvons pas accéder à la page de téléchargement via le /upload
chemin dans notre URL. Nous ne pouvons accéder à notre application que lorsque nous utilisons la fonction de connexion Google pour nous connecter à notre application.
Enfin, nous modifierons la createSnippet
fonctionnalité pour ajouter l'e-mail de l'utilisateur à la base de données, puis nous n'afficherons les boutons Modifier et Supprimer que si l'e-mail correspond.
Dans Fauna.js
, modifiez la createSnippet
fonction comme ceci :
const createSnippet = async (code, language, description, name, mail) => {
return await faunaClient.query(q.Create(q.Collection("codesnippet"), {
data:{code, language, description, name, mail}
}))
}
Dans le createSnippet.js
fichier, apportez les modifications suivantes :
- const { code, language, description, name } = req.body;
+ const { code, language, description, name, mail } = req.body;
- const createdSnippet = await createSnippet(code, language, description, name);
+ const createdSnippet = await createSnippet(code, language, description, name, mail);
Dans upload.js
:
function upload({ snippet, user }) {
+ const email = user.email;
...
}
Et modifiez la createSnippet
fonction et la updateSnippet
fonction, comme suit :
const createSnippet = async (data) => {
const { code, language, description, name, mail } = data;
console.log(data)
try {
await fetch("/api/createSnippet", {
method: "POST",
body: JSON.stringify({ code, language, description, name, mail:email }),
headers: {
"Content-type": "application/json"
},
})
router.push("/")
} catch (error) {
console.log(error)
}
}
const updateSnippet = async (data) => {
const { code, language, description, name } = data
const id = snippet.id
try {
await fetch("/api/updateSnippet", {
method: "PUT",
body: JSON.stringify({ code, language, description, name, mail:email }),
headers: {
"Content-Type": "application/json",
},
})
router.push("/")
}
catch (error) {
console.log(error)
}
}
Nous pouvons maintenant procéder à l' affichage des boutons Modifier et Supprimer uniquement si l'e-mail correspond.
Tout d'abord, nous passons les user.mail
as props au Snippet
composant in index.js
:
<Snippets
key={snippet.id}
snippet={snippet}
snippetDeleted={mutate}
+ email={session.user.email}
/>
Puis dans Snippet.js
:
function Snippets({ snippet, snippetDeleted, email }) {
...
{email == snippet.data.mail && (
<>
<div className={styles.links}>
<Link href={`/edit/${snippet.id}`}>
<a>Edit</a>
</Link>
<a onClick={deleteSnippet}>Delete</a>
</div>
</>
)}
...
}
Exécutez npm run dev
dans la CLI et ouvrez l'application dans votre navigateur. Désormais, si vous créez un nouvel extrait, l'e-mail de l'utilisateur est ajouté à la base de données. Si l'e-mail ne correspond pas, les boutons Modifier et Supprimer ne s'affichent pas sur la page d'affichage de l'extrait. Vous pouvez tester cela en vous connectant avec une adresse e-mail différente de celle utilisée pour créer les extraits de code.
Nous sommes enfin arrivés à la fin de ce tutoriel. Nous avons appris à créer une application CRUD avec Next.js et FaunaDB, et à effectuer des opérations CRUD basées sur l'authentification de l'utilisateur.
Pour consulter le code complet, visitez le dépôt GitHub .
Source : https://www.sitepoint.com/nextjs-faunadb-build-code-snippet-app/
1625674200
In this video, we are going to implement Google Analytics to our Next JS application. Tracking page views of an application is very important.
Google analytics will allow us to track analytics information.
Frontend: https://github.com/amitavroy/video-reviews
API: https://github.com/amitavdevzone/video-review-api
App link: https://video-reviews.vercel.app
You can find me on:
Twitter: https://twitter.com/amitavroy7
Discord: https://discord.gg/Em4nuvQk
#next js #js #react js #react #next #google analytics
1625142062
AngularJS was introduced in the year 2009, by Google. AngularJS is a software framework used worldwide by developers. The entire base of this framework is open source. AngularJS has gained popularity among developers because of how it has become for them to create web applications. AngularJS helps in building apps that require less work and reduces the use of unnecessary codes. AngularJS application development is a javascript framework. AngularJS has a clear goal to make the entire process simpler, it also helps app development process and operations as much as it could. AngularJS is used for building applications that support MVC (model view controller) and SPAs (single page web apps) coding and programming structures. AngularJS has been used by some of the top companies in the world to simplify their app development process, like, Google, Paypal, Udemy, mobile site in iPad for HBO, etc. To read more click on the link.
#hire angular js developer #hire dedicated angular js developer #angular js application development #hire dedicated angular js team #hire best angular js application developer
1616839211
Top organizations and start-ups hire Node.js developers from SISGAIN for their strategic software development projects in Illinois, USA. On the off chance that you are searching for a first rate innovation to assemble a constant Node.js web application development or a module, Node.js applications are the most appropriate alternative to pick. As Leading Node.js development company, we leverage our profound information on its segments and convey solutions that bring noteworthy business results. For more information email us at hello@sisgain.com
#node.js development services #hire node.js developers #node.js web application development #node.js development company #node js application