For AI agents: the complete documentation index is available at https://docs.dataplatform.ovh.net/ja/llms.txt, the full documentation bundle is available at https://docs.dataplatform.ovh.net/ja/llms-full.txt, and this page is available as Markdown at https://docs.dataplatform.ovh.net/ja/tutorials-app-development-custom-components.md.
  • 🇯🇵 日本語
  • カスタムコンポーネントを追加する

    Reactフレームワークを使用すると、独自のコンポーネントをゼロから作成できます。これらのコンポーネントは、2つの用途に使用できます:動的パラメータとチャート

    目的

    Reactフレームワークを使用すると、独自のコンポーネントをゼロから作成できます。これらのコンポーネントは、2つの用途に使用できます:動的パラメータチャート

    Info

    いつでも、技術ガイド🔧を参照して、カスタムコンポーネントについてさらに詳しく学ぶことができます!

    カスタムコンポーネントを動的パラメータとして使用する

    コンポーネントの生成

    カスタムコンポーネントを作成し、それを動的パラメータとして使用する方法を説明します。

    このチュートリアルでは、チェックボックスグループコンポーネントを作成する手順をステップバイステップで説明します。

    alt text

    コンポーネントを生成するには、以下のコマンドを実行して、事前構築されたスクリプトを使用できます。

    yarn generate

    component ジェネレータを選択し、DynamicParameterCheckbox と名前を付け、以下に示すように最後の質問に対して「No」と回答します。

    alt text
    Warning

    コンポーネント名が DynamicParameter で始まることが重要です。これは、それを動的パラメータとして登録するためです。

    このスクリプトは、src/components にフォルダを生成し、以下の3つのファイルを含みます。

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

    コンポーネントの宣言

    コンポーネント自体に取り組む前に、宣言方法と使用方法を確認しましょう。

    新しいコンポーネントを宣言するには、以下の手順に従います。

    • src/components/index.js に移動します。

    • ファイルの先頭に以下の行を追加してコンポーネントをインポートします。

      import DynamicParameterCheckbox from "./DynamicParameterCheckbox";
    • コンポーネント名をコンポーネントオブジェクトに追加して宣言します。

        components: {
            ...
            DynamicParameterCheckbox
      },

    これで、設定ファイルでこのコンポーネントを呼び出すことができます。コンポーネントの alias を指定します。コンポーネントのエイリアスを取得するには、名前を camelCase から kebab-case に変換します(DynamicParameterCheckboxdynamic-parameter-checkbox になります)、その後、名前から "dynamic-parameter" と/または "chart" を削除します。

    ここでは、コンポーネントのエイリアスは checkbox です。次に、config/menus/sidebar.json に移動し、dynamic-weekdaycomponent プロパティを "checkbox"(つまり、エイリアス)に変更します。

    アプリケーションページに移動し、dynamic-weekday コンポーネントが変更された ことに注意してください。

    alt text

    今すぐ動作しない場合は心配しないでください。その動作は次のセクションで設定されます。

    コンポーネントの編集

    このガイドで使用するフレームワークは React です。

    Info

    コンポーネントの作成をステップバイステップでガイドしますが、このフレームワークに慣れていないために問題が発生している場合は、こちらのドキュメントを確認してください。 🆘

    また、機能コンポーネントを使用しているため、React Hooks の最新機能の1つを使用します。詳細については、このページ を確認してください。

    DynamicParameterCheckbox.jsx の編集を開始します。

    このコンポーネントは動的パラメータとして宣言されているため、Platforms データフローのロジックによって自動的にいくつかのプロパティが渡されます。これらのプロパティは、useEffect フックを使用してコンポーネントが最初にレンダリングされるときにログに記録できます。

    まず、useEffectuseState(後で必要になる)をインポートするには、ファイルの最初の行を変更します。

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

    次に、props を関数コンポーネントの引数に追加します。

    const DynamicParameterCheckbox = (props) => {

    最後に、この関数の return 文の直前に useEffect フックを追加します。

    関数コンポーネントは以下のように定義する必要があります。

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

    ブラウザのコンソールパネルを開き、プロパティを確認できます。

    alt text

    動的パラメータを定義する際に sidebar.json に渡されるプロパティのほとんどは、items です。これは、dictionary(この例では week_day)で指定されたフィールドを照会する内部リクエストの結果です。

    alt text

    次に、チェックボックスを作成します。

    これを実現するには、小さなパッケージである react-checkbox-group をインストールする必要があります。以下を実行してインストールします。

    yarn add react-checkbox-group

    このパッケージを使用すると、チェックボックスグループコンポーネントを使用できます。ファイルの先頭に以下の行を追加してインポートできます。

    import CheckboxGroup from 'react-checkbox-group'

    コンポーネントの状態にブール値変数 expanded を追加して、小さな矢印アイコン付きの CheckboxGroup を表示または非表示にできます。

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

    関数の return 文を以下のように変更します。

    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>
    )

    タイトルセクションは props.title を使用しています。これは、dynamic-weekday の定義で title プロパティを渡す必要があることを意味します。config/menus/sidebar.json で以下のように示すとおりです。(HTML要素は冗長になったため削除されました)

    {
      "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"
          }
        }
      ]
    }

    最後に、DynamicParameterCheckbox.less を変更してコンポーネントをスタイル設定します。以下のコードスニペットを使用します。

    DynamicParameterCheckbox.less
    // DynamicParameterCheckbox stylesheet
    
    @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;
    }

    動的パラメータは今良い感じになりましたが、まだ正しく動作していません。

    alt text

    問題があります。ボックスにチェックを入れることができません!

    その理由は、CheckboxGroup を動的パラメータコンポーネントにバインドする必要があるからです。そのためには、コンポーネントの状態に配列を追加する必要があります。選択されたオプションを追跡するため、selectedOptions と名前を付けます。

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

    先ほど定義した配列を更新する関数 onChange を追加します。

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

    最後に、CheckboxGroup に2つのプロパティ(onChangevalueselectedOptions を含む配列)を追加する必要があります。それらをバインドするには、return 文を変更します。

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

    ほぼ完成です! 🚴‍♂️

    最後のステップは、この動的パラメータを redux グローバルストア にバインドして、チャートリクエストに影響を与えられるようにすることです。よりモダンで簡潔なアプローチのために React Redux フックを使用します。ファイルの先頭のインポートに以下の行を追加します。

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

    次に、DynamicParameterCheckbox 関数コンポーネント内で、フックを使用して Redux 状態と dispatch 関数にアクセスします。これらの行をコンポーネント関数内に配置します。

    const options = useSelector((state) => state.querystring[props.id])
    const dispatch = useDispatch()
    • useSelector: このフックを使用すると、Redux ストア状態からデータを抽出できます。ここでは、Redux 状態の querystring 部分から props.id に関連付けられた値を取得しています。このオプション変数は、この特定の ID について Redux 状態が変更されるたびに自動的に更新されます。

    • useDispatch: このフックは、Redux ストアから dispatch 関数への参照を返します。この dispatch 関数を使用して、ストアを更新するアクションを送信します。

    DynamicParameterCheckbox 関数コンポーネント内で、ヘルパー関数 updateModel を作成し、アクションをグローバルストアにディスパッチします。

    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))
      }
    }

    この関数は、useDispatch から取得した dispatch 関数を使用して、set アクションを送信し、Redux ストアの querystring を更新します。

    次に、onChange 関数を更新して、単に updateModel に新しいオプションを渡すようにします。

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

    コンポーネントの内部状態(selectedOptions)が、Redux ストアの状態(特にこのパラメータに対するページのリフレッシュや Redux 状態の外部変更の後)と同期されていることを確保するには、useEffect フックを以下のように更新します。

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

    この useEffect フックは、useSelector を通じて Redux ストアから直接取得されるオプション値が変更されるたびに実行されます。これにより、コンポーネントのローカル selectedOptions 状態がグローバル Redux 状態と同期され、動的パラメータの一貫したビューが提供されます。

    動的パラメータは現在グローバルストアに接続されています。動的パラメータに影響を受ける dynamic-weekday に接続されたチャートがあるため、そのことを確認できます。

    最初のカスタム動的パラメータを作成しました。 途中で迷子になった場合は 😪 心配しないでください。最終コードは こちら で確認できます。

    駅でフィルタリングできるように、2番目の動的パラメータを追加しましょう。

    alt text

    新しいコンポーネントを生成します。

    yarn generate

    component ジェネレータを選択し、DynamicParameterAutocompleteBox と名前を付け、最後の質問に対して「No」と回答します。

    新しく生成された .jsx ファイルの内容を以下のように変更します。

    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

    src/components/index.js宣言 します。 ファイルで定義された components オブジェクトに新しいコンポーネントをインポートして追加します。

    config/dashboards/rides-analytics.json に移動し、id が search-bar のパネルを探し、動的パラメータに置き換えます

    {
      "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": []
    }

    最後に、config/menus/sidebar.json から dyn-stations オブジェクト全体を削除します。これは、新しい検索バーと重複しているためです。

    カスタムコンポーネントをチャートとして使用する

    このセクションでは、カスタムコンポーネントを作成し、それをチャートとして使用する方法を学びます。

    例として、react-leaflet ライブラリを使用してインタラクティブなマップコンポーネントを作成します。最終的な結果は次のようになります。

    alt text

    まず、通常通りスクリプトを使用してコンポーネントを作成することから始めましょう。

    yarn generate

    component ジェネレーターを選択し、ChartMap と名前を付け、最後の質問には「No」と回答してください。

    Warning

    チャートコンポーネントの名前は 'Chart' で始まるようにしてください。そうすることで、正しく認識され、登録されます。

    src/components/index.js宣言してください。

    これで、アナリティクスダッシュボードで使用できます。rides-analytics.json に移動し、新しいチャートとそのタイトルを 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

    動的パラメータと同様に、チャートもマウントされる際に自動的にいくつかのプロパティを受け取ります。それらがどのようなものか見てみましょう。

    通常通り、useEffectuseStateChartMap.jsx ファイルの最初の行を変更することでインポートします。

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

    次に、props を関数コンポーネントの引数に追加します。

    const ChartMap = (props) => {

    最後に、この関数の return 文の直前に useEffect フックを追加します。

    最終的な関数コンポーネントは次のようになります。

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

    ブラウザのコンソールパネルを開き、このコンポーネントに渡されたプロパティを確認できます。

    alt text

    これらのプロパティのほとんどは、config/dashboards/rides-analytics.json のチャート定義から来ています。 例外は data で、これはチャートに関連付けられたリクエストの結果を表す JSON です。この JSON はできるだけ汎用的なものになるように設計されていますので、操作するのが少し面倒な場合があります。

    alt text

    この例では -- そしてほとんどの場合 -- JSON オブジェクトが複雑すぎるため、このヘルパー関数を使用してフラット化し、取り扱いをはるかに簡単にします。

    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;
    }

    上記のコードスニペットをインポートと ChartMap の間にコピー&ペーストし、新しいフラット化された結果を可視化するために useEffect フックの内容を更新します。

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

    これらの結果をマップに表示するには、このデータをコンポーネントの状態に保存する必要があります。ChartMap コンポーネント内に次のように配列を宣言します。

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

    useEffect を更新して、結果をログに記録する代わりにこの配列を変更します。

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

    データの準備ができたので、次にマップを作成する方法を見てみましょう。

    まず、react-leaflet コンポーネントをインポートするには、ファイルの先頭にこの行を追加します。

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

    ChartMap.less に移動し、次のコードスニペットを使用してスタイルシートを変更します。

    ChartMap.less
    // ChartMap stylesheet
    @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;
    }

    ChartMap.jsx に戻り、状態のすぐ下にデフォルトのマップパラメータ(中心、ズーム、最小ズーム)を定義します。

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

    関数の return 文を変更して、シカゴに中心を置いた空のマップを表示します。

    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

    次に、LeafletMapTileLayer のすぐ下に円マーカーを追加して、駅を表します。

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

    円マーカーをカスタマイズするには、サイズ、重さ、色などを制御するためのプロパティをいくつか追加できます。完全なドキュメントはこちらでご覧いただけます。

    以下は、円の色を変更し、そのサイズを乗車回数に比例させるコードスニペットです。

    <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)"}
    />

    次に、円をクリックしたときに駅名とその駅に関連する乗車回数を表示するポップアップを追加します。

    CircleMarker 内に次のように追加します。

    <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

    config/formatter.jsonrides に指定された書式設定ルールに従って、平均乗車回数を表示させるには FpMeasure を使用できます。

    alt text

    FpMeasure をインポートします。

    import { FpMeasure } from 'forepaas/formatter'

    ポップアップの値を変更します。

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

    マップを少し操作すると、動的パラメータを変更するとマップが再読み込みされることに気づくでしょう。この動作を無効にするには、config/dashboards/rides-analytics.json のチャート設定オプションに noReload プロパティを追加します。

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

    react-leaflet-markercluster ライブラリのおかげで、重なりを避けるために円をクラスターで整理するのは非常に簡単です。

    MarkerClusterGroup コンポーネントをインポートします。

    import MarkerClusterGroup from 'react-leaflet-markercluster'

    次に、円マーカーを MarkerClusterGroup でラップします。

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

    最初のカスタムコンポーネントを作成しました。 迷子になった場合は心配しないでください。最終コードはこちらで確認できます。

    Info

    カスタムコンポーネントの作成についてさらに詳しく学ぶには、技術ガイドを参照してください!

    ローカルアプリを Data Platform に公開する

    ローカルでアプリを完成させたので、プラットフォームに接続する時期です。 zip ファイルとしてアプリをアップロードするか、git リポジトリに接続するかのいずれかの方法で行うことができます。

    アプリを zip ファイルとしてインポートする

    まず、アプリを zip ファイルとしてエクスポートする必要があります。zip ファイルには、次のフォルダを含めてはいけません: node_modules, forepaas, webpack, .git

    alt text

    アプリを zip ファイルとして生成するには、事前に構築されたスクリプトを使用することもできます。プロジェクトにアップロードする準備ができた zip ファイルを生成するには、このコマンドを実行します。

    yarn zip

    アプリケーションフォルダと同じ名前の zip ファイルが生成されます。

    次に、この .zip ファイルを使用して新しいアプリケーションを作成するにはこれらの手順に従います。または、既存のアプリケーションを編集し、zip ファイルをアップロードしてアプリケーションの新しいバージョンを作成することもできます。

    alt text

    アプリを git リポジトリに接続する

    git リポジトリをプラットフォームにリンクするには、このガイドに従ってください。

    アプリをアップロードしたら、ビルドし、デプロイします。

    alt text

    素敵なアプリが Data Platform にデプロイされました!

    さらに学ぶ

    ソリューションを実装するためのトレーニングや技術サポートが必要な場合は、営業担当者にお問い合わせください、またはこのリンクをクリックして見積もりを依頼し、プロフェッショナルサービスの専門家にプロジェクトのカスタム分析を依頼してください。

    Data Platform を構築するチームと直接やり取りし、質問をしたり、フィードバックを送信したり、Discord の専用チャネルに参加したりできます。

    OVHcloud サービスについてサポートが必要な場合は、ヘルプセンターでリクエストを作成してください。

    コミュニティに参加してください。