Fermer

septembre 21, 2021

Tutoriel React Dashboard—Créer un tableau de bord interactif


Créez un tableau de bord React avec des aperçus utiles, personnalisables par l'utilisateur avec des widgets glisser/basculer et des vignettes configurables.

Les tableaux de bord sont un excellent moyen de fournir rapidement aux utilisateurs un aperçu des informations et des métriques pertinentes liées à leurs comptes, applications ou des produits.

Dans ce didacticiel de tableau de bord React, nous allons expliquer comment créer un tableau de bord interactif pour afficher les métriques des candidatures à l'aide du Composant React TileLayout proposé par KendoReact. Le tableau de bord permettra aux utilisateurs de faire glisser, de commander et de basculer les widgets du tableau de bord à travers des vignettes configurables dynamiquement.

L'exemple de code complet pour ce modèle d'interface utilisateur React peut être trouvé dans ce référentiel GitHub . Vous pouvez également voir ce que nous allons construire dans le CodeSandbox ci-dessous. Assurez-vous de développer le panneau du navigateur lorsque vous le visualisez.

Configuration du projet pour notre modèle d'interface utilisateur React

Tout d'abord, nous devons configurer un nouveau projet React. Pour créer rapidement un échafaudage, vous pouvez utiliser Create React App ou Vite. Pour cette démo, nous allons utiliser Create React App. Vous pouvez créer un projet React en exécutant l'une des commandes ci-dessous dans votre terminal.

npx create-react-app my-kendo-react-interactive-dashboard
cd my-kendo-react-interactive-dashboard
npm start // ou début du fil

Maintenant, installez quelques packages KendoReact dont nous avons besoin.

 npm install @progress/kendo-licensing @progress/kendo-react-animation @progress/kendo-react-charts @progress/kendo-drawing @progress/kendo- react-grid @progress/kendo-data-query @progress/kendo-react-buttons @progress/kendo-react-dateinputs @progress/kendo-react-treeview @progress/kendo-react-dropdowns @progress/kendo-react- entrées @progress/kendo-react-popup @progress/kendo-react-data-tools @progress/kendo-react-intl @progress/kendo-react-progressbars @progress/kendo-react-layout @progress/kendo-react- graphiques @progress/kendo-react-animation @progress/kendo-theme-material hammerjs

Remarque : KendoReact est une bibliothèque de composants d'interface utilisateur commerciale, et dans le cadre de celle-ci, vous devrez fournir une clé de licence lorsque vous utilisez les composants dans vos projets React. Vous pouvez obtenir une clé de licence via un essai gratuit ou en possédant une licence commerciale. Pour plus d'informations, vous pouvez vous rendre sur la page KendoReact Licensing.

Ensuite, remplacez le contenu des fichiers App.js et App.css.

src/App.js

import "@progress/kendo-theme-material/dist/all.css";
import "./App. css";
function App() {
  return <div className=" App"></div>;
}

export default Application;

src/App.css

.App {
  max-width: 70rem;
  margin[19659015]: 2rem auto;
}

C'est tout pour la configuration du projet. Construisons notre tableau de bord interactif.

Configuration du React TileLayout

Le composant TileLayout offre une grille CSS bidimensionnelle qui peut être utilisée pour rendre les composants dans une disposition en grille. Les composants du TileLayout peuvent être positionnés soit manuellement en spécifiant la position initiale, soit dynamiquement à l'aide de l'algorithme auto-flow. Nous irons avec le premier. Créons maintenant un tableau de bord de base avec deux widgets qui affichent un exemple de texte.

src/App.js

import "@progress/kendo-theme-material/dist/all.css" ;
import { TileLayout } from "@progress/kendo-react-layout";
import { useState } from "react";
import "./App.css";

const WidgetOne  = () => <div>Widget un</div> ;
const WidgetTwo = () => <div>Widget deux</div>;

const positions initiales = [
  {
    col: 1,
    colSpan: 2,
    rowSpan: 2,
  },
  {
    col: 3,
    colSpan: 1,
    rowSpan: 1,
  },
];


function App() {[19659024]const [positions, setPositions] = useState(initialPositions)[19659012315];[196599015] const widgets = [
   	{
      header: "Widget un en-tête",
      corps: <WidgetOne />,
    },
    {
      header: "Widget deux en-tête",
      body: <WidgetTwo />,
    },
  ];

  const handleReposition[19659068]= e => {
    setPositions(e.value);
  }[19659015];

  retour (
    <div className="App">
      <h1>Tableau des tâches</h1>
      <TileLayout
        className="tileLayout"
        colonnes={4}
        ligneHauteur={255}
        écart={{ lignes: 10, colonnes: 10 }[19659015]}
        postes={postes}
        éléments={widgets}
        onReposition={handleReposition}
      />
    </div>
  );
}

export default App;

Le composant TileLayout accepte quelques accessoires différents. Nous pouvons définir le nombre de colonnes de la grille en passant un nombre à la prop columns. La hauteur des lignes est définie en passant un autre nombre via la prop rowHeightet l'espacement entre les colonnes et les lignes est configuré avec la prop gap.

Les positions se compose d'objets qui peuvent avoir les propriétés rowcolrowSpancolSpan et order. Les deux premiers sont utilisés pour spécifier à quelle ligne et à quelle colonne une tuile doit être placée. Les propriétés rowSpan et colSpan déterminent le nombre de lignes et de colonnes à prendre. La propriété order peut être utilisée pour définir l'indice d'ordre de chaque tuile. Pour cet exemple, nous n'avons pas besoin d'utiliser les propriétés row ou order.

En outre, nous avons la propriété items qui reçoit un tableau avec des détails et les composants qui seront rendus dans la grille de mise en page. Enfin, le gestionnaire onReposition qui définit de nouvelles données de position après qu'un utilisateur a manipulé la position des widgets. Ci-dessous, vous pouvez voir le résultat.

La configuration de base de TileLayout montre deux widgets simples glissés-déposés autour d'un espace de tableau de bord

Comme le montre le gif ci-dessus, nous pouvons déjà faire glisser et réorganiser les widgets. . Cependant, les deux widgets que nous avons pour le moment n'ont rien de spécial, alors créons-en quelques-uns qui fourniront des informations utiles concernant les statuts des candidatures. crédits d'emploi, vues totales des emplois et statistiques pour l'emploi le plus populaire. Vous pouvez créer des fichiers et copier le code ci-dessous.

src/components/ActiveJobs.js

const ActiveJobs = props => {[19659024]retour (
    <div className="activeJobs">
      <div className="activeJobsContainer">
        <span className="activeJobsNum">5</  envergure>
      </div>
    </div>
  );
};

export default ActiveJobs;

Les composants ActiveJobscomme leur nom l'indique, affichent un certain nombre de tâches actuellement actives. Pour le moment, c'est cinq.

src/components/JobCredits.js

const JobCredits = props => {
  return[19659023](
    <div className="jobCredits">
      <div className="jobCreditsContainer">
        <span className="jobCreditsNum">850</  envergure>
      </div>
    </div>
  );
};

export default JobCredits;

Le composant JobCredits fonctionne de la même manière que le composant ActiveJobs. Si vous le souhaitez, vous pouvez créer un composant générique pour les deux.

src/components/TotalJobViews.js

const jobViews = [
  {
    identifiant: 1,
    tâche : "Développeur Full-Stack",
    vues : 150,
  },
  {
    identifiant: 2,
    job : "Développeur Android mobile",
    vues: 25,
  },
  {
    identifiant: 3,
    tâche : "Développeur JavaScript",
    vues : 69,
  },
  {
    identifiant: 4,
    tâche : "Développeur Python",
    vues: 45,
  },
];

const TotalJobViews = accessoires =>  {
  retour (
    <div>
      <div className="">
        <ul className="totalJobViewsGrid">
          {jobViews.map((job) => {
            return (
              <li className="jobViewsBlock" key={job .id}>
                <span className="jobTitle">{job. travail}</span>

                <div className="jobViewsContainer">
                  <span className="jobViews">{job. vues}</span>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    </div>
  );
};

export default TotalJobViews;

Le composant TotalJobViews parcourt les tâches actives et affiche le nombre de fois que chaque tâche a été consultée.

src/components/MostPopularJob.js

import {
  Graphique,
  Titre du graphique,
  GraphiqueLégende,
  Info-bulle graphique,
  GraphiqueSérie,
  Élément de la série graphique,
  ChartSeriesLabels,
} from "@progress/kendo-react-charts";

const COULEURS = {
  rejeté : "#B91C1C",
  appliqué: "#D97706",
  interviewing: "#2563EB",
};

const getPercentage = (num, total) =>
  Math.arrondi((num / total) * 100).[19659343]àFixe(2);

const numApplied = 75;
const numInterviewing [19459046= 24;
const numRejeté = 46;
const totalDemandeurs = numApplied+ numInterviewing + numRejected;

const candidats = [
  {
    statut : "Appliquer",
    value: getPercentage(numApplied, totalApplicants),
    couleur: COULEURS.appliquées,
  },
  {
    statut : "Entrevue",
    value: getPercentage(numInterviewing, totalApplicants),
    couleur: COULEURS.interview,
  },
  {
    statut : "Rejeté",
    value: getPercentage(numRejected, totalApplicants),
    color: COLORS.rejeté,
  },
];

const renderTooltip = contexte => {
  const { catégorie, valeur } = contexte.point || contexte;
  retour (
    <div>
      {catégorie} : {valeur}%
    </div>
  );
};

const MostPopularJob = accessoires => {
  retour (
    <div>
      <div className="k-mb-4">
        Votre travail le plus populaire est "Développeur Full-Stack"
      </div>

      <Graphique style={{ minHeight: "20rem" }}[19659015]>
        <ChartTitle text="Statut des applications - ce mois" />
        <Légende du graphique visible={false} />
        <ChartTooltip render={renderTooltip} />
        <Série de graphiques>
          <ChartSeriesItem
            type="donut"
            données={demandeurs}
            CatégorieChamp="statut"
            champ="valeur"
          >
            <ChartSeriesÉtiquettes
              color="#fff"
              arrière-plan="aucun"
              content={e => e.category}
            />
          </ChartSeriesItem>
        </Série de graphiques>
      </Graphique>
    </div>
  );
};

export default MostPopularJob;

Le composant MostPopularJob affiche l'emploi le plus populaire avec un graphique en anneau qui contient des informations sur le nombre de candidats qui ont postulé, sont en cours d'entretien et ont été rejetés.

Si vous le souhaitez. pour en savoir plus sur comment créer facilement des graphiques avec KendoReactj'ai l'article qu'il vous faut !

Enfin, mettons à jour App.js et App.css pour inclure les quatre widgets que nous venons de créer et leur ajouter des styles.

src/App.js

import "@progress/kendo-theme-material/dist /all.css";
import { TileLayout } from "@progress/kendo-react-layout";
import  { useState } from "react";
import "./App.css";
import ActiveJobs de "./comp onents/ActiveJobs";
import TotalJobViews from "./components/TotalJobViews";
import MostPopularJob  from from ./components/MostPopularJob";
import JobCredits from "./components/JobCredits";

const initialPositions=[19459090][
  {
    col: 1,
    colSpan: 2,
    rowSpan: 2,
  },
  {
    col: 3,
    colSpan: 1,
    rowSpan: 1,
  },
  {
    col: 4,
    colSpan: 1,
    rowSpan: 1,
  },
  {
    col: 3,
    colSpan: 2,
    rowSpan: 2,
  },
];

const getPositions = positions initiales =>  {
  
  
  retour (
    JSON.parse(localStorage.getItem("dashboard-positions")) ||  positions initiales
  );
};

fonction App() {
  const [positions, setPositions] = useState(getPositions(initialPositions))[19651239015]t;[1965959 widgets = [
    {
      en-tête : "Nombre total de vues de travaux",
      body: <TotalJobViews />,
    },
    {
      header: "Travaux actifs",
      corps: <ActiveJobs />,
    },
    {
      en-tête : "Crédits de travail",
      corps: <JobCredits />,
    },
    {
      header: "Emploi le plus populaire",
      body: <MostPopularJob />,
    },
  ];

  const handleReposition[19659068]= e => {
    setPositions(e.value);
    localStorage.setItem("dashboard-positions", JSON.stringify(e.valeur));
  };

  retour (
    <div className="App">
      <h1>Tableau de bord des tâches</h1>
      <TileLayout
        className="tileLayout"
        colonnes={4}
        ligneHauteur={255}
        postes={postes}
        écart={{ lignes: 10, colonnes: 10 }[19659015]}
        éléments={widgets}
        onReposition={handleReposition}
      />
    </div>
  );
}

export default App;

Tous les widgets sont importés et transmis à l'intérieur du tableau widgets. Le tableau initialPositions a maintenant des positions pour les quatre widgets. En plus de cela, l'état positions essaiera d'obtenir les positions initiales du stockage local, ou il utilisera par défaut le tableau initialPositions. De plus, le gestionnaire handleReposition enregistrera de nouvelles positions dans le stockage local. Normalement, cela serait enregistré dans la base de données, mais cela suffira pour cet exemple.

Last but not least, nous devons ajouter de nouvelles classes dans le fichier App.css.

. ]src/App.css

.App {
  max-width: 70rem;
  margin:[19659041]2rem auto;
}

.activeJobs,
.jobCredits {
  hauteur: 100%;
}

.activeJobs,
.activeJobsContainer,
.jobViewsContainer,
.jobViewsBlock,
.jobCrédits,
.jobCreditsContainer {
  display: flex;
  justify-content: center;
  align -items: center;
}

.jobViewsContainer,
.activeJobsContainer,
.jobCreditsContainer {
  padding: 1rem;
  border-radius: 50% ;
  largeur: 5rem;
  hauteur: 5rem;
}

.jobViewsContainer  {
  border: 1px solid #7c3aed;
  background-color: #ede9fe[19659015];
  color: #7c3aed;
}

.activeJobsContainer {
  border: 1 px solide #2563eb;
  background-color: #dbeafe;
  color: #2563eb;
 }

.jobCreditsContainer {
  color: #b45309;
  border: 1px soli d #b45309;
  background-color: #fef3c7;
}

.activeJobsNum,
.jobViews,
.jobCreditsNum {
  font-size: 3rem;
  font-weight: 600[19659015];
}

.jobViewsBlock {
  flex-direction: colonne;
}

.jobTitle [19659015]{
  margin-bottom: 1rem;
  font-weight: 500;
  affichage :  block;
}

.totalJobViewsGrid {
  list-style: none;
  affichage :  grille;
  grille-modèle-colonnes: 1fr 1fr;
  grille-modèle-lignes[19659015]: 1fr 1fr;
  gap: 2rem;
  rembourrage :  0;[19659033]}

.tileLayout {
  width: 100%;
}

.dashboardAside {[19659039]largeur: 15rem;
}

Vous pouvez voir le résultat dans le gif ci-dessous.

Tableau de bord interactif React avec widgets de tâche4 widgets sont glissés et déposés autour du tableau de bord. Ils ont différents tableaux et graphiques associés. Le nombre total de vues des tâches affiche 4 compteurs différents avec les types de tâches consultées. Les travaux actifs ont un compteur d'une couleur différente. Les crédits de travail ont un autre compteur dans une couleur différente. Et le travail le plus populaire utilise un graphique en anneau pour afficher trois catégories différentes similaires à un graphique à secteurs, mais contournant l'extérieur du cercle au lieu de secteurs.

Nous avons un joli tableau de bord interactif avec des vignettes (widgets) qui peut être réorganisé. Ajoutons une fonctionnalité pour réinitialiser les positions et basculer les prochains widgets actifs.

Réinitialiser les positions de TileLayout

L'ajout de la fonctionnalité de réinitialisation est très simple. Nous avons besoin d'un bouton et d'un gestionnaire qui définiront les positions sur le tableau initialPositions. Ajoutez le gestionnaire onResetLayout et mettez à jour le balisage JSX comme indiqué ci-dessous.

src/App.js

const onResetLayout = ()  => {
  setPositions(initialPositions);
  localStorage.setItem(
    "dashboard-positions",
    JSON.stringify(initialPositions)
  );
};

retour (
  <div className="App">
    <h1>Tableau de bord des tâches</h1>
    <div className="k-display-flex">
      <TileLayout
        colonnes={4}
        ligneHauteur={255}
        postes={postes}
        écart={{ lignes: 10, colonnes: 10 }[19659015]}
        éléments={widgets}
        onReposition={handleReposition}
        />
      <div className="k-ml-4">
        <button className="k-button" onClick={onResetLayout}>
          Reset layout
        </button>
      </div>
    </div>
  </div>
);

Below you can see the reset functionality in action.

There is now a button for Reset Layout, which returns TileLayout positions to how they started

Great, let’s add one more functionality that will be a bit more complex—toggling widgets.

At the moment, the tiles are defined in an array called widgets. However, we need the UI to update whenever we change the active status of each widget. Therefore, we need to add a useState for the widgets and then filter it to get only active widgets.

We need to do the same for positions because if a widget is not passed to the TileLayout component, the position for it also should not be included. Below you can see the final implementation.

src/App.js

import "@progress/kendo-theme-material/dist/all.css";
import { TileLayout } from "@progress/kendo-react-layout";
import { useMemo, useState } from "react";
import "./App.css";
import ActiveJobs from "./components/ActiveJobs";
import TotalJobViews from "./components/TotalJobViews";
import MostPopularJob from "./components/MostPopularJob";
import JobCredits from "./components/JobCredits";
import { Switch } from "@progress/kendo-react-inputs";

const initialPositions = [
  {
    widgetId: "1",
    col: 1,
    colSpan: 2,
    rowSpan: 2,
  },
  {
    widgetId: "2",
    col: 3,
    colSpan: 1,
    rowSpan: 1,
  },
  {
    widgetId: "3",
    col: 4,
    colSpan: 1,
    rowSpan: 1,
  },
  {
    widgetId: "4",
    col: 3,
    colSpan: 2,
    rowSpan: 2,
  },
];

const getPositions = initialPositions => {
  
  
  return (
    JSON.parse(localStorage.getItem("dashboard-positions")) || initialPositions
  );
};

const widgetsConfig = [
  {
    id: "1",
    header: "Total job views",
    body: <TotalJobViews />,
    active: true,
  },
  {
    id: "2",
    header: "Active jobs",
    body: <ActiveJobs />,
    active: true,
  },
  {
    id: "3",
    header: "Job Credits",
    body: <JobCredits />,
    active: true,
  },
  {
    id: "4",
    header: "Most popular job",
    body: <MostPopularJob />,
    active: true,
  },
];

function App() {
  const [positions, setPositions] = useState(getPositions(initialPositions));
  const [widgets, setWidgets] = useState(widgetsConfig);

  
  const activeWidgets = useMemo(() => {
    return widgets.reduce((acc, widget) => {
      
      if (!widget.active) return acc;
      
      acc.push(widget);
      return acc;
    }, []);
  }, [widgets]);

  
  
  const filteredPositions = useMemo(() => {
    return positions.filter(position => {
      
      return activeWidgets.find(widget => widget.id === position.widgetId)
        ?.active;
    });
  }, [activeWidgets, positions]);

  const handleReposition = e => {
    setPositions(e.value);
    localStorage.setItem("dashboard-positions", JSON.stringify(e.value));
  };

  const onResetLayout = () => {
    setPositions(initialPositions);
    localStorage.setItem(
      "dashboard-positions",
      JSON.stringify(initialPositions)
    );
  };

  const onToggleWidget = e => {
    const { id } = e.target.props;
    const { value } = e.target;
    const updatedWidgets = widgets.map(widget => {
      if (widget.id === id) {
        return {
          ...widget,
          active: value,
        };
      }
      return widget;
    });

    setWidgets(updatedWidgets);
  };

  return (
    <div className="App">
      <h1>Job dashboard</h1>
      <div className="k-display-flex">
        <TileLayout
          columns={4}
          rowHeight={255}
          positions={filteredPositions}
          gap={{ rows: 10, columns: 10 }}
          items={activeWidgets}
          onReposition={handleReposition}
          className="tileLayout"
        />
        <aside className="k-ml-4 dashboardAside">
          <div className="k-mb-6">
            <button className="k-button" onClick={onResetLayout}>
              Reset layout
            </button>
          </div>
          <div>
            <h2 className="k-mb-4">Toggle Widgets</h2>
            <div>
              {widgets.map(widget => {
                return (
                  <div className="k-mb-2" key={widget.id}>
                    <Switch
                      checked={widget.active}
                      onChange={onToggleWidget}
                      id={widget.id}
                    />
                    <label className="k-ml-3">{widget.header}</label>
                  </div>
                );
              })}
            </div>
          </div>
        </aside>
      </div>
    </div>
  );
}

export default App;

Below you can see the final product.

Now there are four toggles for our four widgets, and toggling them off removes them from the dashboard.

Wrap-up

That’s it! We have used the KendoReact TileLayout component to build an interactive dashboard for job application metrics with items that can be dragged, reordered and toggled. I hope you enjoyed this tutorial.

KendoReact is a great tool for developing complex functionality. It provides a lot of feature-rich components out of the box and allows us to create sophisticated features quite easily and quickly. You can check out the entire functionality of the library with a free trialwhich also gives you access to technical support if you ever get stuck.




Source link