For AI agents: the complete documentation index is available at https://docs.ovhcloud.com/fr/llms.txt, the full documentation bundle is available at https://docs.ovhcloud.com/fr/llms-full.txt, and this page is available as Markdown at https://docs.ovhcloud.com/fr/guides/public-cloud/data-platform/tutorials-app-development-custom-components.md.

Ajouter des composants personnalisés

Voir en Markdown

Avec le framework React, vous pouvez créer vos propres composants depuis zéro. Ces composants peuvent être utilisés pour deux choses : les paramètres dynamiques et les graphiques

Objectif

Avec le framework React, vous pouvez créer vos propres composants depuis zéro. Ces composants peuvent être utilisés pour deux choses : les paramètres dynamiques et les graphiques.

Info

À tout moment, n'hésitez pas à consulter le Guide technique pour en savoir plus sur les composants personnalisés !

Utiliser un composant personnalisé comme paramètre dynamique

Générer un composant

Voyons comment créer un composant personnalisé et comment l'utiliser comme paramètre dynamique.

À titre d'exemple, nous allons vous montrer étape par étape comment créer ce composant de groupe de cases à cocher :

alt text

Pour générer un composant, vous pouvez utiliser notre script préconstruit en exécutant la commande ci-dessous :

yarn generate

Sélectionnez le générateur component, nommez-le DynamicParameterCheckbox et répondez « No » à la dernière question, comme indiqué ci-dessous :

alt text
Warning

Il est important que le nom de votre composant commence par DynamicParameter pour qu'il soit enregistré comme paramètre dynamique

Ce script génère un dossier dans src/components contenant trois fichiers :

  • DynamicParameterCheckbox.jsx
  • DynamicParameterCheckbox.less
  • index.js

Déclarer un composant

Avant de commencer à travailler sur le composant lui-même, prenons une minute pour voir comment le déclarer et l'utiliser.

Suivez ces étapes pour déclarer le nouveau composant :

  • Allez dans src/components/index.js

  • Importez le composant en ajoutant cette ligne en haut du fichier :

    import DynamicParameterCheckbox from "./DynamicParameterCheckbox";
  • Déclarez-le en ajoutant son nom à l'objet components

      components: {
          ...
          DynamicParameterCheckbox
    },

Vous pouvez maintenant appeler ce composant dans vos fichiers de configuration en spécifiant son alias. Pour obtenir l'alias d'un composant, transformez son nom du camelCase au kebab-case (DynamicParameterCheckbox devient dynamic-parameter-checkbox), puis retirez-en "dynamic-parameter" et/ou "chart".

Ici, l'alias du composant est checkbox. Allez maintenant dans config/menus/sidebar.json et changez la propriété component de dynamic-weekday en "checkbox" (c'est-à-dire l'alias).

Allez sur la page de votre application, remarquez que le composant dynamic-weekday a changé.

alt text

Le composant s'affiche mais n'est pas encore fonctionnel : son comportement est défini dans la section suivante.

Modifier un composant

Le framework utilisé dans ce guide sera React.

Info

Nous allons vous guider étape par étape pour créer vos composants, mais si vous rencontrez des difficultés parce que vous n'êtes pas familier avec ce framework, vous pouvez consulter la documentation ici.

De plus, puisque nous travaillons avec des composants fonctionnels, nous allons utiliser l'une des dernières fonctionnalités disponibles, les React Hooks. Vous pouvez consulter cette page pour plus d'informations.

Commençons par modifier DynamicParameterCheckbox.jsx

Puisque ce composant est déclaré comme un dynamic-parameter, certaines props lui sont déjà automatiquement transmises par la logique de flux de données de la Platform. Ces props peuvent être journalisées lors du premier rendu du composant, en utilisant le hook useEffect.

Commencez par importer useEffect et useState (dont vous aurez besoin plus tard) en modifiant la première ligne du fichier :

import React, { useEffect, useState } from 'react'

Ajoutez ensuite props aux arguments du composant fonctionnel :

const DynamicParameterCheckbox = (props) => {

Enfin, ajoutez le hook useEffect à l'intérieur de cette fonction, juste avant l'instruction return.

Votre composant fonctionnel devrait être défini comme suit :

const DynamicParameterCheckbox = (props) => {
  useEffect(() => {
    console.log(props);
  }, []);

  return <div>DynamicParameterCheckbox</div>;
};

Ouvrez le panneau console de votre navigateur, vous devriez pouvoir voir les props.

alt text

Comme vous pouvez le voir, la plupart de ces props sont transmises dans sidebar.json lors de la définition du dynamic-parameter.
La seule exception est items, qui est le résultat d'une requête interne interrogeant le champ spécifié dans dictionary (week_day dans ce cas)

alt text

Créons maintenant les checkboxes.

Pour y parvenir, vous devrez installer un petit package : react-checkbox-group. Faites-le en exécutant :

yarn add react-checkbox-group

Ce package vous permet d'utiliser un composant de groupe de cases à cocher. Vous pouvez maintenant l'importer en ajoutant cette ligne en haut du fichier :

import CheckboxGroup from 'react-checkbox-group'

Ajoutez une variable booléenne expanded à l'état du composant pour pouvoir afficher ou masquer le CheckboxGroup à l'aide d'une petite icône flèche :

const DynamicParameterCheckbox = (props) => {
  const [expanded, setExpanded] = useState(true)
  ...

Changez l'instruction return de la fonction comme suit :

return (
  <div>
    <div className='dyn-title checkbox-header'>
      {props.title}
      <i onClick={() => setExpanded(!expanded)} className={`fa fa-chevron-${expanded ? 'down' : 'right'} expand-icon`} /></div>
    {expanded && <CheckboxGroup name='options'>
      {(Checkbox) => (
        <React.Fragment>
          {props.items.map(option =>
            <div key={option.value}>
              <label className='dyn-checkbox-container' htmlFor={option.value}>
                <Checkbox className='dyn-checkbox' id={option.value} value={option.value} />
                <span className='dyn-checkbox-label'>{option.label}</span>
              </label>
            </div>)}
        </React.Fragment>
      )}
    </CheckboxGroup>}
  </div>
)

La section titre utilise props.title. Cela signifie que vous devez transmettre une prop title dans la définition de dynamic-weekday dans config/menus/sidebar.json, comme indiqué ci-dessous : (l'élément HTML a également été retiré puisqu'il est désormais redondant)

{
  "id": "dyn-weekday",
  "items": [
    {
      "type": "dynamic-parameter",
      "dynamic-parameter": {
        "type": "filter",
        "id": "dynamic-weekday",
        "dictionary": "week_day_label",
        "component": "checkbox",
        "title": "Days"
      },
      "style": {
        "paddingBottom": "10px"
      }
    }
  ]
}

Enfin, stylisez votre composant en modifiant DynamicParameterCheckbox.less, à l'aide de l'extrait de code ci-dessous.

DynamicParameterCheckbox.less
// Feuille de style DynamicParameterCheckbox

@import "../../styles/_variables.less";

.checkbox-header {
  display: flex;
  flex-direction: row;
  align-items: center;
}

.dyn-checkbox-container {
  display: flex;
  align-items: flex-end;
  margin: 3px;
}

.dyn-checkbox {
  -webkit-appearance: none;
  background-color: #fafafa;
  border: 1px solid #cacece;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), inset 0px -15px 10px -12px rgba(0, 0, 0, 0.05);
  padding: 7px;
  border-radius: 3px;
  display: inline-block;
  position: relative;
}

.dyn-checkbox:hover {
  cursor: pointer;
  box-shadow: 0 1px 2px @primary-color, inset 0px 1px 3px @primary-color;
  border: 1px solid @primary-color;
}

.dyn-checkbox:active,
.dyn-checkbox:checked:active {
  box-shadow: 0 1px 2px @primary-color, inset 0px 1px 3px @primary-color;
}

.dyn-checkbox:checked {
  background-color: @primary-color;
  border: 1px solid @primary-color;
  box-shadow: 0 1px 2px @primary-color, inset 0px -15px 10px -12px
      @primary-color, inset 15px 10px -12px @primary-color;
  color: white;
}

.dyn-checkbox:checked:after {
  content: "\2714";
  font-size: 12px;
  position: absolute;
  top: -1px;
  left: 2px;
  color: white;
}

.dyn-checkbox-label {
  cursor: pointer;
  font-family: "Source Sans Pro";
  font-size: 14px;
  letter-spacing: 0;
  color: #97a7b7;
  line-height: 17px;
  margin-left: 5px;
}

.fa.expand-icon {
  color: #97a7b7;
  font-size: 12px;
  cursor: pointer;
  margin-left: 5px;
}

.fa.expand-icon:hover {
  color: #3e4550;
  cursor: pointer;
}

Votre dynamic-parameter a maintenant une belle apparence, mais il ne fonctionne pas encore correctement.

alt text

Il y a un problème, vous ne pouvez cocher aucune case !

La raison est que vous devez lier CheckboxGroup à notre composant dynamic-parameter. Pour ce faire, vous devez ajouter un tableau à l'état de votre composant. Il gardera une trace des options sélectionnées, alors nommez-le selectedOptions :

const DynamicParameterCheckbox = (props) => {
  const [expanded, setExpanded] = useState(true)
  const [selectedOptions, setSelectedOptions] = useState([])
  ...

Ajoutez une fonction onChange pour mettre à jour le tableau que vous venez de définir :

const onChange = options => {
  setSelectedOptions(options);
};

Enfin, vous devez ajouter les deux propriétés (onChange et value, un tableau contenant selectedOptions) à CheckboxGroup. Liez-les en modifiant l'instruction return :

return (
  ...
  <CheckboxGroup name='options' value={selectedOptions || []} onChange={onChange}>
  ...

La dernière étape consiste à lier ce dynamic-parameter au store global redux pour lui permettre d'affecter les requêtes des graphiques. Nous allons utiliser les hooks React Redux pour une approche plus moderne et rationalisée. Ajoutez ces lignes aux imports en haut du fichier :

import { useSelector, useDispatch } from 'react-redux'
import { set } from 'forepaas/store/querystring/action'

Ensuite, à l'intérieur de votre composant fonctionnel DynamicParameterCheckbox, accédez à l'état Redux et à la fonction dispatch à l'aide des hooks. Placez ces lignes à l'intérieur de la fonction de votre composant :

const options = useSelector((state) => state.querystring[props.id])
const dispatch = useDispatch()
  • useSelector : ce hook vous permet d'extraire des données de l'état du store Redux. Ici, nous récupérons la valeur associée à props.id depuis la partie querystring de votre état Redux. Cette variable options se mettra automatiquement à jour à chaque fois que l'état Redux change pour cet ID spécifique.

  • useDispatch : ce hook renvoie une référence vers la fonction dispatch du store Redux. Vous utiliserez cette fonction dispatch pour envoyer des actions afin de mettre à jour le store.

À l'intérieur de votre composant fonctionnel DynamicParameterCheckbox, créez une fonction utilitaire updateModel pour envoyer vos actions au store global :

const updateModel = (model) => {
  if (props.id) {
    let value = (model || []).map((item) => item && item.value ? item.value : item)
    dispatch(set(props.id, value.length ? value : null))
  }
}

Cette fonction utilise maintenant la fonction dispatch obtenue depuis useDispatch pour envoyer l'action set, mettant à jour la querystring dans le store Redux.

Ensuite, mettez à jour votre fonction onChange pour simplement appeler updateModel avec les nouvelles options :

const onChange = (options) => {
    updateModel(options)
  }

Pour vous assurer que l'état interne de votre composant (selectedOptions) est synchronisé avec l'état du store Redux (notamment après un rafraîchissement de page ou des changements externes à l'état Redux pour ce paramètre), mettez à jour votre hook useEffect comme suit :

useEffect (() => {
    setSelectedOptions(options)
  }, [options])

Ce hook useEffect s'exécutera chaque fois que la valeur options (qui provient directement de votre store Redux via useSelector) change. Il maintient l'état local selectedOptions de votre composant synchronisé avec l'état Redux global, offrant une vue cohérente du paramètre dynamique.

Votre paramètre dynamique est maintenant connecté au store global. Vous pouvez vous en assurer car les graphiques connectés à dynamic-weekday sont affectés par ce paramètre dynamique.

Vous avez créé votre premier paramètre dynamique personnalisé.
Le code final est disponible ici.

Ajouter une barre de recherche

Ajoutons un second paramètre dynamique pour pouvoir filtrer par station.

alt text

Générez un nouveau composant :

yarn generate

Sélectionnez le générateur component. Nommez-le DynamicParameterAutocompleteBox et répondez « No » à la dernière question.

Remplacez le contenu du fichier .jsx nouvellement généré par ceci :

DynamicParameterAutocompleteBox.jsx
import React, { useState, useEffect } from 'react'
import Select, { createFilter }  from 'react-select'
import { useSelector, useDispatch } from 'react-redux'
import { set } from 'forepaas/store/querystring/action'

const searchIcon = () => ({
  alignItems: 'center',
  display: 'flex',
  ':before': {
    fontFamily: 'FontAwesome',
    content: '"\f002"',
    marginRight: 8
  }
})

const customStyles = {
  control: (base, state) => ({
    ...base,
    height: '57px',
    borderWidth: '0px',
    boxShadow: '5px 5px -2px rgba(0, 0, 0, 0.1)'
  }),
  option: (base, state) => ({
    ...base,
    color: state.theme.colors.neutral50,
    fontSize: '13px',
    height: '48px',
    display: 'flex',
    alignItems: 'center',
    fontWeight: 500,
    letterSpacing: 0
  }),
  menu: (base, state) => ({
    ...base,
    zIndex: 2000
  }),
  multiValue: (base, state) => ({
    ...base,
    borderRadius: '21px',
    backgroundColor: state.theme.colors.primary75,
    color: state.theme.colors.neutral0,
    height: '34px',
    alignItems: 'center'
  }),
  multiValueLabel: (base, state) => ({
    ...base,
    color: state.theme.colors.neutral0,
    display: 'flex',
    alignItems: 'center',
    marginLeft: '10px',
    fontWeight: 600,
    letterSpacing: 0
  }),
  placeholder: (base, state) => ({
    ...base,
    color: state.theme.colors.neutral20,
    fontSize: '14px',
    ...searchIcon()
  }),
  multiValueRemove: (base, state) => {
    return ({
      ...base,
      color: state.theme.colors.neutral0,
      borderRadius: '10px',
      padding: '0px',
      margin: '10px',
      border: `1px solid ${state.theme.colors.neutral0}`,
      ':hover': {
        backgroundColor: state.theme.colors.neutral0,
        color: state.theme.colors.primary75,
        cursor: 'pointer'
      }
    })
  }

}

const DynamicParameterAutocompleteBox = ({ items, ...props }) => {
  const [selectedOptions, setSelectedOptions] = useState([])
  const selectedValues = useSelector((state) => state.querystring[props.id])
  const dispatch = useDispatch()
  items.sort((a,b) => (a.label > b.label) ? 1 : ((b.label > a.label) ? -1 : 0))

  const customTheme = theme => ({
    ...theme,
    colors: {
      ...theme.colors,
      primary: props.primaryColor || '#00CCF9',
      primary25: props.primary25Color || 'rgba(16,182,233,0.06)',
      primary50: props.primary50Color || 'rgba(16,182,233,0.20)',
      primary75: props.primary75Color || 'rgba(16,182,233,0.8)',
      neutral20: props.placeholderColor || '#97A7B7',
      neutral50: props.menuColor || '#485465'
    }
  })

  useEffect (() => {
    const mappedOptions = items.filter(item => (selectedValues || []).includes(item.value))
    setSelectedOptions(mappedOptions)
  }, [selectedValues, items])

  const updateModel = (model) => {
    if (props.id) {
      let values = (model || []).map((item) => item && item.value ? item.value : item)
      dispatch(set(props.id, values.length ? values : null))
    }
  }

  const onChange = (options) => {
    if (options && !Array.isArray(options)) {
      options = [options]
    }
    updateModel(options)
  }

  return (
    <Select 
      value={selectedOptions || []} 
      styles={customStyles} theme={customTheme} 
      options={items} 
      isMulti={props.isMulti}
      placeholder={props.placeholder}
      onChange={onChange} 
      autoFocus={true}
      isClearable={true}
      isSearchable={true}
      pageSize={10}
      closeMenuOnSelect={true}
      filterOption={createFilter({ignoreCase: true, ignoreAccents: true, trim: true, matchFrom: 'start'})}
    />
  )
}

export default DynamicParameterAutocompleteBox

Déclarez-le dans src/components/index.js en important votre nouveau composant et en l'ajoutant à l'objet components défini dans le fichier.

Allez dans config/dashboards/rides-analytics.json, cherchez le panel dont l'id est search-bar et remplacez-le par un dynamic-parameter comme suit :

{
  "type": "dynamic-parameter",
  "id": "search-bar",
  "dynamic-parameter": {
    "type": "filter",
    "id": "dynamic-stations",
    "component": "autocomplete-box",
    "placeholder": "Search for a station",
    "isMulti": true,
    "dictionary": "station_name"
  },
  "sizeX": 100,
  "sizeY": 19,
  "col": 0,
  "row": 0,
  "items": []
}

Enfin, retirez tout l'objet dyn-stations de config/menus/sidebar.json, car il est redondant avec la nouvelle barre de recherche.

Utiliser un composant personnalisé comme graphique

Dans cette section, vous apprendrez à créer un composant personnalisé et à l'utiliser comme graphique.

À titre d'exemple, vous allez créer un composant de carte interactive à l'aide de la bibliothèque react-leaflet. Le résultat final ressemblera à ceci :

alt text

Commençons par créer le composant à l'aide du script, comme d'habitude.

yarn generate

Sélectionnez le générateur component, nommez-le ChartMap et répondez « No » à la dernière question.

Warning

Il est important que le nom de votre composant de graphique commence par 'Chart', afin qu'il soit reconnu et enregistré correctement.

Déclarez-le dans src/components/index.js.

Vous pouvez maintenant l'utiliser dans votre dashboard analytics. Allez dans rides-analytics.json, et ajoutez le nouveau graphique ainsi que son titre au panel custom-map :

{
  "type": "panel",
  "id": "custom-map",
  "sizeX": 75,
  "sizeY": 99,
  "row": 20,
  "col": 0,
  "items": [
    {
      "type": "html",
      "content": "Map view",
      "customclass": "chart-title",
      "sizeX": 100,
      "sizeY": 5
    },
    {
      "type": "chart",
      "chart": {
        "id": "chart-map",
        "component": "map",
        "dynamic-parameters": [
          "dynamic-date",
          "dynamic-holidays",
          "dynamic-stations",
          "dynamic-weekday"
        ],
        "request": {
          "data": {
            "fields": {
              "rides": ["avg"]
            }
          },
          "scale": {
            "fields": ["station_id", "station_name", "lat", "lng"]
          },
          "filter": {},
          "order": {}
        }
      },
      "sizeX": 100,
      "sizeY": 88,
      "row": 6,
      "col": 0
    }
  ]
}
alt text

Comme les dynamic-parameters, les graphiques reçoivent également automatiquement certaines propriétés lors de leur montage. Voyons à quoi elles ressemblent.

Comme d'habitude, importez useEffect et useState en modifiant la première ligne du fichier ChartMap.jsx :

import React, { useState, useEffect } from 'react'

Ajoutez ensuite props aux arguments du composant fonctionnel :

const ChartMap = (props) => {

Enfin, ajoutez un hook useEffect à l'intérieur de cette fonction, juste avant l'instruction return.

Votre composant fonctionnel final devrait ressembler à ceci :

const ChartMap = (props) => {
  useEffect(() => {
    console.log(props);
  }, []);
  return <div>ChartMap</div>;
}

Ouvrez le panneau console de votre navigateur, vous devriez pouvoir voir les props transmises à ce composant.

alt text

La plupart de ces props proviennent de la définition du graphique dans config/dashboards/rides-analytics.json.
L'exception est data, qui est un JSON représentant le résultat de la requête associée au graphique. Ce JSON se veut aussi générique que possible, il peut donc être un peu fastidieux à manipuler.

alt text

Dans cet exemple -- et dans la plupart des cas -- l'objet JSON est trop complexe, nous utilisons donc cette fonction utilitaire pour l'aplatir et le rendre bien plus facile à manipuler :

const flattenChartResults = results => {
  let flattenedChartResults = [];
  results.forEach(result => {
    let fieldEntries = [];
    Object.entries(result.data).forEach(([fieldName, computeModes]) => {
      Object.entries(computeModes).forEach(([computeModeName, rows]) => {
        computeModeName === "select"
          ? fieldEntries.push([computeModeName, rows[0].value])
          : fieldEntries.push([
              `${fieldName}_${computeModeName}`,
              rows[0].value
            ]);
      });
    });
    let flattenedObject = {
      ...result.scales,
      ...Object.fromEntries(fieldEntries)
    };
    flattenedChartResults.push(flattenedObject);
  });
  return flattenedChartResults;
}

Copiez-collez l'extrait de code ci-dessus entre les imports et ChartMap, puis mettez à jour le contenu de votre hook useEffect pour visualiser les nouveaux résultats aplatis :

useEffect(() => {
  const results = flattenChartResults(props.chart.data.results);
  console.log(results);
}, [props.chart.data.results]);
alt text

Pour afficher ces résultats sur la carte, vous devez stocker ces données dans l'état du composant. Déclarez un tableau à l'intérieur du composant ChartMap comme ceci :

const ChartMap = (props) => {
  const [stations, setStations] = useState([])
  ...

Mettez à jour useEffect pour modifier ce tableau au lieu de journaliser les résultats :

useEffect(() => {
  const results = flattenChartResults(props.chart.data.results);
  setStations(results);
}, [props.chart.data.results]);

Maintenant que vous avez préparé les données, voyons comment créer la carte.

Importez maintenant les composants react-leaflet en ajoutant cette ligne en haut de votre fichier :

import { Map as LeafletMap, CircleMarker, Popup, TileLayer } from 'react-leaflet'

Allez dans ChartMap.less et modifiez la feuille de style à l'aide de l'extrait de code ci-dessous :

ChartMap.less
// Feuille de style ChartMap
@import "~leaflet/dist/leaflet.css";
@import "~react-leaflet-markercluster/dist/styles.min.css";

.leaflet-container {
  height: 100%;
}

.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
  opacity: 0.85;
  background-color: #3e4550;
  box-shadow: inset 0 -3px 0 0 rgba(0, 0, 0, 0.13);
  color: #fff;
}

.leaflet-popup-content-wrapper {
  text-align: center;
  border-radius: 1px;
}

.popup-title {
  letter-spacing: 0;
  font-size: 13px;
}

.popup-value {
  font-size: 13px;
  font-weight: 600;
}

Retournez dans ChartMap.jsx et définissez vos paramètres de carte par défaut (center, zoom, minZoom) juste en dessous de votre state :

const center = [41.89, -87.6297982]
const zoom = 14
const minZoom = 7

Modifiez l'instruction return de votre fonction pour afficher une carte vide centrée sur Chicago :

return (
  <LeafletMap center={center} zoom={zoom} minZoom={minZoom}>
    <TileLayer
      attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
      url="https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png"
    />
  </LeafletMap>
)
alt text

Ajoutez maintenant des circle markers à l'intérieur de LeafletMap, juste en dessous du TileLayer, pour représenter les stations :

{
  stations.map(station => (
    <CircleMarker
      key={station.station_id}
      center={[station.lat, station.lng]}
    />
  ))
}
Info

Vous pouvez personnaliser vos circle markers en ajoutant des props pour contrôler leur taille, leur épaisseur, leur couleur, etc. Vous pouvez trouver la documentation complète ici

Ci-dessous, un extrait de code qui change la couleur des cercles et rend leur taille proportionnelle au nombre de trajets.

<CircleMarker
  key={station.station_id}
  center={[station.lat, station.lng]}
  radius={Math.max(
    10 + (station.rides_avg / 1000) * Math.log(zoom),
    ((2 * station.rides_avg) / 1000) * Math.log(zoom)
  )}
  color={"#0089C0"}
  weight={1}
  fillColor={"rgba(0,204,249,0.5)"}
/>

Ensuite, ajoutez un popup pour afficher le nom de la station et le nombre de trajets qui lui sont associés lors du clic sur un cercle.

Ajoutez-le à l'intérieur de CircleMarker comme indiqué ci-dessous :

<CircleMarker
  key={station.station_id}
  center={[station.lat, station.lng]}
  radius={Math.max(
    10 + (station.rides_avg / 1000) * Math.log(zoom),
    ((2 * station.rides_avg) / 1000) * Math.log(zoom)
  )}
  color={"#0089C0"}
  weight={1}
  fillColor={"rgba(0,204,249,0.5)"}
>
  <Popup closeButton={false} position={[station.lat, station.lng]}>
    <div className="popup-title">{station.station_name}</div>
    <div className="popup-value">{station.rides_avg}</div>
  </Popup>
</CircleMarker>
alt text

Vous pouvez faire en sorte que le nombre moyen de trajets suive les règles de formatage spécifiées dans config/formatter.json pour rides, en utilisant FpMeasure.

alt text

Importez FpMeasure :

import { FpMeasure } from 'forepaas/formatter'

Modifiez la valeur du popup :

<div className="popup-value">
  {new FpMeasure("rides").setValue(station.rides_avg).toString()}
</div>

Si vous jouez un peu avec votre carte, vous remarquerez qu'elle continue de se recharger lorsque vous changez vos paramètres dynamiques. Vous pouvez désactiver ce comportement en ajoutant une propriété noReload dans les options de configuration de votre graphique, dans config/dashboards/rides-analytics.json :

"chart": {
  "id": "chart-map",
  "component": "map",
  "noReload": true,
  "dynamic-parameters": [
    ...
  ],
  "request": {
    ...
  }
},

Réorganisez vos cercles par clusters pour éviter les chevauchements ; c'est assez simple grâce à la bibliothèque react-leaflet-markercluster.

Importez le composant MarkerClusterGroup :

import MarkerClusterGroup from 'react-leaflet-markercluster'

Puis enveloppez vos circle markers dans MarkerClusterGroup comme ceci :

<MarkerClusterGroup showCoverageOnHover={false}>
  {stations.map(station => (
    <CircleMarker
      ...
    </CircleMarker>
  ))}
</MarkerClusterGroup>

Vous avez créé votre premier composant personnalisé.
Le code final est disponible ici.

Info

Pour en savoir plus sur la création de vos composants personnalisés, consultez le Guide technique !

Publier votre application locale sur la Data Platform

Maintenant que vous avez terminé votre application en local, il est temps de la connecter à la platform.
Vous pouvez le faire soit en chargeant l'application sous forme de fichier zip, soit en la connectant à un repository git.

Importer votre application en tant que fichier zip

Tout d'abord, vous devez exporter votre application au format zip. Votre fichier zippé ne doit pas contenir les dossiers suivants : node_modules, forepaas, webpack, .git.

alt text

Vous pouvez également utiliser notre script préconstruit pour zipper votre application ; pour générer un fichier zip prêt à être chargé sur votre Projet, exécutez simplement cette commande.

yarn zip

Un fichier zip portant le même nom que le dossier de votre application sera généré.

Ensuite, vous pouvez soit créer une nouvelle application à l'aide de ce fichier .zip en suivant ces étapes, soit modifier une application existante et charger le fichier zip pour créer une nouvelle version de votre application :

alt text

Connecter votre application à un repository git

Pour relier un repository git à la platform, veuillez suivre ce guide.

Une fois votre application chargée, buildez-la puis déployez-la.

alt text

Votre superbe application est maintenant déployée sur la Data Platform !

Aller plus loin

Si vous avez besoin d'une formation ou d'une assistance technique pour la mise en oeuvre de nos solutions, contactez votre commercial ou cliquez sur ce lien pour obtenir un devis et demander une analyse personnalisée de votre projet à nos experts de l’équipe Professional Services.

Posez vos questions, faites-nous part de vos commentaires et interagissez directement avec l’équipe qui développe la Data Platform sur le canal Discord dédié.

Si vous avez besoin d'une assistance concernant vos services OVHcloud, créez une demande depuis notre centre d'aide.

Rejoignez notre communauté d'utilisateurs.

Cette page vous a-t-elle aidé ?