One place for hosting & domains

      Comment créer une pagination personnalisée avec React


      Introduction

      Nous nous impliquons souvent dans la construction d’applications web où nous devons récupérer de grands ensembles de données à partir d’un serveur distant, d’une API ou d’une base de données. Si vous mettez en place un système de paiement, par exemple, il peut aller chercher des milliers de transactions. S’il s’agit d’une app de réseaux sociaux, elle peut récupérer de nombreux commentaires, profils ou activités d’utilisateurs. Quoi qu’il en soit, il existe plusieurs solutions pour présenter les données d’une manière qui ne submerge pas l’utilisateur final qui interagit avec l’app.

      Une méthode pour traiter de grands ensembles de données consiste à utiliser la pagination. La pagination fonctionne efficacement lorsque vous connaissez à l’avance la taille de l’ensemble de données (le nombre total d’enregistrements contenu dans l’ensemble de données). Deuxièmement, vous ne chargez que le morceau de données requis de l’ensemble des données en fonction de l’interaction de l’utilisateur final avec le contrôle de pagination. C’est la technique utilisée pour afficher les résultats de recherche dans Google Search.

      Dans ce tutoriel, vous apprendrez comment construire un composant de pagination personnalisé avec React pour la pagination de grands ensembles de données. Vous construirez une vue paginée des pays du monde – un ensemble de données dont la taille est connue.

      Voici une démo de ce que vous allez construire dans ce tutoriel :

      Capture d'écran de l'application de démo - montrant les pays du monde

      Conditions préalables

      Pour suivre ce tutoriel, vous aurez besoin de :

      Ce tutoriel a été vérifié avec Node v14.2.0, npm v6.14.4, react v16.13.1, et react-scripts v3.4.1.

      Étape 1 – Mettre en place le projet

      Lancez une nouvelle application React en utilisant la commande create-react-app. Vous pouvez nommer l’application comme vous le souhaitez, mais ce tutoriel lui donnera le nom react-pagination :

      • npx create-react-app react-pagination

      Ensuite, vous installerez les dépendances nécessaires pour votre application. Tout d’abord, utilisez la fenêtre du terminal pour accéder au répertoire du projet :

      Exécutez la commande suivante pour installer les dépendances requises :

      • npm install bootstrap@4.1.0 prop-types@15.6.1 react-flags@0.1.13 countries-api@2.0.1 node-sass@4.14.1

      Vous installerez alors bootstrap, prop-types, react-flags, countries-api et node-sass.

      Vous avez installé le bootstrap comme une dépendance de votre demande, car vous aurez besoin d’un style par défaut. Vous utiliserez également les styles du composant de pagination Bootstrap.

      Pour inclure Bootstrap dans l’application, modifiez le fichier src/index.js :

      Et ajoutez la ligne suivante avant les autres déclarations d’import :

      src/index.js

      import "bootstrap/dist/css/bootstrap.min.css";
      

      Maintenant, le style Bootstrap sera disponible dans toute votre application.

      Vous avez également installé react-flags comme une dépendance de votre application. Afin d’accéder aux icônes des drapeaux à partir de votre application, vous devez copier les images des icônes dans le répertoire public de votre application.

      Créez un répertoire img dans votre répertoire public :

      Copiez les fichiers images dans flags vers img :

      • cp -R node_modules/react-flags/vendor/flags public/img

      Ce document fournit une copie de tous les react-flag à votre application.

      Maintenant que vous avez inclus quelques dépendances, lancez l’application en exécutant la commande suivante avec npm de la pagination du répertoire du projet react-pagination :

      Maintenant que vous avez lancé l’application, le développement peut commencer. Vous remarquerez qu’un onglet du navigateur a été ouvert pour vous avec la fonctionnalité de rechargement live pour rester en phase avec l’application au fur et à mesure de son développement.

      À ce stade, la vue de l’application devrait ressembler à la capture d’écran suivante :

      Vue initiale - Bienvenue sur React Screen

      Vous êtes maintenant prêt à commencer à créer des composants.

      Étape 2 – Créer le composant CountryCard

      Dans cette étape, vous allez créer le composant CountryCard. Le composant CountryCard génère le nom, la région et le drapeau d’un pays donné.

      Tout d’abord, créons un composant dans le répertoire src :

      Ensuite, créez une nouvelle CountryCard.js dans le répertoire src/components :

      • nano src/components/CountryCard.js

      Et ajoutez-y le code suivant :

      src/components/CountryCard.js

      import React from 'react';
      import PropTypes from 'prop-types';
      import Flag from 'react-flags';
      
      const CountryCard = props => {
        const {
          cca2: code2 = '', region = null, name = {}
        } = props.country || {};
      
        return (
          <div className="col-sm-6 col-md-4 country-card">
            <div className="country-card-container border-gray rounded border mx-2 my-3 d-flex flex-row align-items-center p-0 bg-light">
              <div className="h-100 position-relative border-gray border-right px-2 bg-white rounded-left">
                <Flag country={code2} format="png" pngSize={64} basePath="./img/flags" className="d-block h-100" />
              </div>
              <div className="px-3">
                <span className="country-name text-dark d-block font-weight-bold">{ name.common }</span>
                <span className="country-region text-secondary text-uppercase">{ region }</span>
              </div>
            </div>
          </div>
        )
      }
      
      CountryCard.propTypes = {
        country: PropTypes.shape({
          cca2: PropTypes.string.isRequired,
          region: PropTypes.string.isRequired,
          name: PropTypes.shape({
            common: PropTypes.string.isRequired
          }).isRequired
        }).isRequired
      };
      
      export default CountryCard;
      

      Le composant CountryCard nécessite un prop country qui contient les données sur le pays à afficher. Comme on l’a vu dans le module propTypes pour le composant CountryCard, l’objet prop country doit contenir les données suivantes :

      • cca2 – un code de pays à deux chiffres
      • region – la région du pays (par exemple, « Africa »)
      • name.common – le nom commun du pays (par exemple, « Nigeria »)

      Voici un exemple d’objet country :

      {
        cca2: "NG",
        region: "Africa",
        name: {
          common: "Nigeria"
        }
      }
      

      Notez également comment vous rendez le drapeau du pays en utilisant le paquet react-flags. Vous pouvez consulter la documentation react-flags pour en savoir plus sur les props nécessaires et sur la façon d’utiliser le paquet.

      Vous avez maintenant un composant CountryCard complété. Enfin, vous utiliserez CountryCard plusieurs fois pour afficher dans votre application différents drapeaux et différentes informations sur le pays.

      Dans cette étape, vous créerez le composant Pagination. Le composant Pagination contient la logique de construction, de rendu et de commutation des pages sur le contrôle de pagination.

      Ensuite, créez une nouvelle Pagination.js dans le répertoire src/components :

      • nano src/components/Pagination.js

      Et ajoutez-y le code suivant :

      src/components/Pagination.js

      import React, { Component, Fragment } from 'react';
      import PropTypes from 'prop-types';
      
      class Pagination extends Component {
        constructor(props) {
          super(props);
          const { totalRecords = null, pageLimit = 30, pageNeighbours = 0 } = props;
      
          this.pageLimit = typeof pageLimit === 'number' ? pageLimit : 30;
          this.totalRecords = typeof totalRecords === 'number' ? totalRecords : 0;
      
          // pageNeighbours can be: 0, 1 or 2
          this.pageNeighbours = typeof pageNeighbours === 'number'
            ? Math.max(0, Math.min(pageNeighbours, 2))
            : 0;
      
          this.totalPages = Math.ceil(this.totalRecords / this.pageLimit);
      
          this.state = { currentPage: 1 };
        }
      }
      
      Pagination.propTypes = {
        totalRecords: PropTypes.number.isRequired,
        pageLimit: PropTypes.number,
        pageNeighbours: PropTypes.number,
        onPageChanged: PropTypes.func
      };
      
      export default Pagination;
      

      Le volet Pagination peut prendre quatre props spéciaux, comme indiqué dans l’objet propTypes.

      • onPageChanged est une fonction appelée avec les données de l’état de pagination actuel uniquement lorsque la page en cours change.
      • totalRecords indique le nombre total de documents à paginer. C’est un obligatoire.
      • pageLimit indique le nombre d’enregistrements à afficher par page. Si elle n’est pas spécifiée, la valeur par défaut est 30 tel que défini dans la constructor().
      • pageNeighbours indique le nombre de numéros de page supplémentaires à afficher de chaque côté de la page en cours. La valeur minimale est 0 et la valeur maximale est 2. Si elle n’est pas spécifiée, la valeur par défaut est 0, comme définie dans la fonction constructor().

      L’image suivante illustre l’effet des différentes valeurs du prop pageNeighbours :

      Illustration de la page Neighbours

      Dans la fonction constructor(), vous calculez le nombre total de pages comme suit :

      this.totalPages = Math.ceil(this.totalRecords / this.pageLimit);
      

      Vous remarquerez que vous utilisez la fonctionMath.ceil() ici pour vous assurer que vous obtenez une valeur entière pour le nombre total de pages. Cela garantit également que les documents excédentaires soient saisis à la dernière page, en particulier dans les cas où le nombre de documents excédentaires est inférieur au nombre de documents à afficher par page.

      Enfin, vous avez initialisé l’état avec la propriété currentPage réglée sur 1. Vous avez besoin de cette propriété d’état pour garder une trace de la page actuellement active en interne.

      Ensuite, vous créerez la méthode pour générer les numéros de page.

      Après les importations mais avant la classe Pagination, ajoutez les constantes et la fonction de plage suivantes :

      src/components/Pagination.js

      // ...
      
      const LEFT_PAGE = 'LEFT';
      const RIGHT_PAGE = 'RIGHT';
      
      /**
       * Helper method for creating a range of numbers
       * range(1, 5) => [1, 2, 3, 4, 5]
       */
      const range = (from, to, step = 1) => {
        let i = from;
        const range = [];
      
        while (i <= to) {
          range.push(i);
          i += step;
        }
      
        return range;
      }
      

      Dans la classe Pagination, après la fonction constructor, ajoutez la méthode fetchPageNumbers qui suit :

      src/components/Pagination.js

      class Pagination extends Component {
        // ...
      
        /**
         * Let's say we have 10 pages and we set pageNeighbours to 2
         * Given that the current page is 6
         * The pagination control will look like the following:
         *
         * (1) < {4 5} [6] {7 8} > (10)
         *
         * (x) => terminal pages: first and last page(always visible)
         * [x] => represents current page
         * {...x} => represents page neighbours
         */
        fetchPageNumbers = () => {
          const totalPages = this.totalPages;
          const currentPage = this.state.currentPage;
          const pageNeighbours = this.pageNeighbours;
      
          /**
           * totalNumbers: the total page numbers to show on the control
           * totalBlocks: totalNumbers + 2 to cover for the left(<) and right(>) controls
           */
          const totalNumbers = (this.pageNeighbours * 2) + 3;
          const totalBlocks = totalNumbers + 2;
      
          if (totalPages > totalBlocks) {
            const startPage = Math.max(2, currentPage - pageNeighbours);
            const endPage = Math.min(totalPages - 1, currentPage + pageNeighbours);
            let pages = range(startPage, endPage);
      
            /**
             * hasLeftSpill: has hidden pages to the left
             * hasRightSpill: has hidden pages to the right
             * spillOffset: number of hidden pages either to the left or to the right
             */
            const hasLeftSpill = startPage > 2;
            const hasRightSpill = (totalPages - endPage) > 1;
            const spillOffset = totalNumbers - (pages.length + 1);
      
            switch (true) {
              // handle: (1) < {5 6} [7] {8 9} (10)
              case (hasLeftSpill && !hasRightSpill): {
                const extraPages = range(startPage - spillOffset, startPage - 1);
                pages = [LEFT_PAGE, ...extraPages, ...pages];
                break;
              }
      
              // handle: (1) {2 3} [4] {5 6} > (10)
              case (!hasLeftSpill && hasRightSpill): {
                const extraPages = range(endPage + 1, endPage + spillOffset);
                pages = [...pages, ...extraPages, RIGHT_PAGE];
                break;
              }
      
              // handle: (1) < {4 5} [6] {7 8} > (10)
              case (hasLeftSpill && hasRightSpill):
              default: {
                pages = [LEFT_PAGE, ...pages, RIGHT_PAGE];
                break;
              }
            }
      
            return [1, ...pages, totalPages];
          }
      
          return range(1, totalPages);
        }
      }
      

      Ici, vous définissez d’abord deux constantes : LEFT_PAGE et RIGHT_PAGE. Ces constantes seront utilisées pour indiquer les points où vous avez des contrôles de page pour vous déplacer respectivement à gauche et à droite.

      Vous avez également défini une aide avec la fonctionrange() qui peut vous aider à générer des séries de chiffres.

      Note : Si vous utilisez une bibliothèque d’utilité comme Lodashdans votre projet, vous pouvez alors utiliser la fonction _.range() fournie par Lodash à la place. L’extrait de code suivant montre la différence entre la fonction range() que vous venez de définir et celle de Lodash :

      range(1, 5); // returns [1, 2, 3, 4, 5]
      _.range(1, 5); // returns [1, 2, 3, 4]
      

      Ensuite, vous avez défini la méthode fetchPageNumbers() dans la classe Pagination. Cette méthode gère la logique de base pour générer les numéros de page à afficher sur le contrôle de pagination. Vous voulez que la première page et la dernière page soient toujours visibles.

      Tout d’abord, vous avez défini quelques variables. totalNumbers représente le nombre total de pages qui seront affichées sur le contrôle. totalBlocks représente le nombre total de pages à afficher, plus deux blocs supplémentaires pour les indicateurs de page gauche et droite.

      Si le nombre totalPages n’est pas supérieur à totalBlocks, vous renvoyez une série de chiffres allant de 1 à totalPages. Sinon, vous renvoyez le tableau des numéros de page, avec LEFT_PAGE et RIGHT_PAGE aux endroits où vous avez des pages qui débordent respectivement à gauche et à droite.

      Toutefois, notez que votre contrôle de pagination garantit que la première page et la dernière page sont toujours visibles. Les contrôles des pages gauche et droite apparaissent vers l’intérieur.

      Maintenant, vous allez ajouter la fonction render() pour vous permettre de contrôler la pagination.

      Dans la classe Pagination, après la méthode constructor et fetchPageNumbers, ajoutez la méthode render suivante :

      src/components/Pagination.js

      class Pagination extends Component {
        // ...
      
        render() {
          if (!this.totalRecords || this.totalPages === 1) return null;
      
          const { currentPage } = this.state;
          const pages = this.fetchPageNumbers();
      
          return (
            <Fragment>
              <nav aria-label="Countries Pagination">
                <ul className="pagination">
                  { pages.map((page, index) => {
      
                    if (page === LEFT_PAGE) return (
                      <li key={index} className="page-item">
                        <a className="page-link" href="https://www.digitalocean.com/community/tutorials/#" aria-label="Previous" onClick={this.handleMoveLeft}>
                          <span aria-hidden="true">&laquo;</span>
                          <span className="sr-only">Previous</span>
                        </a>
                      </li>
                    );
      
                    if (page === RIGHT_PAGE) return (
                      <li key={index} className="page-item">
                        <a className="page-link" href="https://www.digitalocean.com/community/tutorials/#" aria-label="Next" onClick={this.handleMoveRight}>
                          <span aria-hidden="true">&raquo;</span>
                          <span className="sr-only">Next</span>
                        </a>
                      </li>
                    );
      
                    return (
                      <li key={index} className={`page-item${ currentPage === page ? ' active' : ''}`}>
                        <a className="page-link" href="https://www.digitalocean.com/community/tutorials/#" onClick={ this.handleClick(page) }>{ page }</a>
                      </li>
                    );
      
                  }) }
      
                </ul>
              </nav>
            </Fragment>
          );
        }
      }
      

      Ici, vous générez le tableau des numéros de page en appelant la fonction fetchPageNumbers() que vous avez créée précédemment. Vous générez ensuite chaque numéro de page en utilisant Array.prototype.map(). Notez que vous enregistrez des gestionnaires d’événements de clic sur chaque numéro de page généré pour gérer les clics.

      Notez également que le contrôle de la pagination ne sera pas effectué si le proptotalRecords n’a pas été correctement transmis au composant Pagination ou dans les cas où il n’y a qu’une page 1.

      Enfin, vous définirez les méthodes de gestion des événements.

      Dans la classe Pagination, après la méthode con fetchPageNumbers et la méthode render, ajoutez ce qui suit :

      src/components/Pagination.js

      class Pagination extends Component {
        // ...
      
        componentDidMount() {
          this.gotoPage(1);
        }
      
        gotoPage = page => {
          const { onPageChanged = f => f } = this.props;
          const currentPage = Math.max(0, Math.min(page, this.totalPages));
          const paginationData = {
            currentPage,
            totalPages: this.totalPages,
            pageLimit: this.pageLimit,
            totalRecords: this.totalRecords
          };
      
          this.setState({ currentPage }, () => onPageChanged(paginationData));
        }
      
        handleClick = page => evt => {
          evt.preventDefault();
          this.gotoPage(page);
        }
      
        handleMoveLeft = evt => {
          evt.preventDefault();
          this.gotoPage(this.state.currentPage - (this.pageNeighbours * 2) - 1);
        }
      
        handleMoveRight = evt => {
          evt.preventDefault();
          this.gotoPage(this.state.currentPage + (this.pageNeighbours * 2) + 1);
        }
      }
      

      Vous définissez la méthode gotoPage() qui modifie l’état et met currentPage à la page spécifiée. Elle garantit que l’argument de la page a une valeur minimale de 1 et une valeur maximale du nombre total de pages. Il appelle enfin la fonction onPageChanged() qui a été transmise comme prop, avec des données indiquant le nouvel état de pagination.

      Lorsque le composant est monté, vous passez à la première page en appelant this.gotoPage(1) comme indiqué dans la méthode de cycle de vie componentDidMount().

      Remarquez comment vous utilisez (this.pageNeighbours * 2) dans handleMoveLeft() et handleMoveRight() pour faire glisser les numéros de page vers la gauche et vers la droite, respectivement, en fonction du numéro de page en cours.

      Voici une démonstration de l’interaction du mouvement de gauche à droite.

      Mouvement gauche-droite de l'interaction

      Vous avez maintenant terminé le composant Pagination. Les utilisateurs pourront interagir avec les commandes de navigation de ce composant pour afficher différentes pages de drapeaux.

      Étape 4 – Création du composant App

      Maintenant que vous avez un composant CountryCard et Pagination, vous pouvez les utiliser dans votre composant App.

      Modifiez le fichier App.js dans le répertoire src :

      Remplacez le contenu de App.js par les lignes de code suivantes :

      src/App.js

      import React, { Component } from 'react';
      import Countries from 'countries-api';
      import './App.css';
      import Pagination from './components/Pagination';
      import CountryCard from './components/CountryCard';
      
      class App extends Component {
        state = { allCountries: [], currentCountries: [], currentPage: null, totalPages: null }
      
        componentDidMount() {
          const { data: allCountries = [] } = Countries.findAll();
          this.setState({ allCountries });
        }
      
        onPageChanged = data => {
          const { allCountries } = this.state;
          const { currentPage, totalPages, pageLimit } = data;
          const offset = (currentPage - 1) * pageLimit;
          const currentCountries = allCountries.slice(offset, offset + pageLimit);
      
          this.setState({ currentPage, currentCountries, totalPages });
        }
      }
      
      export default App;
      

      Ici, vous initialisez l’état du composant App avec les attributs suivants :

      • allCountries – Voici un tableau de tous les pays qui figurent dans votre app. Initialisé vers un tableau vide ([]).
      • currentCountries – Il s’agit d’un tableau de tous les pays qui doivent être affichés sur la page actuellement active. Initialisé vers un tableau vide ([]).
      • currentPage – Le numéro de page de la page actuellement active. Initialisé vers la valeur null.
      • totalPages – Le nombre total de pages pour l’ensemble des fiches pays. Initialisé vers la valeur null.

      Ensuite, dans la méthode du cycle de vie de componentDidMount(), vous récupérez tous les pays du monde en utilisant le paquet countries-api en invoquant Countries.findAll(). Vous mettez ensuite à jour l’état de l’application, en définissant allCountries pour contenir tous les pays du monde. Vous pouvez voir la documentation countries-apipour en savoir plus sur le paquet.

      Enfin, vous avez défini la méthode onPageChanged() qui sera appelée chaque fois que vous naviguerez vers une nouvelle page à partir du contrôle de pagination. Cette méthode sera transmise à la prop onPageChanged du composant Pagination.

      Il y a deux lignes auxquelles il convient de prêter attention dans cette méthode. La première est cette ligne :

      const offset = (currentPage - 1) * pageLimit;
      

      La valeur offset indique l’index de départ pour récupérer les enregistrements de la page en cours. En utilisant (currentPage - 1), on s’assure que la valeur offset est basée sur zéro. Disons, par exemple, que vous affichez 25 enregistrements par page, et que vous êtes en train de consulter la page 5. La valeur offset sera alors de ((5 - 1) * 25 = 100).

      Par exemple, si vous récupérez des enregistrements sur demande à partir d’une base de données, voici un exemple de requête SQL pour vous montrer comment utiliser la valeur offset :

      SELECT * FROM `countries` LIMIT 100, 25
      

      Comme vous ne récupérez pas les enregistrements d’une base de données ou d’une source externe, vous avez besoin d’un moyen d’extraire le bloc d’enregistrements requis pour la page en cours.

      La deuxième est cette ligne :

      const currentCountries = allCountries.slice(offset, offset + pageLimit);
      

      Ici, vous utilisez la méthode Array.prototype.slice() pour extraire le bloc d’enregistrements requis de allCountries en passant la valeur offset comme indice de départ de la tranche et (offset + pageLimit) comme indice avant lequel la tranche doit se terminer.

      Note : Dans ce tutoriel, vous n’avez pas récupéré d’enregistrements provenant d’une source externe. Dans une véritable application, vous irez probablement chercher des enregistrements dans une base de données ou une API. La logique de récupération des enregistrements peut être consultée dans la méthodeonPageChanged() du composant App.

      Supposons que vous ayez un point final API fictif /api/countries?page={current_page}&limit={page_limit}. L’extrait suivant montre comment vous pouvez récupérer des pays à la demande à partir de l’API en utilisant le paquet HTTP [axios][“axios] :

      onPageChanged = data => {
        const { currentPage, totalPages, pageLimit } = data;
      
        axios.get(`/api/countries?page=${currentPage}&limit=${pageLimit}`)
          .then(response => {
            const currentCountries = response.data.countries;
            this.setState({ currentPage, currentCountries, totalPages });
          });
      }
      

      Maintenant, vous pouvez achever le composantApp en ajoutant la méthode render().

      Dans la classe App, mais après componentDidMount et onPageChanged, ajoutez la méthode render suivante :

      src/App.js

      class App extends Component {
        // ... other methods here ...
      
        render() {
          const { allCountries, currentCountries, currentPage, totalPages } = this.state;
          const totalCountries = allCountries.length;
      
          if (totalCountries === 0) return null;
      
          const headerClass = ['text-dark py-2 pr-4 m-0', currentPage ? 'border-gray border-right' : ''].join(' ').trim();
      
          return (
            <div className="container mb-5">
              <div className="row d-flex flex-row py-5">
                <div className="w-100 px-4 py-5 d-flex flex-row flex-wrap align-items-center justify-content-between">
                  <div className="d-flex flex-row align-items-center">
                    <h2 className={headerClass}>
                      <strong className="text-secondary">{totalCountries}</strong> Countries
                    </h2>
                    { currentPage && (
                      <span className="current-page d-inline-block h-100 pl-4 text-secondary">
                        Page <span className="font-weight-bold">{ currentPage }</span> / <span className="font-weight-bold">{ totalPages }</span>
                      </span>
                    ) }
                  </div>
                  <div className="d-flex flex-row py-4 align-items-center">
                    <Pagination totalRecords={totalCountries} pageLimit={18} pageNeighbours={1} onPageChanged={this.onPageChanged} />
                  </div>
                </div>
                { currentCountries.map(country => <CountryCard key={country.cca3} country={country} />) }
              </div>
            </div>
          );
        }
      }
      

      Dans la méthode render(), vous générez le nombre total de pays, la page en cours, le nombre total de pages, le contrôle <Pagination>, puis la <CountryCard> pour chaque pays de la page en cours.

      Vous remarquerez que vous avez passé la méthode onPageChanged() que vous avez définie précédemment au prop onPageChanged du contrôle de <Pagination>. Ceci est très important pour la saisie des changements de page à partir du composant Pagination. Vous affichez également 18 pays par page.

      À ce stade, l’application ressemblera à la capture d’écran suivante :

      Capture d'écran de l'application avec 248 pays listés et les numéros de page indiqués en haut pour parcourir chaque page

      Vous avez maintenant une App qui affiche plusieurs composants CountryCard et uncomposant Pagination qui décompose le contenu en pages séparées. Ensuite, vous étudierez le style de votre application.

      Étape 5 – Ajout de styles personnalisés

      Vous avez peut-être remarqué que vous avez ajouté des classes personnalisées aux composants que vous avez créés précédemment. Définissons quelques règles de style pour ces classes dans le fichier src/App.scss.

      Le fichierApp.scss ressemblera à l’extrait suivant :

      src/App.scss

      /* Declare some variables */
      $base-color: #ced4da;
      $light-background: lighten(desaturate($base-color, 50%), 12.5%);
      
      .current-page {
        font-size: 1.5rem;
        vertical-align: middle;
      }
      
      .country-card-container {
        height: 60px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
      }
      
      .country-name {
        font-size: 0.9rem;
      }
      
      .country-region {
        font-size: 0.7rem;
      }
      
      .current-page,
      .country-name,
      .country-region {
        line-height: 1;
      }
      
      // Override some Bootstrap pagination styles
      ul.pagination {
        margin-top: 0;
        margin-bottom: 0;
        box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
      
        li.page-item.active {
          a.page-link {
            color: saturate(darken($base-color, 50%), 5%) !important;
            background-color: saturate(lighten($base-color, 7.5%), 2.5%) !important;
            border-color: $base-color !important;
          }
        }
      
        a.page-link {
          padding: 0.75rem 1rem;
          min-width: 3.5rem;
          text-align: center;
          box-shadow: none !important;
          border-color: $base-color !important;
          color: saturate(darken($base-color, 30%), 10%);
          font-weight: 900;
          font-size: 1rem;
      
          &:hover {
            background-color: $light-background;
          }
        }
      }
      

      Modifiez votre fichierApp.jspour référencer App.scss au lieu de App.css.

      Remarque : Pour plus d’informations à ce sujet, voir la documentation de l’application Create React.

      src/App.js

      import React, { Component } from 'react';
      import Countries from 'countries-api';
      import './App.scss';
      import Pagination from './components/Pagination';
      import CountryCard from './components/CountryCard';
      

      Après avoir ajouté les styles, l’application ressemblera maintenant à la capture d’écran suivante :

      Capture d'écran de l'app, page 1 sur 14, avec les styles

      Vous avez maintenant une application complète avec un style personnalisé supplémentaire. Vous pouvez utiliser des styles personnalisés pour modifier et améliorer les styles par défaut fournis par des bibliothèques comme Bootstrap.

      Conclusion

      Dans ce tutoriel, vous avez créé un widget de pagination personnalisé dans votre application React. Bien que vous n’ayez pas fait d’appel à une API ou interagi avec une base de données dans ce tutoriel, votre application peut exiger de telles interactions. Vous n’êtes en aucun cas limité à l’approche utilisée dans ce tutoriel – vous pouvez l’étendre comme vous le souhaitez pour répondre aux exigences de votre application.

      Pour obtenir le code source complet de ce tutoriel, consultez le dépôt build-react-pagination-demo sur GitHub. Vous pouvez également obtenir une démo live de ce tutoriel sur Code Sandbox.

      Si vous souhaitez en savoir plus sur React, consultez notre série Comment coder dans React.js ou consultez notre page thématique React pour des exercices et des projets de programmation.



      Source link

      Comment développer une API REST avec Prisma et PostgreSQL


      L’auteur a choisi le Diversity in Tech Fund​​​​​ pour recevoir un don dans le cadre du programme Write for DOnations.

      Introduction

      Prisma est une boîte à outils de base de données open source. Il se compose de trois outils principaux :

      • Prisma Client : un constructeur de requêtes automatisé de type sécurisé pour Node.js et TypeScript.
      • Prisma Migrate : un système déclaratif de modélisation et de migration de données.
      • Prisma Studio : une interface graphique permettant de visualiser et de modifier les données de votre base de données.

      Ces outils sont conçus pour optimiser la productivité d’un développeur d’applications dans les flux de travail de ses bases de données. L’un des principaux avantages de Prisma réside dans le niveau d’abstraction qu’il offre : Au lieu de trouver des requêtes SQL complexes ou des migrations de schéma, en utilisant Prisma, les développeurs d’applications peuvent travailler avec leur base de données en réfléchissant de manière plus intuitive sur leurs données.

      Dans ce tutoriel, vous allez créer une API REST pour une petite application de blogs dans TypeScript à l’aide de Prisma et d’une base de données PostgreSQL. Vous allez configurer votre base de données PostgreSQL localement avec Docker et implémenter des itinéraires API REST en utilisant Express. À la fin du tutoriel, vous disposerez d’un serveur web qui fonctionne localement sur votre machine, capable de répondre aux diverses demandes HTTP et de lire et écrire des données dans la base de données.

      Conditions préalables

      Ce tutoriel suppose que :

      Il vous sera utile d’avoir des connaissances de base sur les API TypeScript et REST, mais pas nécessaire pour suivre ce tutoriel.

      Étape 1 — Création de votre projet TypeScript

      Au cours de cette étape, vous allez configurer un projet TypeScript simple en utilisant npm. Ce projet constituera la base de l’API REST que vous allez développer tout au long de ce tutoriel.

      Tout d’abord, créez un nouveau répertoire pour votre projet :

      Ensuite, naviguez dans le répertoire et initialisez un projet npm vide. Notez que l’option -y signifie ici signifie que vous ignorez les invites interactives de la commande. Pour parcourir les invites, supprimez -y de la commande :

      Pour plus d’informations sur ces invites, vous pouvez suivre l’étape 1 dans Comment utiliser les modules Node.js avec npm et package.json.

      Vous obtiendrez un résultat similaire à ce qui suit, avec les réponses par défaut en place :

      Output

      Wrote to /.../my-blog/package.json: { "name": "my-blog", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

      Cette commande crée un fichier package.json minimal qui vous servira de fichier de configuration pour votre projet npm. Vous êtes maintenant prêt à configurer TypeScript dans votre projet.

      Exécutez la commande suivante pour procéder à une configuration simple de TypeScript :

      • npm install typescript ts-node @types/node --save-dev

      Vous installerez ainsi trois paquets en tant que dépendances de développement dans votre projet :

      • typescript : la chaîne d’outils TypeScript.
      • ts-node : un paquet qui exécutera les applications TypeScript sans compilation préalable à JavaScript.
      • @types/node : les définitions de type TypeScript pour Node.js.

      La dernière chose à faire consiste à ajouter un fichier tsconfig.json pour vous assurer que TypeScript est correctement configuré pour l’application que vous allez développer.

      Tout d’abord, exécutez la commande suivante pour créer le fichier :

      Ajoutez le code JSON suivant dans le fichier :

      my-blog/tsconfig.json

      {
        "compilerOptions": {
          "sourceMap": true,
          "outDir": "dist",
          "strict": true,
          "lib": ["esnext"],
          "esModuleInterop": true
        }
      }
      

      Enregistrez et quittez le fichier.

      Il s’agit d’une configuration standard et minimale pour un projet TypeScript. Si vous souhaitez en savoir plus sur les propriétés individuelles du fichier de configuration, vous pouvez les consulter dans la documentation de TypeScript.

      Vous avez configuré votre projet TypeScript simple en utilisant npm. Ensuite, vous allez configurer votre base de données PostgreSQL avec Docker et y connecter Prisma.

      Étape 2 — Configuration de Prisma avec PostgreSQL

      Au cours de cette étape, vous allez installer la CLI Prisma, créer votre fichier de schéma Prisma, configurer PostgreSQL avec Docker et y connecter Prisma. Le schéma Prisma est le fichier de configuration principal de votre configuration Prisma et contient votre schéma de base de données.

      Commencez par installer la CLI Prisma avec la commande suivante :

      • npm install @prisma/cli --save-dev

      L’une des meilleures pratiques recommande d’installer la CLI Prisma localement dans votre projet (par opposition à une installation globale). Cela permet d’éviter les conflits de versions dans le cas où vous disposeriez de plusieurs projets Prisma sur votre machine.

      Ensuite, vous allez configurer votre base de données PostgreSQL en utilisant Docker. Créez un nouveau fichier Docker Compose avec la commande suivante :

      Maintenant, ajoutez le code suivant au fichier nouvellement créé :

      my-blog/docker-compose.yml

      version: '3.8'
      services:
        postgres:
          image: postgres:10.3
          restart: always
          environment:
            - POSTGRES_USER=sammy
            - POSTGRES_PASSWORD=your_password
          volumes:
            - postgres:/var/lib/postgresql/data
          ports:
            - '5432:5432'
      volumes:
        postgres:
      

      Ce fichier Docker Compose configure une base de données PostgreSQL qui peut être consultée via le port 5432 du conteneur Docker. Notez également que les informations d’identification de la base de données actuelles sont les suivantes : sammy (utilisateur) et your_password (mot de passe). N’hésitez pas à modifier ces informations d’identification et à utiliser votre nom d’utilisateur et votre mot de passe préférés. Enregistrez et quittez le fichier.

      Une fois cette configuration en place, vous pouvez lancer le serveur de base de données PostgreSQL avec la commande suivante :

      Le résultat de cette commande sera similaire à ce qui suit :

      Output

      Pulling postgres (postgres:10.3)... 10.3: Pulling from library/postgres f2aa67a397c4: Pull complete 6de83ca23e55: Pull complete . . . Status: Downloaded newer image for postgres:10.3 Creating my-blog_postgres_1 ... done

      Vous pouvez vérifier si le serveur de base de données fonctionne avec la commande suivante :

      Vous obtiendrez un résultat similaire à celui-ci :

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8547f8e007ba postgres:10.3 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp my-blog_postgres_1

      Maintenant que le serveur de la base de données est en cours d’exécution, vous pouvez créer votre configuration Prisma. Exécutez la commande suivante depuis la CLI Prisma :

      Vous obtiendrez le résultat suivant :

      Output

      ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor.

      Notez que l’une des meilleures pratiques vous recommande de préfixer toutes les invocations de CLI Prisma avec npx. Vous aurez ainsi la certitude que votre installation locale est bien utilisée.

      Une fois la commande exécutée, la CLI Prisma aura créé un nouveau dossier appelé prisma dans votre projet. Il contient les deux fichiers suivants :

      • schema.prisma : le fichier de configuration principal de votre projet Prisma (comprendra votre modèle de données).
      • .env : un fichier dotenv qui définit l’URL de connexion de votre base de données.

      Pour veiller à ce que Prisma connaisse bien l’emplacement de votre base de données, ouvrez le fichier .env et ajustez la variable de l’environnement DATABASE_URL.

      Tout d’abord, ouvrez le fichier .env :

      Maintenant, vous pouvez configurer la variable d’environnement de la manière suivante :

      my-blog/prisma/.env

      DATABASE_URL="postgresql://sammy:your_password@localhost:5432/my-blog?schema=public"
      

      Veillez à bien remplacer les informations d’identification de la base de données par les données que vous avez spécifiées dans le fichier Docker Compose. Pour en savoir plus sur le format de l’URL de connexion, consultez les docs Prisma.

      Une fois que vous avez terminé, enregistrez et fermez le fichier.

      Au cours de cette étape, vous avez configuré votre base de données PostgreSQL avec Docker, installé la CLI Prisma et connecté Prisma à la base de données via une variable d’environnement. Lors de la section suivante, vous configurerez votre modèle de données et créerez les tableaux de votre base de données.

      Étape 3 — Configuration de votre modèle de données et création des tableaux de base de données

      Au cours de cette étape, vous allez configurer votre data model dans le fichier du schéma Prisma. Ce modèle de données sera ensuite mappé à la base de données avec Prisma Migrate, qui générera et enverra les instructions SQL pour créer les tableaux correspondant à votre modèle de données. Étant donné que vous développez une application de blog, les principales entités de l’application seront les utilisateurs et les publications.

      Prisma utilise son propre langage de modélisation des données pour définir la forme des données de votre application.

      Tout d’abord, ouvrez votre fichier schema.prisma avec la commande suivante :

      • nano prisma/schema.prisma

      Maintenant, ajoutez-y les définitions de modèles suivantes. Vous pouvez placer les modèles au bas du fichier, juste après le bloc generator client :

      my-blog/prisma/schema.prisma

      . . .
      model User {
        id    Int     @default(autoincrement()) @id
        email String  @unique
        name  String?
        posts Post[]
      }
      
      model Post {
        id        Int     @default(autoincrement()) @id
        title     String
        content   String?
        published Boolean @default(false)
        author    User?   @relation(fields: [authorId], references: tag:www.digitalocean.com,2005:/community/tutorials/how-to-build-a-rest-api-with-prisma-and-postgresql-fr)
        authorId  Int?
      }
      

      Enregistrez et quittez le fichier.

      Vous allez définir deux modèles, que vous nommerez User et Post. Chacun de ces modèles possède un certain nombre de fields qui représentent les propriétés du modèle. Les modèles seront mappés sur les tables de base de données ; les champs représentent les colonnes individuelles.

      Notez également qu’il existe une relation de un à plusieurs entre les deux modèles, spécifiés par les champs de relation posts et author sur User et Post. Cela signifie qu’un utilisateur peut être associé à plusieurs publications.

      Une fois ces modèles en place, vous pouvez maintenant créer les tableaux correspondants dans la base de données en utilisant Prisma Migrate. Sur votre terminal, exécutez la commande suivante :

      • npx prisma migrate save --experimental --create-db --name "init"

      Cette commande crée une nouvelle migration sur votre système de fichiers. Voici un aperçu rapide des trois options disponibles avec la commande :

      • --experimental : requise car Prisma Migrates indique actuellement un état experimental.
      • --create-db : permet à Prisma Migrate de créer la base de données nommée my-blog qui est spécifiée dans l’URL de connexion.
      • --name "init" : spécifie le nom de la migration (sera utilisé pour nommer le dossier de migration créé sur votre système de fichiers).

      Le résultat de cette commande sera similaire à ce qui suit :

      Output

      New datamodel: // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id Int @default(autoincrement()) @id email String @unique name String? posts Post[] } model Post { id Int @default(autoincrement()) @id title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: tag:www.digitalocean.com,2005:/community/tutorials/how-to-build-a-rest-api-with-prisma-and-postgresql-fr) authorId Int? } Prisma Migrate just created your migration 20200811140708-init in migrations/ └─ 20200811140708-init/ └─ steps.json └─ schema.prisma └─ README.md

      N’hésitez pas à explorer les fichiers de migration qui ont été créés dans le répertoire prisma/migrations.

      Pour exécuter la migration par rapport à votre base de données et créer les tableaux pour vos modèles Prisma, exécutez la commande suivante dans votre terminal :

      • npx prisma migrate up --experimental

      Vous obtiendrez le résultat suivant :

      Output

      . . . Checking the datasource for potential data loss... Database Changes: Migration Database actions Status 20200811140708-init 2 CreateTable statements. Done 🚀 You can get the detailed db changes with prisma migrate up --experimental --verbose Or read about them here: ./migrations/20200811140708-init/README.md 🚀 Done with 1 migration in 206ms.

      Prisma Migrate génère maintenant les instructions SQL nécessaires à la migration et les envoie à la base de données. Les instructions SQL qui ont créé les tableaux sont les suivantes :

      CREATE TABLE "public"."User" (
        "id" SERIAL,
        "email" text  NOT NULL ,
        "name" text   ,
        PRIMARY KEY ("id")
      )
      
      CREATE TABLE "public"."Post" (
        "id" SERIAL,
        "title" text  NOT NULL ,
        "content" text   ,
        "published" boolean  NOT NULL DEFAULT false,
        "authorId" integer   ,
        PRIMARY KEY ("id")
      )
      
      CREATE UNIQUE INDEX "User.email" ON "public"."User"("email")
      
      ALTER TABLE "public"."Post" ADD FOREIGN KEY ("authorId")REFERENCES "public"."User"("id") ON DELETE SET NULL ON UPDATE CASCADE
      

      Au cours de cette étape, vous avez défini votre modèle de données dans votre schéma Prisma et créé les tableaux des bases de données correspondants avec Prisma Migrate. À l’étape suivante, vous allez installer Prisma Client dans votre projet afin de pouvoir interroger la base de données.

      Étape 4 — Exploration des requêtes Prisma Client dans un script simple

      Prisma Client est un constructeur de requêtes automatisé de type sécurisé qui vous permet de lire et d’écrire des données dans une base de données depuis une application Node.js ou TypeScript. Vous l’utiliserez pour accéder à la base de données dans vos itinéraires API REST, en remplaçant les ORM traditionnelles, les requêtes SQL simples, les couches d’accès aux données personnalisées ou toute autre méthode d’échange avec une base de données.

      Au cours de cette étape, vous allez installer Prisma Client et vous familiariser avec les requêtes que vous pouvez envoyer. Avant d’implémenter les itinéraires de votre API REST au cours des prochaines étapes, vous allez tout d’abord explorer certaines des requêtes Prisma Client dans un script exécutable simple.

      Premièrement, vous pouvez procéder à l’installation de Prisma Client dans votre projet en ouvrant votre terminal et en installant le paquet npm de Prisma Client :

      • npm install @prisma/client

      Ensuite, créez un nouveau répertoire que vous nommerez src. Il contiendra vos fichiers sources :

      Créez maintenant un fichier TypeScript à l’intérieur du nouveau répertoire :

      Toutes les requêtes de Prisma Client renvoient les promesses auxquelles vous pouvez vous attendre dans votre code. Vous devez donc envoyer les requêtes à l’intérieur d’une fonction async.

      Ajoutez le texte standard suivant avec une fonction async qui s’exécutera dans votre script :

      my-blog/src/index.ts

      import { PrismaClient } from '@prisma/client'
      
      const prisma = new PrismaClient()
      
      async function main() {
        // ... your Prisma Client queries will go here
      }
      
      main()
        .catch((e) => console.error(e))
        .finally(async () => await prisma.disconnect())
      

      Voici une rapide décomposition du texte standard :

      1. Importez le constructeur PrismaClient depuis le paquet @prisma/client npm déjà installé.
      2. Instanciez PrismaClient en appelant le constructeur et en obtenant une instance appelée prisma.
      3. Définissez une fonction async que vous appellerez main dans laquelle vous allez ensuite ajouter vos requêtes Prisma Client.
      4. Appelez la fonction main, tout en détectant toute exception potentielle et en vous assurant que Prisma Client ferme toutes les connexions à la base de données ouvertes, en appelant prisma.disconnect().

      Une fois la fonction main en place, vous pouvez commencer à ajouter les requêtes Prisma Client au script. Ajustez index.ts pour que cela ressemble à ce qui suit :

      my-blog/src/index.ts

      import { PrismaClient } from '@prisma/client'
      
      const prisma = new PrismaClient()
      
      async function main() {
        const newUser = await prisma.user.create({
          data: {
            name: 'Alice',
            email: '[email protected]',
            posts: {
              create: {
                title: 'Hello World',
              },
            },
          },
        })
        console.log('Created new user: ', newUser)
      
        const allUsers = await prisma.user.findMany({
          include: { posts: true },
        })
        console.log('All users: ')
        console.dir(allUsers, { depth: null })
      }
      
      main()
        .catch((e) => console.error(e))
        .finally(async () => await prisma.disconnect())
      

      Dans ce code, vous utilisez deux requêtes Prisma Client :

      • create : crée un nouvel enregistrement User. Notez que, en réalité, vous utilisez une écriture imbriquée, ce qui signifie que vous créez à la fois un enregistrement User et un enregistrement Post dans la même requête.
      • findMany : lit tous les enregistrements User existants depuis la base de données. Vous fournissez l’option include qui charge également les enregistrements de Post correspondants pour chaque enregistrement User.

      Maintenant, exécutez le script avec la commande suivante :

      Vous obtiendrez le résultat suivant dans votre terminal :

      Output

      Created new user: { id: 1, email: '[email protected]', name: 'Alice' } [ { id: 1, email: '[email protected]', name: 'Alice', posts: [ { id: 1, title: 'Hello World', content: null, published: false, authorId: 1 } ] }

      Remarque : si vous utilisez une interface graphique de base de données, vous pouvez valider si les données ont bien été créées en examinant les tableaux User et Post. Vous pouvez également explorer les données dans Prisma Studio en exécutant npx prisma studio --experimental.

      Vous avez maintenant utilisé Prisma Client pour lire et écrire des données dans votre base de données. Au cours des étapes restantes, vous allez appliquer ces nouvelles connaissances pour implémenter les itinéraires dans une API REST échantillon.

      Étape 5 — Implémentation de votre premier itinéraire API REST

      Au cours de cette étape, vous allez installer Express dans votre application. Express est un framework web populaire pour Node.js que vous utiliserez pour implémenter vos itinéraires API REST dans ce projet. Le premier itinéraire que vous allez implémenter vous permettra de récupérer tous les utilisateurs de l’API en utilisant une requête GET. Les données utilisateur seront récupérées depuis la base de données en utilisant Prisma Client.

      Vous pouvez maintenant installer Express avec la commande suivante :

      Étant donné que vous utilisez TypeScript, vous devez également installer les types correspondants en tant que dépendances de développement. Pour cela, exécutez la commande suivante :

      • npm install @types/express --save-dev

      Une fois les dépendances installée, vous pouvez configurer votre application Express.

      Commencez par rouvrir votre fichier source principal :

      Maintenant, supprimez l’intégralité du code dans index.ts et remplacez-le par ce qui suit pour lancer votre API REST :

      my-blog/src/index.ts

      import { PrismaClient } from '@prisma/client'
      import express from 'express'
      
      const prisma = new PrismaClient()
      const app = express()
      
      app.use(express.json())
      
      // ... your REST API routes will go here
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Voici une décomposition rapide du code :

      1. Importez PrismaClient et express à partir des paquets npm correspondants.
      2. Instanciez PrismaClient en appelant le constructeur et en obtenant une instance appelée prisma.
      3. Créez votre application Express en appelant express().
      4. Ajoutez le logiciel médiateur express.json() pour avoir la certitude que les données de JSON soient correctement traitées par Express.
      5. Lancez le serveur sur le port 3000.

      Maintenant, vous pouvez implémenter votre premier itinéraire. Entre les appels à app.use et app.listen, ajoutez le code suivant :

      my-blog/src/index.ts

      . . .
      app.use(express.json())
      
      app.get('/users', async (req, res) => {
        const users = await prisma.user.findMany()
        res.json(users)
      })
      
      app.listen(3000, () =>
      console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Une fois ajouté, enregistrez et fermez votre fichier. Ensuite, démarrez votre serveur web local en utilisant la commande suivante :

      Vous recevrez le résultat suivant :

      Output

      REST API server ready at: http://localhost:3000

      Pour accéder à l’itinéraire /users, vous pouvez pointer votre navigateur vers http://localhost:3000/users ou tout autre client HTTP.

      Dans ce tutoriel, vous allez tester tous les itinéraire API REST en utilisant curl, un client HTTP basé sur le terminal.

      Note : si vous préférez utiliser un client HTTP basé sur une interface graphique, vous pouvez utiliser des alternatives comme Postwoman ou le Advanced REST Client.

      Pour tester votre itinéraire, ouvrez une nouvelle fenêtre ou un nouveal onglet du terminal (afin que votre serveur web local puisse continuer à fonctionner) et exécutez la commande suivante :

      • curl http://localhost:3000/users

      Vous obtiendrez les données User que vous avez créées au cours de l’étape précédente : 

      Output

      [{"id":1,"email":"[email protected]","name":"Alice"}]

      Notez que, cette fois, le tableau posts n’est pas inclus, étant donné que vous ne faites pas passer l’option include à l’appel findMany dans l’implémentation de l’itinéraire /users.

      Vous avez implémenté votre premier itinéraire API REST au niveau de /users. Au cours de l’étape suivante, vous allez implémenter les autres itinéraires API REST pour ajouter plus de fonctionnalités à votre API.

      Étape 6 — Implémentation des itinéraires API REST restants

      Au cours de cette étape, vous allez implémenter les autres itinéraires API REST de votre application de blog. À la fin, votre serveur web servira diverses requêtes GET, POST, PUT et DELETE.

      Voici un aperçu des différents itinéraires que vous allez implémenter :

      Méthode HTTPItinéraireDescription
      GET/feedRécupère toutes les publications published.
      GET/post/:idRécupère une publication spécifique en utilisant son ID.
      POST/userCrée un nouvel utilisateur.
      POST/postCrée une nouvelle publication (en tant que draft).
      PUT/post/publish/:idDéfinit le champ published d’une publication comme true.
      DELETEpost/:idSupprime une publication en utilisant son ID.

      Vous pouvez maintenant implémenter le reste des itinéraires Get en premier.

      Ouvrez la commande index.ts avec la commande suivante :

      Ensuite, ajoutez le code suivant une fois l’itinéraire /users  implémenté :

      my-blog/src/index.ts

      . . .
      
      app.get('/feed', async (req, res) => {
        const posts = await prisma.post.findMany({
          where: { published: true },
          include: { author: true }
        })
        res.json(posts)
      })
      
      app.get(`/post/:id`, async (req, res) => {
        const { id } = req.params
        const post = await prisma.post.findOne({
          where: { id: Number(id) },
        })
        res.json(post)
      })
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Enregistrez et fermez votre fichier

      Ce code implémente les itinéraires API pour deux requêtes GET :

      • /feed : renvoie une liste des posts publiés.
      • /post/:id : renvoie un post spécifique en utilisant son ID.

      Prisma Client est utilisé dans les deux implémentations. Dans l’implémentation de l’itinéraire /feed, la requête que vous envoyez avec Prisma Client filtre pour tous les enregistrements Post pour lesquels la colonne published indique la valeur true. En outre, la requête Prisma Client utilise include pour récupérer les informations liées à l’author pour chaque publication renvoyée. Dans l’implémentation de l’itinéraire /post/:id, faites passer l’ID récupérée depuis le chemin de l’URL afin de lire un enregistrement Post spécifique depuis la base de données.

      Vous pouvez arrêter le serveur en utilisant les touches CTRL+C de votre clavier. Ensuite, redémarrez le serveur en utilisant :

      Pour tester l’itinéraire /feed, vous pouvez utiliser la commande curl suivante :

      • curl http://localhost:3000/feed

      Étant donné qu’aucune publication n’a encore été publiée, la réponse prendra la forme d’un tableau vide :

      Output

      []

      Pour tester l’itinéraire /post/:id, vous pouvez utiliser la commande curl suivante :

      • curl http://localhost:3000/post/1

      Vous obtiendrez la publication que vous avez créée initialement :

      Output

      {"id":1,"title":"Hello World","content":null,"published":false,"authorId":1}

      Ensuite, implémentez les deux itinéraires POST. Ajoutez le code suivant à index.ts après les trois itinéraires GET :

      my-blog/src/index.ts

      . . .
      
      app.post(`/user`, async (req, res) => {
        const result = await prisma.user.create({
          data: { ...req.body },
        })
        res.json(result)
      })
      
      app.post(`/post`, async (req, res) => {
        const { title, content, authorEmail } = req.body
        const result = await prisma.post.create({
          data: {
            title,
            content,
            published: false,
            author: { connect: { email: authorEmail } },
          },
        })
        res.json(result)
      })
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Une fois que vous avez terminé, enregistrez et fermez le fichier.

      Ce code implémente les itinéraires API pour deux requêtes POST :

      • /user : crée un nouvel utilisateur dans la base de données.
      • /post : crée une nouvelle publication dans la base de données.

      Comme auparavant, Prisma Client est utilisé dans les deux implémentations. Dans le cadre de l’implémentation de l’itinéraire /user, vous faites passer les valeurs depuis le corps de la requête HTTP à la requête create de Prisma Client.

      L’itinéraire /post exige un peu plus d’implication. Ici, vous ne pouvez pas faire passer les valeurs directement depuis le corps de la requête HTTP. Au contraire, vous devez d’abord les extraire manuellement afin de les transmettre à la requête Prisma Client. En effet, étant donné que la structure de JSON dans le corps de requête ne correspond pas à la structure attendue par Prisma Client. Vous devez donc créer la structure attendue manuellement.

      Vous pouvez tester les nouveaux itinéraires en arrêtant le serveur avec CTRL+C. Ensuite, redémarrez le serveur en utilisant :

      Pour créer un nouvel utilisateur via l’itinéraire /user, vous pouvez envoyer la requête POST suivante avec curl :

      • curl -X POST -H "Content-Type: application/json" -d '{"name":"Bob", "email":"[email protected]"}' http://localhost:3000/user

      Cela créera un nouvel utilisateur dans la base de données, en donnant le résultat suivant :

      Output

      {"id":2,"email":"[email protected]","name":"Bob"}

      Pour créer une nouvelle publication via l’itinéraire /post, vous pouvez envoyer la requête POST suivante avec curl :

      • curl -X POST -H "Content-Type: application/json" -d '{"title":"I am Bob", "authorEmail":"[email protected]"}' http://localhost:3000/post

      Cela créera une nouvelle publication dans la base de données et la connectera à l’utilisateur avec le courriel [email protected]. Cela donne le résultat suivant :

      Output

      {"id":2,"title":"I am Bob","content":null,"published":false,"authorId":2}

      Enfin, vous pouvez implémenter les itinéraires PUT et DELETE.

      Ouvrez la commande index.ts avec la commande suivante :

      Ensuite, une fois les deux itinéraires POST implémentés, ajoutez le code surligné :

      my-blog/src/index.ts

      . . .
      
      app.put('/post/publish/:id', async (req, res) => {
        const { id } = req.params
        const post = await prisma.post.update({
          where: { id: Number(id) },
          data: { published: true },
        })
        res.json(post)
      })
      
      app.delete(`/post/:id`, async (req, res) => {
        const { id } = req.params
        const post = await prisma.post.delete({
          where: { id: Number(id) },
        })
        res.json(post)
      })
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Enregistrez et fermez votre fichier

      Ce code implémente les itinéraires API pour une requête PUT et une requête DELETE :

      • /post/publish/:id (PUT) : publie une publication en utilisant son ID.
      • /post/:id (DELETE) : supprime une publication en utilisant son ID.

      À nouveau, Prisma Client est utilisé dans les deux implémentations. Dans le cadre de l’implémentation de l’itinéraire /post/publish/:id, l’ID du message à publier est récupéré depuis l’URL et transmis à la requête update de Prisma Client. L’implémentation de l’itinéraire /post/:id qui permet de supprimer une publication dans la base de données renvoie également l’ID de l’URL et le transmet à la requête delete de Prisma Client.

      Encore une fois, arrêtez le serveur à l’aide des touches CTRL+C de votre clavier. Ensuite, redémarrez le serveur en utilisant :

      Vous pouvez tester l’itinéraire PUT avec la commande curl suivante :

      • curl -X PUT http://localhost:3000/post/publish/2

      Cela vous permettra de publier la publication avec une valeur d’ID de 2. Si vous renvoyez la requête /feed, cette publication sera alors incluse dans la réponse.

      Enfin, vous pouvez tester l’itinéraire DELETE avec la commande curl suivante :

      • curl -X DELETE http://localhost:3000/post/1

      Cela vous permettra de supprimer la publication avec une valeur d’ID de 1. Pour valider le fait que la publication portant cet ID ait été supprimée, vous pouvez renvoyer une requête GET à l’itinéraire /post/1.

      Au cours de cette étape, vous avez implémenté les autres itinéraires API REST de votre application de blog. L’API répond maintenant aux diverses requêtes GET, POST, PUT et DELETE et implémente une fonctionnalité pour lire et écrire des données dans la base de données.

      Conclusion

      Au cours de cet article, vous avez créé un serveur API REST avec plusieurs itinéraires différents pour créer, lire, mettre à jour et supprimer les données utilisateur et de publications pour une application de blog échantillon. À l’intérieur des itinéraires de l’API, vous utilisez le Prisma Client pour envoyer les requêtes correspondantes à votre base de données.

      Ensuite, vous pouvez implémenter des itinéraires API supplémentaires ou étendre le schéma de votre base de données en utilisant Prisma Migrate. Veillez à consulter la documentation de Prisma pour en savoir plus sur les divers aspects de Prisma et à explorer quelques exemples de projets prêts à l’exécution dans le référentiel prisma-examples – en utilisant des outils comme les API GraphQL ou grPC.



      Source link

      Comment installer une pile ERPNext sur Ubuntu 18.04


      L’auteur a choisi Software in the Public Interest pour recevoir un don dans le cadre du programme Write for DOnations.

      Introduction

      ERPNext est une suite de planification des ressources d’entreprise (ERP) qui tire parti de la puissance et de la flexibilité des technologies open-source. Elle excelle dans la gestion des processus opérationnels de base tels que la finance, les ventes, les ressources humaines, la fabrication, les achats, les services, les besoins du helpdesk, et plus encore. Parmi les avantages de la mise en œuvre d’un système comme ERPNext, on peut citer :

      • Une meilleure productivité en automatisant les processus commerciaux répétitifs
      • Une amélioration de l’efficacité informatique en partageant une base de données pour tous les départements de la société
      • Une meilleure prise de décisions grâce à une vision intégrale de la relation entre les unités commerciales

      ERPNext repose sur Frappe, un cadre d’application web full-stack écrit en Python qui tire pleinement parti de l’environnement d’exécution Node/JavaScript et utilise MariaDB comme backend de base de données. L’un des nombreux avantages des applications reposant sur Frappe, comme ERPNext, est l’utilitaire de ligne de commande bench. L’ILC bench permet aux administrateurs de gagner du temps en automatisant des tâches telles que l’installation, la mise à jour, la configuration et la gestion de plusieurs sites Frappe/ERPNext.

      Dans ce tutoriel, vous installerez et configurez une pile ERPNext sur un serveur tournant sous Ubuntu 18.04. Cela vous permettra de configurer votre pile pour divers environnements de développement ou de production en fonction de vos besoins, et cela vous préparera à construire une architecture plus complexe et tolérante aux défauts.

      Conditions préalables

      Note : Lorsque vous choisissez les spécifications de votre serveur, n’oubliez pas que les systèmes ERP sont gourmands en ressources. Ce guide préconise un serveur de 4 Go de RAM, ce qui est suffisant pour les cas d’utilisation de base, mais les exigences matérielles spécifiques peuvent varier en fonction du nombre d’utilisateurs et de la taille de votre entreprise.

      • Un nom de domaine entièrement enregistré avec un enregistrement A pointant vers votre serveur. Si vous utilisez un droplet DigitalOcean, vous pouvez suivre ce guide pour configurer correctement votre DNS. Ce tutoriel utilisera your_domain.

      Étape 1 — Configuration du pare-feu

      Bien que la configuration d’un pare-feu pour le développement soit facultative, pour la production il s’agit d’une pratique de sécurité obligatoire.

      Vous devrez ouvrir les ports suivants sur votre serveur ERPNext :

      • 80/tcp et 443/tcp pour HTTP et HTTPS, respectivement
      • 3306/tcp pour la connexion à MariaDB (recommandé uniquement si vous avez besoin d’un accès à la base de données à distance)
      • 143/tcp et 25/tcp pour IMAP et STMP, respectivement
      • 22/tcp pour SSH (si vous n’avez pas encore activé OpenSSH)
      • 8000/tcp pour les tests de développement avant de déployer votre site

      Pour ouvrir plusieurs ports à la fois, vous pouvez utiliser la commande suivante :

      • sudo ufw allow 22,25,143,80,443,3306,8000/tcp

      Vous pouvez également autoriser des connexions à partir d’adresses IP spécifiques sur des ports spécifiques en utilisant cette commande :

      • sudo ufw allow from server_IP to any port port_number

      Après avoir ouvert tous les ports nécessaires, activez le pare-feu :

      Après avoir activé le pare-feu, confirmez l’état de vos ports ouverts :

      Pour plus d’informations concernant la configuration du pare-feu, veuillez lire notre guide Comment configurer un pare-feu avec UFW sur Ubuntu 18.04.

      La mise en place d’un pare-feu approprié est la première des deux étapes préliminaires. Vous allez maintenant configurer le mappage du clavier et l’encodage des caractères sur votre serveur.

      Étape 2 — Configuration des sites

      Il est fortement recommandé de configurer le mappage du clavier pour la console ainsi que la langue et l’encodage des caractères sur votre hôte. Ceci est nécessaire pour éviter les problèmes éventuels lors du processus d’installation d’ERPNext 12. Remarquez que cette configuration n’a rien à voir avec la langue de l’interface utilisateur sur votre plateforme ERPNext actuelle, mais avec la configuration locale du système.

      Tout d’abord, mettez à jour votre serveur :

      Configurez maintenant le keymap, la langue et l’encodage des caractères :

      • sudo localectl set-keymap us && sudo localectl set-locale LANG=en_US.utf8

      L’utilitaire localectl est utilisé par Ubuntu 18.04 et d’autres distributions Linux pour contrôler et modifier les paramètres locaux et la disposition du clavier à l’échelle du système, avant que l’utilisateur ne se connecte, ce qui est exactement ce dont ERPNext 12 a besoin.

      Vous devrez également ajouter les lignes suivantes à votre fichier /etc/environment. Utilisez nano ou votre éditeur de texte préféré pour ouvrir le fichier :

      • sudo nano /etc/environment

      Maintenant ajoutez le contenu suivant :

      /etc/environment

      LC_ALL=en_US.UTF-8
      LC_CTYPE=en_US.UTF-8
      LANG=en_US.UTF-8
      

      Enregistrez et fermez le fichier.

      Redémarrez votre serveur pour appliquer tous les changements :

      Patientez quelques minutes pendant que votre serveur redémarre, puis réintégrez le ssh. Vous êtes maintenant prêt à installer votre base de données.

      Étape 3 — Installation de MariaDB 10.4

      Vous allez maintenant ajouter MariaDB à la pile de votre serveur. ERPNext 12 requiert MariaDB 10.2+, mais la version incluse dans le dépôt officiel d’Ubuntu 18.04 est 10.1, ce qui signifie que vous devrez installer une version supérieure. Pour les besoins de ce guide, vous utiliserez la dernière version stable de MariaDB, qui, au moment de la rédaction de ce document, est la version 10.4.

      Pour installer MariaDB 10.4 sur Ubuntu 18.04, vous devrez ajouter la clé de signature et le dépôt appropriés. Vous pouvez trouver ces informations sur l’assistant de dépôt de la Fondation MariaDB. Pour visualiser la page, collez cette URL dans votre navigateur web. Maintenant, sous 1. Choose a Distro, cliquez sur Ubuntu. Une deuxième colonne intitulée 2. Choose a Release (Choisir une version) apparaîtra. Sous ce titre, cliquez sur 18.04 LTS “bionic”. Une troisième colonne intitulée 3.Choose a Version apparaîtra alors. Sous ce titre, cliquez sur 10.4 stable. Une quatrième colonne intitulée 4.Choose a Mirror apparaîtra alors. Choisissez un miroir en fonction de votre emplacement, puis MariaDB remplira les commandes appropriées pour votre installation personnalisée.

      Assistant de dépôt MariaDB

      Exécutez les trois commandes remplies, ce qui ajoutera correctement le dépôt et la clé MariaDB. Vos propres commandes ressembleront à ceci :

      • sudo apt-get install software-properties-common && sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc' && sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] http://mirror.klaus-uwe.me/mariadb/repo/10.4/ubuntu bionic main'

      Une fois que vous avez fini d’ajouter le référentiel, installez MariaDB :

      • sudo apt install mariadb-server

      Après avoir installé mariadb-server, installez les packages suivants :

      • sudo apt install libmysqlclient-dev python3-mysqldb

      ERPNext 12 est une application Python et nécessite donc la bibliothèque python3-mysqldb pour la gestion de la base de données. Concernant libmysqlclient-dev, mariadb-client, et libmariadbclient18 : ces paquets permettent aux utilisateurs de communiquer avec le service MariaDB. ntpdate et libdate-manip-perl sont utilisés par ERPNext pour la synchronisation horaire du serveur.

      Ensuite, ajoutez une couche de sécurité basique supplémentaire au serveur MariaDB en exécutant le script mysql_secure_installation :

      • sudo mysql_secure_installation

      Le script mysql_secure_installation vous posera plusieurs questions :

      • La première invite vous demandera le mot de passe root, mais comme aucun de mot de passe n’a été configuré, appuyez sur ENTER.
      • Ensuite, vous devrez décider d’utiliser ou non l’authentification Unix. Répondez Y pour accepter cette méthode d’authentification.
      • Lorsqu’il vous sera demandé de modifier le mot de passe root de MariaDB, répondez N. L’utilisation du mot de passe par défaut avec l’authentification Unix est la configuration recommandée pour les systèmes basés sur Ubuntu, car le compte root est étroitement lié aux tâches de maintenance automatisées du système.
      • Les questions restantes concernent la suppression de l’utilisateur anonyme de la base de données, la restriction du compte root pour vous connecter à distance sur localhost, la suppression de la base de données de test et le rechargement des tables de privilèges. Vous pouvez répondre Y à toutes ces questions en toute sécurité.

      Après avoir terminé le script mysql_secure_installation, MariaDB commencera à fonctionner en utilisant sa configuration par défaut. L’installation standard ERPNext utilise le root user de MariaDB, pour toutes les opérations de la base de données. Bien que cette approche soit pratique sur les configurations de serveur unique, elle n’est pas considérée comme une bonne pratique en matière de sécurité. Par conséquent, dans la section suivante, vous apprendrez à éviter ce problème en créant un nouvel utilisateur avec des privilèges spéciaux.

      Création d’un Super utilisateur admin de MariaDB

      ERPNext prévoit d’utiliser le root user de MariaDB pour gérer les connexions aux bases de données, mais ce n’est pas toujours idéal. Pour contourner cette limitation et laisser un utilisateur non-root gérer MariaDB, vous allez maintenant créer manuellement une base de données portant le nom de l’utilisateur. Ensuite, vous serez en mesure d’attribuer des privilèges spéciaux au nouvel utilisateur pour conduire les opérations de la base de données d’ERPNext.

      Ouvrez l’invite MariaDB :

      Créez maintenant une nouvelle base de données nommée d’après l’utilisateur que vous souhaitez affecter aux connexions MariaDB. Ce tutoriel utilisera sammy mais vous êtes libre de choisir votre propre nom :

      Confirmez que la base de données a été créée en utilisant cette instruction SQL :

      Vous obtiendrez une sortie semblable à ceci :

      Output

      +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sammy | +--------------------+

      Créez maintenant l’utilisateur MariaDB sammy avec des privilèges similaires à root, puis donnez à l’utilisateur le mot de passe fort de votre choix. Conservez le mot de passe dans un endroit sûr, vous en aurez besoin plus tard :

      • GRANT ALL PRIVILEGES ON *.* TO 'sammy'@'%' IDENTIFIED BY 'mariadb_password' WITH GRANT OPTION;

      Confirmez maintenant la création de l’utilisateur et les privilèges du nouvel utilisateur :

      • SELECT host, user, Super_priv FROM mysql.user;

      Vous verrez un résultat similaire à ce qui suit :

      Output

      +-----------+-------+------------+ | Host | User | Super_priv | +-----------+-------+------------+ | localhost | root | Y | | localhost | mysql | Y | | % | sammy | Y | +-----------+-------+------------+ 3 rows in set (0.001 sec)

      Maintenant videz les privilèges pour appliquer tous les changements :

      Une fois que vous avez terminé, quittez la session :

      Maintenant que vous avez créé un utilisateur de la base de données, il ne vous reste plus qu’à régler MariaDB pour vous assurer le fonctionnement correct d’ERPNext 12. Heureusement, l’équipe ERPNext fournit un excellent modèle de configuration que vous utiliserez comme point de départ pour votre implémentation. Dans la section suivante, vous apprendrez à configurer correctement la base de données MariaDB en utilisant ce modèle.

      Étape 4 — Configuration de MariaDB pour ERPNext

      Une fois MariaDB installé et sécurisé, il est temps de le mettre au point pour les connexions ERPNext.

      Tout d’abord, arrêtez mariadb.service :

      • sudo systemctl stop mariadb

      Utilisez maintenant nano ou votre éditeur de texte préféré pour créer un fichier de configuration MariaDB appelé settings.cnf :

      • sudo nano /etc/mysql/conf.d/settings.cnf

      Ajoutez maintenant le modèle de configuration d’ERPNext :

      /etc/mysql/conf.d/settings.cnf

      [mysqld]
      
      # GENERAL #
      user                           = mysql
      default-storage-engine         = InnoDB
      socket                         = /var/lib/mysql/mysql.sock
      pid-file                       = /var/lib/mysql/mysql.pid
      
      # MyISAM #
      key-buffer-size                = 32M
      myisam-recover                 = FORCE,BACKUP
      
      # SAFETY #
      max-allowed-packet             = 256M
      max-connect-errors             = 1000000
      innodb                         = FORCE
      
      # DATA STORAGE #
      datadir                        = /var/lib/mysql/
      
      # BINARY LOGGING #
      log-bin                        = /var/lib/mysql/mysql-bin
      expire-logs-days               = 14
      sync-binlog                    = 1
      
      # REPLICATION #
      server-id                      = 1
      
      # CACHES AND LIMITS #
      tmp-table-size                 = 32M
      max-heap-table-size            = 32M
      query-cache-type               = 0
      query-cache-size               = 0
      max-connections                = 500
      thread-cache-size              = 50
      open-files-limit               = 65535
      table-definition-cache         = 4096
      table-open-cache               = 10240
      
      # INNODB #
      innodb-flush-method            = O_DIRECT
      innodb-log-files-in-group      = 2
      innodb-log-file-size           = 512M
      innodb-flush-log-at-trx-commit = 1
      innodb-file-per-table          = 1
      innodb-buffer-pool-size        = 5462M
      innodb-file-format             = barracuda
      innodb-large-prefix            = 1
      collation-server               = utf8mb4_unicode_ci
      character-set-server           = utf8mb4
      character-set-client-handshake = FALSE
      max_allowed_packet             = 256M
      
      # LOGGING #
      log-error                      = /var/lib/mysql/mysql-error.log
      log-queries-not-using-indexes  = 0
      slow-query-log                 = 1
      slow-query-log-file            = /var/lib/mysql/mysql-slow.log
      
      [mysql]
      default-character-set = utf8mb4
      
      [mysqldump]
      max_allowed_packet=256M
      
      !includedir /etc/mysql/mariadb.conf.d/
      

      Enregistrez et fermez le fichier. Pour obtenir des informations plus détaillées sur ces configurations, consultez ce fichier modèle sur le référentiel Github d’ERPNext. C’est un point de départ utile pour explorer ces options.

      Ensuite, créez un autre fichier appelé erpnext.cnf :

      • sudo nano /etc/mysql/mariadb.conf.d/erpnext.cnf

      Ajoutez le contenu suivant au fichier :

      /etc/mysql/mariadb.conf.d/erpnext.cnf

      [mysqld]
      pid-file        = /var/run/mysqld/mysqld.pid
      socket          = /var/run/mysqld/mysqld.sock
      bind-address    = 0.0.0.0
      

      Le premier fichier,/etc/mysql/conf.d/settings.cnf, complète et remplace également quelques valeurs incluses dans la configuration par défaut de MariaDB située dans /etc/mysql/my.cnf. Ce fichier vous donne un modèle de conservation qui améliore considérablement les performances de la base de données pour ERPNext. N’oubliez pas toutefois que si ce modèle est un excellent point de départ, rien ne vous empêche d’améliorer encore plus les performances de MariaDB en ajustant ces paramètres à vos besoins.

      Le deuxième fichier, /etc/mysql/mariadb.conf.d/erpnext.cnf, permet également de remplacer certaines valeurs par des informations spécifiques concernant la connexion à votre base de données.

      Test de la connexion MariaDB

      Comme ERPNext dépend de la connexion à la base de données pour presque toutes ses opérations internes, il est bon de tester la connexion avant de continuer.

      Démarrez mariadb.service :

      • sudo systemctl start mariadb

      Pour tester la connexion, vous pouvez utiliser la commande suivante. N’oubliez pas de remplacer sammy et mariadb_password par vos propres identifiants :

      • mysql --user sammy --password mariadb_password --host=localhost --protocol=tcp --port=3306 test

      Vous verrez un résultat montrant le contenu de l’aide de base de MariaDB et plusieurs paramètres. Cela signifie que votre connexion a réussi :

      Output

      mysql Ver 15.1 Distrib 10.4.13-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2 Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Usage: mysql [OPTIONS] [database] Default options are read from the following files in the given order: /etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf ... --ssl-verify-server-cert Verify server's "Common Name" in its cert against hostname used when connecting. This option is disabled by default. -t, --table Output in table format. --tee=name Append everything into outfile. See interactive help (h) also. Does not work in batch mode. Disable with --disable-tee. This option is disabled by default. -u, --user=name User for login if not current user. -U, --safe-updates Only allow UPDATE and DELETE that uses keys. -U, --i-am-a-dummy Synonym for option --safe-updates, -U. -v, --verbose Write more. (-v -v -v gives the table output format). ... max-join-size 1000000 secure-auth FALSE show-warnings FALSE plugin-dir (No default value) default-auth (No default value) binary-mode FALSE connect-expired-password FALSE

      Si vous devez apporter des ajustements aux paramètres de MariaDB ou corriger des erreurs, n’oubliez pas de recharger le service en utilisant la commande suivante :

      • sudo systemctl restart mariadb

      Une fois que vous avez terminé, activez MariaDB :

      • sudo systemctl enable mariadb

      Maintenant que vous avez testé la connexion à la base de données, vous pouvez continuer à installer votre application ERPNext.

      Étape 5 — Configuration ERPNext 12

      Maintenant que le backend de votre base de données est prêt, vous pouvez continuer à configurer votre application web ERPNext. Dans cette section, vous apprendrez à installer et configurer tous les composants requis par ERPNext 12, puis à installer l’application elle-même.

      Commencez par préparer le serveur avec tous les paquets système requis par ERPNext 12. Installez les dépendances dans tout le système en utilisant la commande suivante :

      • sudo DEBIAN_FRONTEND=noninteractive apt install -y curl build-essential mariadb-client python3-setuptools python3-dev libffi-dev python3-pip libcurl4 dnsmasq fontconfig git htop libcrypto++-dev libfreetype6-dev liblcms2-dev libwebp-dev libxext6 libxrender1 libxslt1-dev libxslt1.1 libffi-dev ntpdate postfix python3-dev python-tk screen vim xfonts-75dpi xfonts-base zlib1g-dev apt-transport-https libsasl2-dev libldap2-dev libcups2-dev pv libjpeg8-dev libtiff5-dev tcl8.6-dev tk8.6-dev libssl1.0-dev python3-mysqldb libdate-manip-perl logwatch

      La variable DEBIAN_FRONTEND=noninteractive a été transmise à la commande d’installation afin d’éviter les invites Postfix. Pour obtenir des informations détaillées sur la configuration de Postfix, lisez notre guide Comment installer et configurer Postfix sur Ubuntu 18.04

      Ensuite, mettez à jour pip3 et installez les dernières versions de trois modules Python supplémentaires requis par ERPNext :

      • sudo -H python3 -m pip install --upgrade setuptools cryptography psutil

      Maintenant que vous avez installé toutes les dépendances générales nécessaires, vous allez installer tous les services et les bibliothèques nécessaires à ERPNext 12.

      Configuration de Node.js et Yarn

      ERPNext 12 peut fonctionner avec la version 8+ de l’environnement serveur Node.js. En réalité, au moment de la rédaction de ce texte, le script officiel easy_install d’ERPNext utilise Node 8. Mais du point de vue de la sécurité, il est conseillé d’installer une version plus récente, car Node 8 a atteint sa fin de vie (EOL) en 2020 et ne bénéficiera donc plus de correctifs de sécurité. Pour les besoins de ce guide, la version 12 LTS de Node.js sera installée en même temps que les gestionnaires de paquets npm et yarn correspondants. Veuillez noter que le framework Frappe utilise yarn pour installer les dépendances. Si vous décidez d’utiliser une autre méthode d’installation, vérifiez que la version 1.12+ de yarn fonctionne sur votre système.

      Ajoutez le référentiel NodeSource à votre système :

      • curl -sL https://deb.nodesource.com/setup_12.x -o nodesource_setup.sh

      Vous pouvez maintenant inspecter le contenu du script téléchargé :

      • sudo nano nodesurce_setup.sh

      Une fois que vous êtes satisfait, vous pouvez exécuter le script :

      • sudo bash nodesource_setup.sh

      Ce script mettra à jour automatiquement la liste apt. Vous pouvez maintenant installer nodejs sur votre serveur :

      Ensuite, installez yarn globalement en utilisant le paquet npm inclus :

      Maintenant que vous avez installé Node, vous pouvez continuer à configurer wkhtmltopdf pour votre plate-forme.

      ERPNext utilise l’outil open source wkhtmltopdf pour convertir le contenu HTML en PDF, en utilisant le moteur de rendu Qt WebKit. Cette fonction est principalement utilisée pour l’impression de factures, de devis et d’autres rapports. Dans le cas d’ERPNext 12, une version spécifique de wkhtmltopdf est requise, 0.12.5 avec Qt patché.

      Pour installer wkhtmltopdf, commencez par passer à un répertoire approprié pour télécharger le paquet, dans ce cas /tmp :

      Téléchargez la version wkhtmltopdf appropriée et le paquet pour Ubuntu 18.04 depuis la page du projet :

      • wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.bionic_amd64.deb

      Installez maintenant le paquet en utilisant l’outil dpkg :

      • sudo dpkg -i wkhtmltox_0.12.5-1.bionic_amd64.deb

      Ensuite, copiez tous les exécutables pertinents dans votre répertoire /usr/bin/ :

      • sudo cp /usr/local/bin/wkhtmlto* /usr/bin/

      Une fois les fichiers en place, modifiez leurs autorisations pour les rendre exécutables :

      • sudo chmod a+x /usr/bin/wk*

      Maintenant que wkhtmltopdf est correctement installé, nous ajouterons Redis à notre pile de base de données.

      Installation de Redis

      ERPNext 12 utilise Redis pour améliorer les performances de MariaDB. Plus précisément, il aide à la mise en cache.

      Tout d’abord, installez Redis depuis le référentiel officiel Ubuntu 18.04 :

      • sudo apt install redis-server

      Ensuite, activez Redis au démarrage :

      • sudo systemctl enable redis-server

      Maintenant que vous avez ajouté Redis à votre pile, prenons un moment pour résumer ce que vous avez accompli jusqu’à présent. Jusqu’à présent, vous avez installé tous les principaux composants nécessaires à ERPNext 12, dont :

      • Un backend de base de données MariaDB
      • L’environnement serveur JavaScript Node.js
      • Le gestionnaire de paquets Yarn
      • Un cache de la base de donnée de Redis
      • Le générateur de documents PDF wkhtmltopdf

      Que vous installiez le système ERP pour le développement ou pour la production, vous êtes maintenant prêt pour la prochaine étape, qui consiste à installer le framework full-stack Frappe et l’application web ERPNext 12 actuelle.

      Étape 6 — Configuration de l’ILC Bench de Frappe

      Maintenant que vous avez mis en place toutes les exigences de pile d’ERPNext, vous pouvez exploiter la flexibilité de l’utilitaire de ligne de commande bench de Frappe. L’ILC bench a été conçue dans le but d’aider les utilisateurs dans le processus d’installation, de mise en place et de gestion d’applications comme ERPNext, qui reposent sur le Framework Frappe. Dans les sections suivantes, vous allez installer l’ILC bench et l’utiliser ensuite pour terminer le processus de configuration d’ERPNext 12.

      Assurez-vous que l’utilisateur de Frappe (dans ce cas sammy) dispose des droits appropriés sur son répertoire home :

      • sudo chown sammy -R /home/sammy

      Maintenant, clonez le référentiel frappe/bench vers votre répertoire de base. N’oubliez pas de remplacer sammy par votre nom d’utilisateur système :

      • git clone https://github.com/frappe/bench /home/sammy/.bench --depth 1 --branch master

      Installez l’ILC bench :

      • sudo pip3 install -e /home/sammy/.bench

      Ce guide suppose que vous installez ERPNext 12 pour des scénarios de test/production et que vous utilisez donc la branche master. Mais si votre intention est de développer des applications ou des modules ERPNext personnalisés, la branche develop pourrait être préférable. Dans les deux cas, vous êtes maintenant prêt à installer le Framework de Frappe. Ce sera la dernière étape avant d’installer ERPNext lui-même.

      Configuration de l’environnement du framework de Frappe

      Dans cette section, vous allez créer un environnement Frappe en utilisant l’ILC bench.

      Pendant l’installation de Frappe, vous pouvez dépasser la limite de surveillance des fichier d’Ubuntu, qui par défaut est fixée à 8192. Pour éviter ce problème, définissez une limite supérieure en utilisant la commande suivante :

      • echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

      Ensuite, initialisez Frappe framework 12. Remplacez Sammy par votre nom d’utilisateur système :

      • bench init /home/sammy/frappe-bench --frappe-path https://github.com/frappe/frappe --frappe-branch version-12 --python python3

      Au cours de l’exécution, vous pouvez voir une erreur concernant votre chemin d’accès, ainsi que plusieurs avertissements. Laissez le processus se poursuivre jusqu’à la fin. Une fois terminé, vous verrez un résultat similaire à celui qui suit, indiquant que votre environnement a été créé avec succès :

      Output

      ... Done in 82.23s. INFO:bench.utils:setting up backups no crontab for sammy SUCCESS: Bench /home/sammy/frappe-bench initialized

      Note : le processus bench init pourrait s’arrêter si une erreur spawn ENOMEM était rencontrée. Cette erreur se produit lorsque votre système manque de mémoire. Vous devez corriger le problème avant de continuer, soit en installant plus de mémoire physique, soit en attribuant l’espace SWAP.

      Examinons de plus près la commande utilisée pour créer l’environnement :

      • /home/sammy/frappe-bench est le chemin où le framework Frappe, les sites web et les applications connexes seront installés. Un nouveau répertoire, appelé frappe-bench dans cet exemple, sera créé pour accueillir tous les fichiers nécessaires.
      • --frappe-path pointe vers le référentiel de Frappe, qui dans ce cas est le référentiel officiel de Github.
      • --frappe-branch est la version Frappe à installer. Comme vous souhaitez installer ERPNext 12, la version choisie est Frappe 12.
      • --python est la version Python qui sera utilisée. ERPNext 12 requiert Python 3.6+. Les versions antérieures, cependant, utilisent toujours Python 2.7.

      Pour plus d’informations sur les commandes ILC bench, veuillez vous référer à la fiche d’aide des commandes de Bench.

      La flexibilité offerte par le framework Frappe va bien au-delà de l’utilisation d’environnements isolés. Vous pouvez également créer différents sites web et y installer des applications.

      Étape 7 — Configuration de l’application web ERPNext 12

      Dans cette section, vous allez configurer un site reposant sur Frappe, puis installer l’application ERPNext 12 sur celui-ci.

      Passez dans le répertoire où Frappe a été initialisé.

      • cd /home/sammy/frappe-bench

      Maintenant, téléchargez ERPNext 12 depuis son référentiel en utilisant l’ILC bench :

      • bench get-app erpnext https://github.com/frappe/erpnext --branch version-12

      Ensuite, créez le nouveau site, en remplaçant your_domain par le domaine que vous avez associé à l’IP de ce serveur :

      • bench new-site your_domain --admin-password 'erpnext_admin_password' --mariadb-root-username sammy --mariadb-root-password 'mariadb_password'

      Prenons un moment pour examiner les options utilisées dans la commande ci-dessus :

      • bench new-site crée un nouveau site reposant sur le framework Frappe.
      • your_domain est le nom du nouveau site. Assurez-vous que le DNS de votre domaine a un enregistrement A pointant vers l’IP de votre serveur.
      • erpnext_admin_passwordest le mot de passe souhaité pour l’utilisateur Administrator d’ERPNext. Conservez ce mot de passe dans un endroit sûr, vous en aurez besoin sous peu.
      • mariadb_password est le mot de passe que vous avez créé au début du guide de l’utilisateur sammy de MariaDB.

      Ensuite, installez l’application ERPNext sur le site :

      • bench --site your_domain install-app erpnext

      Une fois l’installation terminée, vous disposerez d’une application ERPNext 12 fonctionnelle. Maintenant, testons-la à l’aide d’une commande bench :

      La commande ci-dessus lancera une console de surveillance en temps réel vous montrant divers messages concernant le serveur web et d’autres services. Ouvrez un navigateur web et naviguez vers localhost:8000 (pour les installations locales) ou your_domain:8000 (si vous utilisez un serveur distant). Vous verrez l’écran de connexion ERPNext (nous procéderons à la connexion et à la configuration dans une étape ultérieure, une fois que notre site sera prêt pour la production).

      Après avoir consulté votre déploiement de test, retournez à votre terminal et appuyez sur CTRL+C. Cela arrêtera ERPNext et permettra de quitter la console de surveillance.

      Si votre objectif principal est de créer des modules ou de modifier ERPNext 12, vous pouvez alors vous arrêter à ce stade. Aucun autre composant n’est nécessaire pour le développement. Cependant, si vous avez besoin d’un système prêt pour la production qui ne requiert pas d’initialisation manuelle, vous devrez alors installer et configurer quelques composants supplémentaires. C’est votre prochaine étape.

      Étape 8 — Configuration d’ERPNext 12 pour la production

      Bien que l’application ERPNext 12 soit prête, le système dans son ensemble n’est pas encore complètement prêt pour la production. Pour garantir la fiabilité et la sécurité d’ERPNext, vous devrez activer quelques services supplémentaires :

      • Fail2ban fournit une couche supplémentaire de protection contre les tentatives de recours abusif des utilisateurs et des bots malveillants.
      • Nginx fonctionne principalement comme un proxy web, redirigeant tout le trafic depuis le port 8000 vers le port 80 (HTTP) ou le port 443 (HTTPS)
      • Supervisor veille à ce que les processus clés d’ERPNext soient constamment opérationnels, en les redémarrant au besoin.

      Jusqu’à ce stade, vous avez installé et configuré manuellement ERPNext 12, ce qui vous a permis de personnaliser le processus pour qu’il corresponde à n’importe quel cas d’utilisation particulier. Néanmoins, pour le reste de la configuration de la production, vous pouvez tirer parti de la commodité de l’ILC bench, afin d’automatiser l’installation et la configuration de ces services restants.

      Assurez-vous que vous êtes bien dans le répertoire de travail de Frappe :

      • cd /home/sammy/frappe-bench

      Maintenant, utilisez la commande suivante pour terminer la configuration d’ERPNext 12 pour la production :

      • sudo bench setup production sammy --yes

      La commande ci-dessus installera et configurera aNginx, Supervisor, et Fail2Ban, et définira sammy comme propriétaire de l’environnement de production.

      Les fichiers de configuration créés par la commande bench  sont les suivants :

      • Deux fichiers de configuration Nginx situés dans /etc/nginx/nginx.conf et /etc/nginx/conf.d/frappe-bench.conf
      • Un proxy jail Fail2Ban situé dans /etc/fail2ban/jail.d/nginx-proxy.conf et un filtre situé dans /etc/fail2ban/filter.d/nginx-proxy.conf

      Ces configurations par défaut suffiront pour ce tutoriel, mais n’hésitez pas à explorer et ajuster ces fichiers pour qu’ils correspondent à vos besoins. Vous pouvez arrêter tous les services en exécutant :

      • sudo supervisorctl stop all

      Et ensuite, une fois que vous êtes prêt, vous pouvez redémarrer vos services :

      • sudo supervisorctl start all

      Maintenant vous êtes prêt pour tester votre installation.

      Test de votre installation ERPNext 12

      Tout d’abord, vérifiez que les principaux services de production fonctionnent en utilisant la commande systemctl suivante, puis en la transmettant à grep :

      • systemctl list-unit-files | grep 'fail2ban|nginx|supervisor'

      Vous verrez un résultat similaire à ce qui suit :

      Output

      fail2ban.service enabled nginx.service enabled supervisor.service enabled

      Après avoir confirmé que tout fonctionne comme prévu, vous pouvez tester ERPNext 12 en direct sur votre serveur. Ouvrez votre navigateur préféré et naviguez jusqu’au domaine où vous hébergez votre application ERPNext 12.

      Après quelques secondes, vous devriez voir l’écran de connexion d’ERPNext 12. Utilisez Administrator pour le nom d’utilisateur et erpnext_admin_password que vous avez créé précédemment pour le mot de passe.

      Écran de connexion d'ERPNext

      Dans l’écran suivant, vous verrez un menu déroulant où vous pouvez sélectionner la langue de l’interface utilisateur pour l’application :

      Sélection de la langue

      Après la sélection de la langue, ERPNext vous demandera d’entrer votre pays, votre fuseau horaire et votre devise :

      Sélectionnez votre région

      Une fois que vous aurez complété les informations sur votre région, vous pourrez créer le premier utilisateur ERPNext. Les informations que vous fournissez seront utilisées comme identifiants de connexion de l’utilisateur.

      Premier utilisateur ERPNext

      Dans l’écran suivant, vous serez questionné sur ce qu’ERPNext appelle Domains. Si vous n’êtes pas sûr de savoir quel est votre domaine, sélectionnez Distribution et cliquez sur le bouton Next.

      Sélectionnez vos domaines

      Ensuite, vous devrez fournir un nom de société et une abréviation.

      Nom de la société

      Dans le dernier écran, ERPNext vous demandera d’indiquer l’activité de votre société, le nom de sa banque, le type de plan comptable et la période de l’exercice. Vous pourrez entrer des banques supplémentaires plus tard. Pour l’instant, remplissez tous les champs comme vous le souhaitez, puis cliquez sur le bouton Complete Setup.

      Informations financières

      Ensuite, vous verrez un barre de progression.

      Configuration d'ERPNext

      Une fois le processus de configuration terminé, le tableau de bord principal d’ERPNext 12 apparaît.

      Tableau de bord d'ERPNext 12

      Vous avez maintenant entièrement installé et configuré une application ERPNext 12.

      Conclusion

      Maintenant que vous avez correctement installé votre application ERPNext 12, vous pouvez commencer à mettre en œuvre le système pour vos besoins commerciaux. Un bon point de départ consiste à cliquer sur le bouton Getting Started sur le tableau de bord d’ERPNext. ERPNext vous aidera alors à configurer la plate-forme pour tous vos besoins commerciaux et de commerce électronique.

      Mise en route

      Vous pouvez également souhaiter améliorer la vitesse d’ERPNext. Si c’est le cas, vous pouvez lire les informations sur le réglage de performance ERPNext, qui vous guideront sur les meilleures pratiques et sur la manière de résoudre les problèmes liés aux performances.



      Source link