protected getDataset()

in powerbi-visual-builder/src_visual/visual.ts [261:586]


    protected getDataset(
      dataView: DataView
    ): {
      dataset: CharticulatorContainer.Dataset.Dataset;
      rowInfo: Map<
        CharticulatorContainer.Dataset.Row,
        { highlight: boolean; index: number; granularity: string }
      >;
    } {
      if (
        !dataView ||
        !dataView.categorical ||
        !dataView.categorical.categories ||
        !dataView.categorical.categories[0]
      ) {
        return null;
      }
      const categorical = dataView.categorical;
      const categories = categorical.categories;
      const valueColumns = categorical.values;

      // Match columns
      const columnToValues: {
        [name: string]: {
          values: CharticulatorContainer.Specification.DataValue[];
          highlights: boolean[];
        };
      } = {};
      const defaultTable = this.getDefaultTable(this.template);
      let columns = defaultTable.columns.filter(
        col => !col.metadata.isRaw
      ) as PowerBIColumn[];
      for (const chartColumn of columns) {
        let found = false;
        if (valueColumns != null) {
          for (const powerBIColumn of valueColumns) {
            if (powerBIColumn.source.roles[chartColumn.powerBIName]) {
              const [converted, raw] = this.mapColumns(
                powerBIColumn,
                chartColumn.type,
                chartColumn.metadata.format
              );
              columnToValues[
                chartColumn.powerBIName || refineColumnName(chartColumn.name)
              ] = converted;
              if (raw && !chartColumn.metadata.isRaw) {
                columnToValues[
                  `${chartColumn.powerBIName ||
                    refineColumnName(chartColumn.name)}${rawColumnPostFix}`
                ] = raw;
              }
              found = true;
            }
          }
        }
        for (const powerBIColumn of categories.reverse()) {
          // reverse - to take the latest column (if drill down was enabled)
          if (
            powerBIColumn.source.roles[
              chartColumn.powerBIName || chartColumn.name
            ] &&
            !columnToValues[chartColumn.powerBIName || chartColumn.name]
          ) {
            const [converted, raw] = this.mapColumns(
              powerBIColumn,
              chartColumn.type,
              chartColumn.metadata && chartColumn.metadata.format
            );
            columnToValues[
              chartColumn.powerBIName || refineColumnName(chartColumn.name)
            ] = converted;
            if (raw && !chartColumn.metadata.isRaw) {
              columnToValues[
                `${chartColumn.powerBIName ||
                  refineColumnName(chartColumn.name)}${rawColumnPostFix}`
              ] = raw;
            }
            found = true;
          }
        }
        if (!found) {
          return null;
        }
      }
      const defaultTableRawColumns = defaultTable.columns
        // add powerBIName to raw columns
        .map((column: PowerBIColumn) => {
          if (!column.powerBIName) {
            column.powerBIName = refineColumnName(column.name);
          }
          return column;
        })
        .filter(col => !col.metadata.isRaw)
        .filter(rawColumnFilter(defaultTable.columns))
        .map(rawColumnMapper);
      columns = defaultTable.columns = defaultTable.columns.concat(
        defaultTableRawColumns
      ) as PowerBIColumn[];

      const linksTable = this.getLinksTable(this.template);
      const powerBILinkColumns = dataView.categorical.categories;
      let chartLinks =
        linksTable &&
        (linksTable.columns.filter(
          col => !col.metadata.isRaw
        ) as PowerBIColumn[]);

      if (chartLinks && powerBILinkColumns) {
        for (const chartColumn of chartLinks) {
          for (const powerBIColumn of powerBILinkColumns) {
            if (powerBIColumn.source.roles[chartColumn.powerBIName]) {
              const [converted, raw] = this.mapColumns(
                powerBIColumn,
                chartColumn.type,
                chartColumn.metadata && chartColumn.metadata.format
              );
              columnToValues[
                chartColumn.powerBIName || chartColumn.name
              ] = converted;
              if (raw && !chartColumn.metadata.isRaw) {
                columnToValues[
                  `${chartColumn.powerBIName ||
                    refineColumnName(chartColumn.name)}${rawColumnPostFix}`
                ] = raw;
              }
            }
          }
        }

        const linksTableRawColumns = linksTable.columns
          .filter(rawColumnFilter(linksTable.columns))
          .map(rawColumnMapper);
        chartLinks = linksTable.columns = linksTable.columns.concat(
          linksTableRawColumns
        ) as PowerBIColumn[];
      }

      const tooltipsTable = this.getTooltipsTable(this.template);
      const tooltipsTableColumns = [
        ...categorical.categories.filter(
          cat => cat.source.roles.powerBITooltips
        ),
        ...(categorical.values
          ? categorical.values.filter(cat => cat.source.roles.powerBITooltips)
          : [])
      ];

      if (tooltipsTable && tooltipsTableColumns) {
        const type =
          (tooltipsTable.columns.length && tooltipsTable.columns[0].type) ||
          CharticulatorContainer.Specification.DataType.String;
        const metadata = (tooltipsTable.columns.length &&
          tooltipsTable.columns[0].metadata) || {
          kind: "categorical"
        };
        tooltipsTable.columns = [];
        tooltipsTableColumns.forEach(powerBIColumn => {
          if (!columnToValues[powerBIColumn.source.displayName]) {
            const [converted, raw] = this.mapColumns(powerBIColumn, type);
            columnToValues[powerBIColumn.source.displayName] = converted;
            if (raw) {
              columnToValues[
                `${refineColumnName(
                  powerBIColumn.source.displayName
                )}${rawColumnPostFix}`
              ] = raw;
            }
          }
          tooltipsTable.columns.push({
            displayName: powerBIColumn.source.displayName,
            name: powerBIColumn.source.displayName,
            metadata,
            type
          });
        });
      }
      const tooltips =
        tooltipsTable && (tooltipsTable.columns as PowerBIColumn[]);

      const rowInfo = new Map<
        CharticulatorContainer.Dataset.Row,
        { highlight: boolean; index: number; granularity: string }
      >();

      const uniqueRows = new Set<string>();

      const rowIdentity = categories.filter(
        category => category.source.roles.primarykey
      );
      const rows = categories[0].values
        .map((categoryValue, i) => {
          const obj: CharticulatorContainer.Dataset.Row = {
            _id: /*"ID" +*/ i.toString()
          };
          let rowHasHighlightedColumn = false;
          let rowHash = rowIdentity.length
            ? rowIdentity.map(idRow => idRow.values[i]).toString()
            : "";
          for (const column of columns) {
            const valueColumn = columnToValues[column.powerBIName];
            if (!valueColumn) {
              return null;
            }
            let value = valueColumn.values[i];

            if (value == null) {
              if (
                columns.find(col => col.name === column.name).metadata.kind ===
                "numerical"
              ) {
                value = 0;
              } else {
                return null;
              }
            }
            obj[column.powerBIName] = value;
            rowHash += (value || "null").toString();
            // if one value column has highlights
            if (valueColumn.highlights[i]) {
              rowHasHighlightedColumn = true;
            }
          }

          const catDate = categoryValue as Date;
          let granularity = categoryValue.valueOf().toString();

          // Try to do some extra formatting for dates
          if (catDate && typeof catDate.toDateString === "function") {
            granularity = catDate.toDateString();
          }

          if (!uniqueRows.has(rowHash)) {
            uniqueRows.add(rowHash);
            rowInfo.set(obj, {
              highlight: rowHasHighlightedColumn,
              index: i,
              granularity
            });
            return obj;
          } else {
            return null;
          }
        })
        .filter(x => x != null);

      const dataset: CharticulatorContainer.Dataset.Dataset = {
        name: "Dataset",
        tables: [
          {
            name: defaultTable.name,
            columns: columns.map(column => {
              return {
                displayName: this.getUserColumnName(
                  dataView,
                  column.powerBIName
                ),
                name: column.powerBIName,
                type: column.type,
                metadata: column.metadata
              };
            }),
            rows
          },
          chartLinks &&
            powerBILinkColumns && {
              name: linksTable.name,
              columns:
                powerBILinkColumns.length >= 2
                  ? chartLinks.map(column => {
                      return {
                        displayName: this.getUserColumnName(
                          dataView,
                          column.powerBIName
                        ),
                        name: column.powerBIName,
                        type: column.type,
                        metadata: column.metadata
                      };
                    })
                  : null,
              rows: categories[0].values
                .map((source, index) => {
                  const obj: CharticulatorContainer.Dataset.Row = {
                    _id: index.toString()
                  };
                  for (const column of chartLinks) {
                    const valueColumn =
                      columnToValues[column.powerBIName || column.name];
                    if (valueColumn) {
                      const value = valueColumn.values[index];
                      obj[column.powerBIName || column.name] = value;
                    }
                  }
                  if (obj.source_id && obj.target_id) {
                    return obj;
                  } else {
                    return null;
                  }
                })
                .filter(row => row)
            },
          tooltips &&
            tooltipsTableColumns && {
              name: powerBITooltipsTablename,
              columns: tooltipsTable ? tooltipsTable.columns : null,
              rows: categories[0].values
                .map((source, index) => {
                  const obj = {
                    _id: index.toString()
                  };
                  for (const column of tooltips) {
                    const valueColumn =
                      columnToValues[column.powerBIName || column.name];
                    if (valueColumn) {
                      const value = valueColumn.values[index];
                      obj[column.powerBIName || column.name] = value;
                    }
                  }
                  return obj;
                })
                .filter(row => row)
            }
        ].filter(table => table && table.columns)
      };
      return { dataset, rowInfo };
    }