Mark-a-Spot - это дистрибутив Drupal для краудмэппинга и отслеживания общественных проблем. Он использует функции визуализации карты и мониторинга данных, которые в более ранних версиях были тепловыми картами, картами запросов на обслуживание и простыми представлениями агрегирования, подсчитывающими контент по категории и статусу.

Обсуждение фреймворка JavaScript для пользовательского интерфейса администратора Drupal побудило меня поиграть с Vue.js и реализовать больше функций визуализации для краудсорсинговых данных. В этой короткой статье я расскажу, как я получил все это, работая с vue-chartjs, оболочкой для Charts.js.

Желаемый результат

Установка 8.4.x dev ветки Mark-a-Spot теперь представляет отдельный раздел сайта для визуализации данных и один раздел для проверки 311 запросов на обслуживание в контексте местоположения.

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

Компоненты

Блоки

Шаблон веточки каждого блока состоит всего из нескольких строк разметки:

<div class="trend_organisations">
    <doughnut-organisations></doughnut-organisations>
</div>

Плагин блока подключает только необходимые библиотеки JavaScript:

class MarkaspotTrendFilterBlock extends BlockBase implements BlockPluginInterface {

  /**
   * {@inheritdoc}
   */
  public function build() {

    $config = $this->getConfiguration();

    return [
      '#theme' => 'markaspot_trend_filter_block',
      '#filter_intro' => $config['filter_intro'],
      '#attached' => [
        'library' => [
          'markaspot_trend/vue',
          'markaspot_trend/vue-router',
          'markaspot_trend/trend',
          'markaspot_trend/filter',
        ],
      ],
    ];
  }

Библиотеки

Drupal также должен знать источник внешних библиотек. Мне потребовались vue, vue-charts.js, vue-router и axios, клиентская библиотека http для использования остальных представлений Drupal.

В первой версии мы загружаем все необходимые библиотеки, скомпилированные через CDN с unpg.com, и помещаем их в markaspot_trend.libraries.yml модуля:

axios:
  remote: https://unpkg.com/axios/dist/axios.min.js
  version: 0.17.1
  license:
    name: MIT
  js:
    https://unpkg.com/axios/dist/axios.min.js: { type: external, minified: true }

vue-router:
  remote: https://unpkg.com/vue-router/dist/vue-router.min.js
  version: 3.0.1
  license:
    name: MIT
  js:
   https://unpkg.com/vue-router/dist/vue-router.min.js: { type: external, minified: true }

vue:
  remote: https://unpkg.com/[email protected]/dist/vue.js
  version: 2.5.9
  license:
    name: MIT
  js:
    https://unpkg.com/[email protected]/dist/vue.js: { type: external, minified: true }

Пользовательский код

Каждому блоку принадлежит отдельный js-файл. Он отображает диаграммы, следит за изменениями маршрутизатора, передавая аргументы из блока фильтра.

Как только блок фильтра изменяет маршрут vue, свойство watch запускает новый запрос к представлениям Drupal. В основном все происходит в этих нескольких строках каждого js файла блоков. Если у кого-то есть предложения по общему рефакторингу, дайте мне знать.

watch: {
  '$route'(to, from){
    this.getChartData();
  }
},
methods: {
getChartData: function (param) {
  param = (param) ? param : this.$route.path;
  let baseUrl = settings.path.baseUrl;
  let url = baseUrl + 'georeport/stats/organisations' + param;

  let parent = this;
  axios.get(url, {}).then(function (response) {
    let stats = response.data;

    let chartData = {
      datasets: [parent.getStats(stats)],
      labels: parent.getLabels(stats)
    };
    if (parent.$data._chart) {
      parent.$data._chart.destroy();
    }
    parent.renderChart(chartData, parent.options);

  }).catch(function (error) {
    console.log(error);
  });
  return this.chartData;

},

Результат всех блоков вместе с некоторыми эффектами на компоненте карты Mark-a-Spot должен быть загружен в левой части этой статьи.

Код еще не полностью переработан и все еще представляет собой смесь jQuery и vue.js. Итак, работа продолжается. В будущих версиях должно быть некоторое кеширование для повторяющихся запросов, таких как получение меток терминов.