loadIssues()

in modules/services/keepRight.js [289:412]


  loadIssues(projection) {
    const options = {
      format: 'geojson',
      ch: _krRuleset
    };

    // determine the needed tiles to cover the view
    const proj = new Projection().transform(projection.transform()).dimensions(projection.clipExtent());
    const tiles = tiler.getTiles(proj).tiles;

    // abort inflight requests that are no longer needed
    abortUnwantedRequests(_cache, tiles);

    // issue new requests..
    tiles.forEach(tile => {
      if (_cache.loadedTile[tile.id] || _cache.inflightTile[tile.id]) return;

      const [ left, top, right, bottom ] = tile.wgs84Extent.rectangle();
      const params = Object.assign({}, options, { left, bottom, right, top });
      const url = `${_krUrlRoot}/export.php?` + utilQsString(params);
      const controller = new AbortController();

      _cache.inflightTile[tile.id] = controller;

      d3_json(url, { signal: controller.signal })
        .then(data => {
          delete _cache.inflightTile[tile.id];
          _cache.loadedTile[tile.id] = true;
          if (!data || !data.features || !data.features.length) {
            throw new Error('No Data');
          }

          data.features.forEach(feature => {
            const {
              properties: {
                error_type: itemType,
                error_id: id,
                comment = null,
                object_id: objectId,
                object_type: objectType,
                schema,
                title
              }
            } = feature;
            let {
              geometry: { coordinates: loc },
              properties: { description = '' }
            } = feature;

            // if there is a parent, save its error type e.g.:
            //  Error 191 = "highway-highway"
            //  Error 190 = "intersections without junctions"  (parent)
            const issueTemplate = _krData.errorTypes[itemType];
            const parentIssueType = (Math.floor(itemType / 10) * 10).toString();

            // try to handle error type directly, fallback to parent error type.
            const whichType = issueTemplate ? itemType : parentIssueType;
            const whichTemplate = _krData.errorTypes[whichType];

            // Rewrite a few of the errors at this point..
            // This is done to make them easier to linkify and translate.
            switch (whichType) {
              case '170':
                description = `This feature has a FIXME tag: ${description}`;
                break;
              case '292':
              case '293':
                description = description.replace('A turn-', 'This turn-');
                break;
              case '294':
              case '295':
              case '296':
              case '297':
              case '298':
                description = `This turn-restriction~${description}`;
                break;
              case '300':
                description = 'This highway is missing a maxspeed tag';
                break;
              case '411':
              case '412':
              case '413':
                description = `This feature~${description}`;
                break;
            }

            // move markers slightly so it doesn't obscure the geometry,
            // then move markers away from other coincident markers
            let coincident = false;
            do {
              // first time, move marker up. after that, move marker right.
              let delta = coincident ? [0.00001, 0] : [0, 0.00001];
              loc = vecAdd(loc, delta);
              let bbox = new Extent(loc).bbox();
              coincident = _cache.rtree.search(bbox).length;
            } while (coincident);

            let d = new QAItem(loc, this, itemType, id, {
              comment,
              description,
              whichType,
              parentIssueType,
              severity: whichTemplate.severity || 'error',
              objectId,
              objectType,
              schema,
              title
            });

            d.replacements = tokenReplacements(d);

            _cache.data[id] = d;
            _cache.rtree.insert(encodeIssueRtree(d));
          });

          dispatch.call('loaded');
        })
        .catch(() => {
          delete _cache.inflightTile[tile.id];
          _cache.loadedTile[tile.id] = true;
        });

    });
  },