public render()

in src/app/views/panels/legend_creator.tsx [45:331]


  public render() {
    return (
      <div className="charticulator__link-type-table">
        <div className="el-row">
          {/* <h2>Legend type:</h2> */}
          <Label>{strings.legendCreator.legendType}</Label>
          <PanelRadioControl
            options={["columnValues", "columnNames"]}
            labels={["Column values", "Column names"]}
            value={this.state.legendDataSource}
            onChange={(newValue: "columnNames" | "columnValues") =>
              this.setState({ legendDataSource: newValue })
            }
            showText={true}
          />
        </div>
        {this.state.legendDataSource == "columnValues" ? (
          <div>
            {/* <h2>Connect by:</h2> */}
            <Label>{strings.legendCreator.connectBy}</Label>
            <div className="el-row">
              <DataFieldSelector
                multiSelect={false}
                ref={(e) => (this.groupBySelector = e)}
                kinds={[
                  Specification.DataKind.Categorical,
                  Specification.DataKind.Numerical,
                  Specification.DataKind.Temporal,
                  Specification.DataKind.Ordinal,
                ]}
                datasetStore={this.store}
                nullDescription="(select column to create legend)"
              />
            </div>
          </div>
        ) : (
          <div>
            {/* <h2>Connect by:</h2> */}
            <Label>{strings.legendCreator.connectBy}</Label>
            <div className="el-row">
              <DataFieldSelector
                multiSelect={true}
                ref={(e) => (this.groupBySelector = e)}
                kinds={[
                  Specification.DataKind.Categorical,
                  Specification.DataKind.Numerical,
                  Specification.DataKind.Temporal,
                  Specification.DataKind.Ordinal,
                ]}
                datasetStore={this.store}
                nullDescription="(select column names to create legend)"
              />
            </div>
          </div>
        )}
        <div className="el-row">
          <PrimaryButton
            text={strings.legendCreator.createLegend}
            title={strings.legendCreator.createLegend}
            // eslint-disable-next-line
            onClick={() => {
              const columns = this.groupBySelector
                ? this.groupBySelector.value
                  ? this.groupBySelector.props.multiSelect
                    ? (this.groupBySelector.value as DataFieldSelectorValue[])
                    : [this.groupBySelector.value as DataFieldSelectorValue]
                  : []
                : [];

              let attributeType: AttributeType = AttributeType.Color;

              if (this.state.legendDataSource === "columnNames") {
                const valueType: Specification.DataType =
                  Specification.DataType.String;
                const valueKind: Specification.DataKind =
                  Specification.DataKind.Categorical;
                const outputType: Specification.AttributeType =
                  Specification.AttributeType.Color;

                const scaleClassID = Prototypes.Scales.inferScaleType(
                  valueType,
                  valueKind,
                  outputType
                );

                const tableName = this.store.dataset.tables.find(
                  (t) => t.type === TableType.Main
                ).name;
                const table = this.store.chartManager.dataflow.getTable(
                  tableName
                );

                const data = (columns as any[])
                  .map((ex) => {
                    const index = table.columns.findIndex(
                      (col) => col.name == ex.columnName
                    );
                    return `get(get(${ex.table}.columns, ${index}), "displayName")`;
                  })
                  .filter((v) => v != null);

                const expression = `list(${(data as any[])
                  .map((ex) => {
                    return `${ex}`;
                  })
                  .join(",")})`;

                const parsedExpression = this.store.chartManager.dataflow.cache.parse(
                  expression
                );
                const expressionData = parsedExpression.getValue(table);

                const newScale = this.store.chartManager.createObject(
                  scaleClassID
                ) as Specification.Scale;
                newScale.properties.name = this.store.chartManager.findUnusedName(
                  "Scale"
                );
                newScale.inputType = valueType;
                newScale.outputType = outputType;
                this.store.chartManager.addScale(newScale);
                const scaleClass = this.store.chartManager.getClassById(
                  newScale._id
                ) as Prototypes.Scales.ScaleClass;

                scaleClass.inferParameters(
                  expressionData as Specification.DataValue[],
                  {}
                );

                const newLegend = this.store.chartManager.createObject(
                  `legend.custom`
                ) as Specification.ChartElement;
                newLegend.properties.scale = newScale._id;
                newLegend.mappings.x = {
                  type: MappingType.parent,
                  parentAttribute: "x2",
                } as Specification.ParentMapping;
                newLegend.mappings.y = {
                  type: MappingType.parent,
                  parentAttribute: "y2",
                } as Specification.ParentMapping;
                this.store.chartManager.addChartElement(newLegend);
                this.store.chartManager.chart.mappings.marginRight = {
                  type: MappingType.value,
                  value: 100,
                } as Specification.ValueMapping;

                const mappingOptions = {
                  type: MappingType.scale,
                  table: tableName,
                  expression,
                  valueType,
                  scale: newScale._id,
                  allowSelectValue: true,
                } as Specification.ScaleMapping;

                if (!newLegend.mappings) {
                  newLegend.mappings = {};
                }
                newLegend.mappings.mappingOptions = mappingOptions;
              } else {
                const kind = (this.groupBySelector
                  .value as DataFieldSelectorValue).metadata.kind;
                switch (kind) {
                  case DataKind.Numerical:
                  case DataKind.Temporal:
                    attributeType = AttributeType.Number;
                    break;
                  case DataKind.Ordinal:
                    attributeType = AttributeType.Text;
                    break;
                }
              }

              if (this.state.legendDataSource === "columnValues") {
                const aggregation = Expression.getDefaultAggregationFunction(
                  columns[0].type,
                  columns[0].metadata?.kind
                );
                const aggregatedExpression = Expression.functionCall(
                  aggregation,
                  Expression.parse(columns[0].expression)
                ).toString();

                const table = columns[0].table;
                const inferred = this.store.scaleInference(
                  { chart: { table } },
                  {
                    expression: aggregatedExpression,
                    valueType: columns[0].type,
                    valueKind: columns[0].metadata.kind,
                    outputType: attributeType,
                    hints: {},
                  }
                );

                const scaleObject = getById(
                  this.store.chartManager.chart.scales,
                  inferred
                );
                let newLegend: Specification.Object<Specification.ObjectProperties> = null;
                switch (scaleObject.classID) {
                  case "scale.categorical<string,color>":
                    newLegend = this.store.chartManager.createObject(
                      `legend.categorical`
                    ) as Specification.ChartElement;
                    newLegend.properties.scale = inferred;
                    newLegend.mappings.x = {
                      type: MappingType.parent,
                      parentAttribute: "x2",
                    } as Specification.ParentMapping;
                    newLegend.mappings.y = {
                      type: MappingType.parent,
                      parentAttribute: "y2",
                    } as Specification.ParentMapping;
                    this.store.chartManager.addChartElement(newLegend);
                    this.store.chartManager.chart.mappings.marginRight = {
                      type: MappingType.value,
                      value: 100,
                    } as Specification.ValueMapping;
                    break;
                  case "scale.linear<number,color>":
                  case "scale.linear<integer,color>":
                    newLegend = this.store.chartManager.createObject(
                      `legend.numerical-color`
                    ) as Specification.ChartElement;
                    newLegend.properties.scale = inferred;
                    newLegend.mappings.x = {
                      type: MappingType.parent,
                      parentAttribute: "x2",
                    } as Specification.ParentMapping;
                    newLegend.mappings.y = {
                      type: MappingType.parent,
                      parentAttribute: "y2",
                    } as Specification.ParentMapping;
                    this.store.chartManager.addChartElement(newLegend);
                    this.store.chartManager.chart.mappings.marginRight = {
                      type: MappingType.value,
                      value: 100,
                    } as Specification.ValueMapping;
                    break;
                  case "scale.linear<number,number>":
                  case "scale.linear<integer,number>":
                    newLegend = this.store.chartManager.createObject(
                      `legend.numerical-number`
                    ) as Specification.ChartElement;
                    newLegend.properties.scale = inferred;
                    newLegend.mappings.x1 = {
                      type: MappingType.parent,
                      parentAttribute: "x1",
                    } as Specification.ParentMapping;
                    newLegend.mappings.y1 = {
                      type: MappingType.parent,
                      parentAttribute: "y1",
                    } as Specification.ParentMapping;
                    newLegend.mappings.x2 = {
                      type: MappingType.parent,
                      parentAttribute: "x1",
                    } as Specification.ParentMapping;
                    newLegend.mappings.y2 = {
                      type: MappingType.parent,
                      parentAttribute: "y2",
                    } as Specification.ParentMapping;
                    this.store.chartManager.addChartElement(newLegend);
                }

                newLegend.mappings.mappingOptions = {
                  type: MappingType.scale,
                  table,
                  expression: aggregatedExpression,
                  valueType: columns[0].type,
                  scale: inferred,
                } as Specification.ScaleMapping;
              }

              this.store.solveConstraintsAndUpdateGraphics();
              this.props.onFinish();
            }}
          />
          {this.state.errorReport ? (
            <span>{this.state.errorReport}</span>
          ) : null}
        </div>
      </div>
    );
  }