Обзор

В этой серии руководств мы собираемся создать расширение Qlik Sense с использованием Nebula.js и React, используя Recharts библиотеки построения диаграмм React. Recharts — это компонуемая библиотека диаграмм компонентов React, созданная на основе D3. Вы можете найти домашнюю страницу библиотеки здесь .

В частности, мы собираемся создать расширение диаграммы с областями на основе некоторых данных о COVID-19. Я знаю, что это не супер оригинально, но он научит вас основам создания расширений в Nebula и React.

Что вы узнаете

  • Как начать создавать расширения Qlik Sense с помощью Nebula.js и React
  • Основы хуков React
  • Библиотека графиков Recharts

Что вам нужно

  • Qlik Sense Desktop или Qlik Sense Business Cloud
  • Node и NPM, установленные на вашем компьютере, и редактор кода
  • Доступ к нашему стартовому проекту Nebula React доступен здесь: https://github.com/datalitlearning/nebula-react-starter .

Проект github Nebula — React

Загрузите стартовый проект Nebula — React с Github и запустите пользовательский интерфейс Nebula.js.

Мы создали стартовый проект, чтобы избежать головной боли при настройке. Это тесно связано с примером React на странице github Nebula.js. Чтобы начать работу с ним, перейдите к: https://github.com/datalitlearning/nebula-react-starter

и либо клонируйте репо, либо загрузите. Затем откройте папку с выбранным вами редактором кода и в терминале перейдите в корень вашего проекта и запустите…

npm i
npm run start

Это запустит пользовательский интерфейс, в котором вы можете ввести свои учетные данные сайта Qlik Sense и подключиться к своему сайту. Он должен выглядеть примерно так, как показано ниже:

Подключение к вашему сайту Qlik Sense с помощью Nebula.js

Если у вас возникли проблемы с подключением к вашему сайту, щелкните знак вопроса, чтобы получить помощь (рядом с пунктом «Подключиться к движку» в пользовательском интерфейсе), вам необходимо передать URL-адрес Websocket для подключения к вашему сайту Qlik.

После этого выберите приложение, и запустится среда разработки Nebula.js! 🚀

Обратите внимание, что в этом руководстве мы будем использовать данные COVD -19. Я предварительно загрузил эти данные в qvf-файл, который можно найти в репозитории руководства на GitHub.

Теперь ваша среда разработки nebula должна работать на http://localhost:8000 и, по сути, представляет собой упрощенный пользовательский интерфейс Qlik, который вы можете использовать для разработки своего расширения. При первом запуске вы получите бесконечно работающий счетчик, который выглядит примерно так:

Не идеально. Nebula.js ищет ваше скомпилированное расширение, но пока ничего не может найти. Давайте исправим это, открыв новое окно терминала и перейдя в корень вашего проекта туманности…

cd nebula-react-starter

далее запускаем сборку

npm run build

Ура, теперь мы должны увидеть наше расширение в пользовательском интерфейсе Nebula.js…

Теперь мы запускаем наш сервер разработки ( через npm run start ) и перекомпилируем наше расширение при внесении изменений ( через npm run build ).

Вы также заметите, что у нас есть новая папка dist в наших файлах проекта, она содержит наш скомпилированный код расширения, который подбирает nebula.

Проверка файлов проекта

Прежде чем мы углубимся в программирование, давайте просмотрим файлы проекта, чтобы у вас было понимание кода:

data.js: содержит цель данных. Цель данных — это способ определить, где находятся динамические HyperCubeDef в свойствах универсального объекта. Для каждого целевого объекта данных вы можете указать дополнительные сведения, такие как максимальное/минимальное количество измерений и показателей.

extDefinition.js : он будет содержать определение нашей панели свойств, но пока должен быть пустым объектом.

object-properties.js : свойства нашего расширения, включая выборку данных HyperCube и те, которые мы хотим изменить с помощью нашей панели свойств.

root.jsx : это точка входа в реакцию. Мы экспортируем функцию рендеринга , которая содержит метод рендеринга React DOM. Он отображает JSX в переменную элемента , которая передается в функцию при вызове в index.js.

index.js : здесь отображается наше расширение. Чтобы отобразить что-то, что вам нужно для доступа к элементу DOM, которому назначена визуализация, вы можете сделать это, импортировав useElementфункцию. Это то, что мы передали нашему методу рендеринга ReactDOM, чтобы отобразить наш JSX в нашем расширении.

Начало работы с Recharts

Я бы порекомендовал вам прочитать руководство по началу работы с Rechart, прежде чем мы начнем, чтобы у вас было некоторое представление о библиотеке.

Мы начнем с установки библиотеки и импорта компонентов в наш проект.

В терминальном режиме

npm install recharts --save

Затем создайте новый файл с именем App.jsx в папке src . В этом компоненте мы импортируем и визуализируем диаграмму областей Recharts, используя некоторые фиктивные данные. Нам также нужно импортировать и отображать App.jsx в нашем файле root.jsx .

App.jsx

import React from 'react';
import { XAxis, YAxis, AreaChart, Area } from 'recharts';

const App = () => {

  const data = [
    {
      name: 'Page A', uv: 4000, pv: 2400, amt: 2400,
    },
    {
      name: 'Page B', uv: 3000, pv: 1398, amt: 2210,
    },
    {
      name: 'Page C', uv: 2000, pv: 9800, amt: 2290,
    },
    {
      name: 'Page D', uv: 2780, pv: 3908, amt: 2000,
    },
    {
      name: 'Page E', uv: 1890, pv: 4800, amt: 2181,
    },
    {
      name: 'Page F', uv: 2390, pv: 3800, amt: 2500,
    },
    {
      name: 'Page G', uv: 3490, pv: 4300, amt: 2100,
    },
  ];

  return (
    <AreaChart 
      width={500}
      height={400}
      data={data}
    >
      <XAxis dataKey="name" />
      <YAxis />
      <Area type="monotone" dataKey="uv" stackId="1" stroke="#8884d8" fill="#8884d8" />
      <Area type="monotone" dataKey="pv" stackId="1" stroke="#82ca9d" fill="#82ca9d" />
      <Area type="monotone" dataKey="amt" stackId="1" stroke="#ffc658" fill="#ffc658" />
    </AreaChart>
  );
};

export default App;

root.jsx

import ReactDOM from 'react-dom';
import React from 'react';
import App from './App'

export function render(element) {
  ReactDOM.render(<App />, element);
}

export function teardown(element) {
  ReactDOM.unmountComponentAtNode(element);
}

Теперь вы должны увидеть диаграмму, отображаемую в нашем пользовательском интерфейсе Nebula. Давайте уделим минуту, чтобы просмотреть код в App.jsx и понять следующие шаги для нашего расширения.

Обратите внимание, переменная данных, которую мы передаем в нашу диаграмму с областями, представляет собой массив объектов. Это отличается от структуры наших данных HyperCube, поэтому нам нужно будет манипулировать данными из нашего HyperCube, прежде чем передавать их в нашу диаграмму позже в этом руководстве.

Также обратите внимание, как мы отображаем данные на нашей диаграмме. Мы создаем отдельные компоненты Area для каждой области рендеринга. Мы хотим, чтобы наше расширение поддерживало несколько мер, поэтому нам нужно будет создать ряд этих компонентов области в зависимости от количества мер, созданных в нашем расширении.

Использование данных из нашего HyperCube

Теперь мы возьмем данные из нашего гиперкуба и вставим их в нашу диаграмму. Для этого мы будем использовать пользовательские хуки Nebula для получения данных из нашего движка.

Пользовательские хуки — это механизм повторного использования логики с отслеживанием состояния.

В index.js мы уже используем два таких хука: useElement (который получает HTMLElement, в который визуализируется эта визуализация) и useLayout (который получает макет универсального объекта, связанного с этой визуализацией).

Гиперкуб Qlik находится в макете универсального объекта, поэтому давайте сохраним его в переменной с именем hc:

const hc = layout.qHyperCube

Теперь ваш index.js должен выглядеть так, как показано ниже. Вы также можете консольно войти в hc и посмотреть на объект в консоли. Обратите внимание, что когда вы добавляете в расширение измерения и меры , данные в hc.qDataPages[0].qMatrix обновляются.

index.js

import { useElement, useLayout, useEffect } from '@nebula.js/stardust';
import properties from './object-properties';
import data from './data';
import { render } from './root';

export default function supernova() {
  return {
    qae: {
      properties,
      data,
    },
    component() {
      const el = useElement();
      const layout = useLayout();
      const hc = layout.qHyperCube;

      useEffect(() => {
        // do some heavy update
      }, [layout]);

      render(el, hc, { layout });
    },
  };
}

Если мы посмотрим на данные HyperCube более подробно, то увидим, что он возвращает массив массивов, который содержит объект для каждого измерения/меры, которые мы добавляем в наш HyperCube . Нам нужно преобразовать это в структуру данных, которую ожидает Recharts, чтобы заполнить диаграмму.

Как видно из примера данных выше, нам нужно создать массив объектов, где каждый объект содержит наши данные в парах ключ-значение. Прежде чем мы продолжим и сделаем это, давайте рассмотрим хуки React.

Объясняя Nebula / React Hooks

Прежде чем мы перейдем к коду, я хочу объяснить использование хуков в проектах Nebula и React. Хуки были представлены в React 16.8 и позволяют нам использовать состояние и другие функции React в функциональных компонентах.

Хуки имеют ряд преимуществ, включая упрощение повторного использования логики с сохранением состояния между компонентами и упрощение нашего кода React (нам больше не нужно использовать компоненты класса!)

Библиотека Nebula.js создала реализацию в стиле хуков для реализации повторно используемой логики.

В то время как реализация Nebula полностью настраиваема с помощью пользовательских хуков, концепция и правила очень похожи, настолько, что вы можете прочитать документацию по хукам React , чтобы понять, как использовать собственные хуки stardust.

На самом деле, Nebula.js поставляется со своими собственными хуками useStateuseEffect, которые выполняют те же функции, что и собственные хуки React. Все пользовательские хуки в библиотеке Nebula можно найти здесь (с префиксом use ).

Вернемся к нашему коду..

Чтобы манипулировать нашими данными из HyperCube, нам нужно использовать useEffectхук Nebula.js.

Переданная функция useEffectбудет запущена после того, как рендеринг будет зафиксирован на экране.

По умолчанию эффекты запускаются после каждого завершенного рендеринга, но вы можете активировать их только при изменении определенных значений .

В этом случае мы будем запускать функцию, которая перебирает наш HyperCube и реструктурирует данные.

Для начала мы собираемся принудительно выбрать одно измерение и две меры в нашем расширении . На данный момент это упростит код, и мы вернемся к этому в следующем руководстве.

Мы можем установить это в нашем файле data.js , который теперь должен выглядеть следующим образом:

data.js

export default {
  targets: [{
    path: '/qHyperCubeDef',
    dimensions: {
      min: 1,
      max: 1,
    },
    measures: {
      min: 2,
      max: 2,
    },
  }]
};

Мы также собираемся добавить следующий код в раздел компонентов нашей функции supernova в нашем файле index.js .

// state to store our data used in our chart
const [seriesData, setSeriesData] = useState([]);

//state to store our dimension name
const [dimKey, setDimKey] = useState([]);

//state to store our measure names
const [measKeys, setMeasKeys] = useState([]);

//Array that we will populate with restructured data
const series = [];

Мы создаем 3 набора начального состояния для хранения:

  • Реструктурированные данные, которые мы передадим на нашу диаграмму
  • Массив, содержащий имя нашего измерения
  • Массив, содержащий имена наших мер

На данный момент мы будем хранить имена наших измерений и показателей в виде массива, чтобы его было легче расширить, когда мы разрешим больше показателей.

Далее, в нашем useEffect, мы сопоставим наши данные HyperCube и создадим новый массив объектов. Обратите внимание, что в приведенном ниже коде мы сопоставляем hcData и помещаем объекты в массив с именем series , который содержит данные измерений и измерений в парах ключ-значение.

Затем мы помещаем эти данные вместе с именами измерений и показателей в состояние (строки 41–43 ниже). Наконец, мы добавляем эти данные в наш метод рендеринга и в root.jsx передаем их в наш компонент приложения.

index.js

import { useElement, useLayout, useEffect, useState } from '@nebula.js/stardust';
import properties from './object-properties';
import data from './data';
import { render } from './root';

export default function supernova() {
  return {
    qae: {
      properties,
      data,
    },
    component() {

      const el = useElement();
      const layout = useLayout();
      
      const [seriesData, setSeriesData] = useState([]);
      const [dimKey, setDimKey] = useState([]);
      const [measKeys, setMeasKeys] = useState([]);
      const hc = layout.qHyperCube;
      const series = [];

      useEffect(() => {

        const hcData =  hc.qDataPages[0].qMatrix;

        if (hcData.length === 0) return;

        const dim1 = hc.qDimensionInfo[0].qFallbackTitle;
        const meas1 = hc.qMeasureInfo[0].qFallbackTitle;
        const meas2 = hc.qMeasureInfo[1].qFallbackTitle;

        hcData.map(e => (
          series.push({
            [dim1]: e[0].qText,
            [meas1]: e[1].qText,
            [meas2]: e[2].qText,
          })
        ));

        setDimKey([dim1]);
        setMeasKeys([meas1, meas2]);
        setSeriesData(series);
      }, [layout]);

      render(el, seriesData, dimKey, measKeys, { layout });
    },
  };
}

root.jsx

import ReactDOM from 'react-dom';
import React from 'react';
import App from './App'

export function render(element, seriesData, dimKey, measKeys) {
  ReactDOM.render(<App data={seriesData} dimKey={dimKey} measKeys={measKeys} />, element);
}

export function teardown(element) {
  ReactDOM.unmountComponentAtNode(element);
}

Итак, теперь у нас есть все данные, которые нам нужны в App.jsx . Теперь мы можем передать это в нашу диаграмму. Если вы помните ранее в этом руководстве, мы заметили, что нам нужно визуализировать компонент AreaChart для каждой визуализируемой линии/области. Для этого нам нужно сопоставить наши ключи измерений.

Мы также создали массив цветов для окрашивания наших компонентов Area.

import React from 'react';
import { XAxis, YAxis, AreaChart, Area } from 'recharts';

const App = ({ data, dimKey, measKeys }) => {

  const colors = ["#8884d8", "#82ca9d"]

  return (
    <AreaChart 
      width={500}
      height={400}
      data={data}
    >
      <XAxis dataKey={dimKey[0]} />
      <YAxis />
      {measKeys.map((m, i) => (
        <Area type="monotone" dataKey={m} stackId="1" stroke={colors[i]} fill={colors[i]} />
      ))}
    </AreaChart>
  );
};

export default App;

Теперь ваше расширение должно выглядеть примерно так, как показано ниже.

Делаем нашу диаграмму отзывчивой

Мы закончим написание кода в части 1 этого руководства, сделав нашу диаграмму адаптивной. К счастью, у Recharts есть хороший и простой пример этого на своем сайте, который можно найти здесь .

Они предоставляют компонент ResonsiveContainer , который мы можем обернуть вокруг нашей диаграммы, чтобы она расширялась до размера своего родительского контейнера. Мы можем импортировать и использовать это в App.jsx , как показано ниже.

import React from 'react';
import { XAxis, YAxis, AreaChart, Area, ResponsiveContainer } from 'recharts';

const App = ({ data, dimKey, measKeys }) => {

  const colors = ["#8884d8", "#82ca9d"]

  return (
    <div style={{ width: '100%', height: '100%' }}>
      <ResponsiveContainer>
        <AreaChart 
          width={500}
          height={400}
          data={data}
        >
          <XAxis dataKey={dimKey[0]} />
          <YAxis />
          {measKeys.map((m, i) => (
            <Area type="monotone" dataKey={m} stackId="1" stroke={colors[i]} fill={colors[i]} />
          ))}
        </AreaChart>
      </ResponsiveContainer>
    </div>
  );
};

export default App;

Тестирование расширения в Qlik Sense

Наконец, мы быстро импортируем наше расширение в Qlik Sense и убедимся, что все работает должным образом.

Запустите приведенную ниже команду в своем терминале

npm run sense

Это поместит наше расширение в новую папку в нашем репозитории. Затем мы можем заархивировать это и импортировать на наш сайт Qlik Sense.

И вот, у нас есть рабочее расширение, созданное с использованием Nebula.js и React!

Использованные материалы при создании статьи

0 0 голосов
Рейтинг статьи

Подписаться
Уведомление о
guest
0 комментариев
Встроенная Обратная Связь
Просмотр всех комментариев
0
Оставьте, пожалуйста, комментарий!x