UNPKG

@devgateway/dvz-ui-react

Version:

A modular, embeddable React component library for data visualization and UI, built with TypeScript. Provides reusable components for charts, maps, dashboards, and more, with built-in support for internationalization and Redux integration.

463 lines (462 loc) 18.5 kB
import { jsx as Z } from "react/jsx-runtime"; import "react"; import pt from "./BaseLayer.js"; import ct from "../data/DataProvider.js"; import ut from "../data/DataConsumer.js"; import * as M from "d3"; import { injectIntl as dt } from "react-intl"; import Y from "./BreaksStyles.js"; import ot from "./GradientColors.js"; const W = (D) => D ? D.toString().replace(/ /g, "_") : "", C = (D) => D ? "pattern_" + W(D) : ""; class ht extends pt { constructor() { super(), this.state = { geoJson: null, json: null }, this.getTooltipVariables = this.getTooltipVariables.bind(this), this.resize = this.resize.bind(this), this.createLayer = this.createLayer.bind(this), this.createCentroids = this.createCentroids.bind(this), this.createPatterns = this.createPatterns.bind(this), this.createPaths = this.createPaths.bind(this); } createLayer(e) { const p = this.joinData(e, this.props.app, this.props.featureJoinAttribute, this.props.data, this.props.measures, this.props.patternDiscriminator); this.createDataLayer(p); } resize() { const { markerLabelSize: e, markFillColor: p, markBorderColor: v, markSizeScale: i, measures: u, data: h, breaks: c, gradientScheme: F, gradientReverse: l } = this.props, d = new Y({ breaks: c, defaultFillColor: p, defaultBorderColor: v, defaultSize: i }); new ot({ data: h.children, measure: u[0], defaultFillColor: p, gradientScheme: F, gradientReverse: l }); const s = this.props.transform ? this.props.transform.k : 1; this.g.selectAll(".centroids .point").attr("r", (n) => d.getSize(n.properties._value) * 1 / s), this.g.selectAll(".centroids .point-label").attr("font-size", (n) => e * (1 / s) + "px"); } getTooltipVariables(e) { const { apiJoinAttribute: p } = this.props; return e.properties._value ? { ...e.properties, meta: { [p]: e.properties.meta ? e.properties.meta.value : "", ...e.properties.meta, value: e.properties._value } } : {}; } createDataLayer(e) { const { app: p, svg: v, format: i, id: u, file: h, path: c, onLayerCreated: F, labelFilter: l = [], labelField: d, labelFontSize: s, labelColor: n, fillColor: L, borderColor: f, tooltip: x, markFillColor: g, markLabelColor: P, markBorderColor: J, markSizeScale: N, markerLabelSize: H, featureJoinAttribute: tt, apiJoinAttribute: K, measures: I, editing: et, data: z, patternDiscriminator: k, patternDiscriminatorLabel: Q, breaks: $, gradientScheme: G, gradientReverse: E, patterns: w, projection: rt, useBreaks: X, useGradients: V, useCentroidPoint: U, usePattern: j, waitForFilters: at, intl: q, patternsVisible: B = !0, togglePatterns: R, colorLayerVisible: O = !0, visible: it } = this.props; if (this.gRef && this.gRef.current) { debugger; this.g = M.select(this.gRef.current.parentNode), this.g.attr("class", "base-layer"); const S = e.features.filter((A) => A.properties._value != null); this.createPaths(e), U || this.createColors(S), j && this.createPatterns(e), d != "none" && this.createLabels(e), U && this.createCentroids(S); } } createColors(e) { const { app: p, svg: v, format: i, id: u, file: h, path: c, onLayerCreated: F, labelFilter: l = [], labelField: d, labelFontSize: s, labelColor: n, fillColor: L, borderColor: f, tooltip: x, markFillColor: g, markLabelColor: P, markBorderColor: J, markSizeScale: N, markerLabelSize: H, featureJoinAttribute: tt, apiJoinAttribute: K, measures: I, editing: et, data: z, patternDiscriminator: k, patternDiscriminatorLabel: Q, breaks: $, gradientScheme: G, gradientReverse: E, patterns: w, projection: rt, useBreaks: X, useGradients: V, useCentroidPoint: U, usePattern: j, waitForFilters: at, intl: q, patternsVisible: B = !0, togglePatterns: R, colorLayerVisible: O = !0, visible: it } = this.props, S = new Y({ breaks: $, defaultFillColor: g, defaultBorderColor: J, defaultSize: N }), A = new ot({ data: z.children, measure: I[0], defaultFillColor: g, gradientScheme: G, gradientReverse: E }); if (this.g) { debugger; this.g.selectAll("path").attr("fill", (o) => !o || !o.properties || !o.properties._value ? L : V ? A.getColor(o.properties._value) : S.getColor(o.properties._value)).attr("stroke", f).attr("id", "state-borders").attr("d", c).on("mouseenter", (o, b) => { b.properties._value && this.showToolTip(x, this.getTooltipVariables(b), V ? A.getColor(b.properties._value) : S.getColor(b.properties._value), b); }).on("mouseleave", (o) => { this.hiddenToolTip(o); }).on("mousemove", (o) => { this.moveToolTip(o); }), O || this.g.selectAll(".borders").style("fill", this.props.fillColor), this.g.attr("transform", this.props.transform); } } createCentroids(e) { const { app: p, svg: v, format: i, id: u, file: h, path: c, onLayerCreated: F, labelFilter: l = [], labelField: d, labelFontSize: s, labelColor: n, fillColor: L, borderColor: f, tooltip: x, markFillColor: g, markLabelColor: P, markBorderColor: J, markSizeScale: N, markerLabelSize: H, featureJoinAttribute: tt, apiJoinAttribute: K, measures: I, editing: et, data: z, patternDiscriminator: k, patternDiscriminatorLabel: Q, breaks: $, gradientScheme: G, gradientReverse: E, patterns: w, projection: rt, useBreaks: X, useGradients: V, useCentroidPoint: U, usePattern: j, waitForFilters: at, intl: q, patternsVisible: B = !0, togglePatterns: R, colorLayerVisible: O = !0, visible: it } = this.props, S = new Y({ breaks: $, defaultFillColor: g, defaultBorderColor: J, defaultSize: N }), A = new ot({ data: z.children, measure: I[0], defaultFillColor: g, gradientScheme: G, gradientReverse: E }); if (this.g) { const o = { style: i.style === "compacted" ? "decimal" : i.style, notation: i.style === "compacted" ? "compact" : "standard", currency: i.currency, minimumFractionDigits: parseInt(i.minimumFractionDigits), maximumFractionDigits: parseInt(i.maximumFractionDigits) }, b = this.props.transform ? this.props.transform.k : 1; this.g.selectAll(".centroids").remove(); const m = this.g.selectAll("centroids").data(e).enter().append("g").attr("class", "centroids"); m.append("circle").attr("fill", (a) => V ? A.getColor(a.properties._value) : S.getColor(a.properties._value, !0)).attr("stroke", J).attr("class", "point").attr("stroke-width", 2).style("vector-effect", "non-scaling-stroke").attr("cx", (a) => c.centroid(a)[0]).attr("cy", (a) => c.centroid(a)[1]).attr("r", (a) => S.getSize(a.properties._value) * 1 / b).on("mouseenter", (a, t) => { if (t.properties._value) { const y = { ...t.properties, meta: { [K]: t.properties.meta ? t.properties.meta.value : "", ...t.properties.meta, value: t.properties._value } }; this.showToolTip(x, y, V ? A.getColor(t.properties._value) : S.getColor(t.properties._value)); } }).on("mouseleave", (a) => { this.hiddenToolTip(); }), m.append("text").attr("class", "point-label").attr("x", (a) => c.centroid(a)[0]).attr("y", (a) => c.centroid(a)[1]).attr("font-size", (a) => H * (1 / b) + "px").attr("text-anchor", "middle").attr("dominant-baseline", "middle").style("pointer-events", "none").attr("fill", P).text((a) => q.formatNumber(i.style === "percent" ? a.properties._value / 100 : a.properties._value, o)).on("mouseover", (a) => { }), O || this.g.selectAll(".centroids").style("display", "none"); } } createPatterns(e) { const { app: p, svg: v, format: i, id: u, file: h, path: c, onLayerCreated: F, labelFilter: l = [], labelField: d, labelFontSize: s, labelColor: n, fillColor: L, borderColor: f, tooltip: x, markFillColor: g, markLabelColor: P, markBorderColor: J, markSizeScale: N, markerLabelSize: H, featureJoinAttribute: tt, apiJoinAttribute: K, measures: I, editing: et, data: z, patternDiscriminator: k, patternDiscriminatorLabel: Q, breaks: $, gradientScheme: G, gradientReverse: E, patterns: w, projection: rt, useBreaks: X, useGradients: V, useCentroidPoint: U, usePattern: j, waitForFilters: at, intl: q, patternsVisible: B = !0, togglePatterns: R, colorLayerVisible: O = !0, visible: it } = this.props, S = new Y({ breaks: $, defaultFillColor: g, defaultBorderColor: J, defaultSize: N }), A = this.props.transform ? this.props.transform.k : 1, o = 10 * 1 / A, b = 10 * 1 / A; let m = []; if (p == "csv" && k != "none") m = [...new Set(z.data.map((t) => t[k]))].map((t) => ({ key: t, type: w[t + "_symbol"], color: w[t + "_color"], rotation: w[t + "_rotation"] })); else if (k != "none") { const t = z.metadata ? z.metadata.types.filter((y) => y.dimension == k) : []; m = t && t.length > 0 ? t[0].items.map((y) => { const _ = y.value; return { key: _, type: w[_ + "_symbol"], color: w[_ + "_color"], rotation: w[_ + "_rotation"] }; }) : []; } this.g.selectAll("defs").remove(); const a = this.g.append("defs"); if (a.selectAll("pattern").remove(), a.selectAll("pattern").data(m).enter().append("pattern").attr("id", (t) => C(t.key)).attr("patternUnits", "userSpaceOnUse").attr("width", o).attr("height", b).attr("x", 0).attr("y", 0).attr("patternTransform", (t) => `rotate(${t.rotation})`), m.forEach((t) => { t.type === "lines" && a.select("#" + C(t.key)).append("rect").attr("x", 0.05).attr("width", o / 2).attr("height", b).attr("opacity", 1).attr("fill", t.color), t.type === "squares" && a.select("#" + C(t.key)).append("rect").attr("width", o / 2).attr("height", b / 2).attr("fill", t.color).attr("opacity", 1).attr("stroke-width", 1), t.type === "dots" && a.select("#" + C(t.key)).append("circle").attr("cx", o / 2).attr("cy", b / 2).attr("r", o / 2.5).attr("fill", t.color).attr("opacity", 1).attr("stroke-width", 1), t.type === "triangle" && a.select("#" + C(t.key)).append("polygon").attr("points", `${o / 2} 0, 0 ${o}, ${o} ${o} `).attr("fill", t.color).attr("opacity", 1).attr("stroke-width", 1); }), m = m.filter((t) => t.type != null).sort((t, y) => new Intl.Collator(q.locale, { caseFirst: "upper", numeric: !0, sensitivity: "variant" }).compare(t.key, y.key)), j && e && e.features) { this.g.selectAll(".shape-pattern").remove(), B && e.features.forEach((r) => { let T = []; r.properties && r.properties.meta && (T = p != "csv" ? r.properties.meta[k] ? r.properties.meta[k] : [] : [r.properties.meta[k]], T && T.length > 0 && T.forEach((lt) => { this.g.append("path").attr("d", c(r)).datum(lt).attr("class", "shape-pattern").attr("opacity", (st) => { if (X) return 0.7; }).attr("fill", (st) => "transparent").attr("style", () => "none;fill:url(#" + C(lt) + ");").on("mouseenter", () => { this.showToolTip(x, this.getTooltipVariables(r), V ? gradientColors.getColor(r.properties._value) : S.getColor(r.properties._value)); }).on("mousemove", (st) => { this.moveToolTip(); }).on("mouseleave", (st) => { this.hiddenToolTip(); }); })); }), M.select(this.gRef.current.parentNode.parentNode).select(`.layer_${W(u)}`).select("svg").remove(); debugger; const t = M.select(this.gRef.current.parentNode.parentNode).select(`.layer_${W(u)}`).append("svg"); t.attr("height", 30 + m.length * 23 + "px"); const y = t.append("svg").append("g"), _ = y.append("defs"); _.selectAll("pattern").remove(), B && (_.selectAll("pattern").data(m).enter().append("pattern").attr("id", (r) => "l_" + C(r.key)).attr("patternUnits", "userSpaceOnUse").attr("width", 5).attr("height", 5).attr("x", 0).attr("y", 0).attr("patternTransform", (r) => `rotate(${r.rotation ? r.rotation : 0})`), m.forEach((r) => { r.type === "lines" && _.select("#l_" + C(r.key)).append("rect").attr("x", 0).attr("width", 1).attr("height", 10).attr("opacity", 0.75).attr("fill", r.color), r.type === "squares" && _.select("#l_" + C(r.key)).append("rect").attr("width", 3).attr("height", 3).attr("fill", r.color).attr("opacity", 1).attr("stroke-width", 1), r.type === "dots" && _.select("#l_" + C(r.key)).append("circle").attr("cx", 2).attr("cy", 2).attr("r", 2).attr("fill", r.color).attr("opacity", 1).attr("stroke-width", 1), r.type === "triangle" && _.select("#l_" + C(r.key)).append("polygon").attr("points", "5,0 8,8 0,5").attr("fill", r.color).attr("opacity", 1).attr("stroke-width", 1); })); let nt = B ? "☑ " : "☐ "; y.append("text").attr("class", "patterns-checkbox").attr("x", 10).attr("y", 20).text((r) => nt).attr("font-size", "22px").on("click", () => { R && R(u); }), y.append("text").attr("class", "patterns-title").attr("x", 25).attr("y", 7).text((r) => p === "csv" ? k : Q).on("click", () => { R && R(u); }), B && (y.selectAll(".legend-squares").data(m).enter().append("rect").attr("width", 15).attr("height", 15).attr("y", (r, T) => T * 22 + 30).attr("x", 15).attr("stroke", f).attr("style", (r) => "none;fill:url(#l_" + C(r.key) + ");"), y.selectAll(".patterns-labels").data(m).enter().append("text").attr("class", "patterns-labels").attr("y", (r, T) => T * 22 + 30).attr("x", 32).text((r) => r.key)); } } joinData(e, p, v, i, u, h) { const c = e.features.map((l) => { const d = l.properties[v]; if (p != "csv" && i && i.children) { const s = i.children.filter((n) => n.value == d); if (s.length > 0) { const n = s[0][u[0]]; if (l.properties.meta = s[0], l.properties._value = n, h && h != "none") { const L = s[0] && s[0].children ? s[0].children.filter((f) => f.type == h).map((f) => f.value) : []; l.properties.meta[h] = L; } } else l.properties._value = null; } else if (p == "csv") { const s = i.data.filter((n) => n[i.meta.fields[0]] == d); s.length > 0 ? (l.properties.meta = s[0], l.properties._value = s[0][i.meta.fields[1]]) : l.properties._value = null; } else l.properties._value = null; return l; }); return { ...e, features: c }; } componentDidUpdate(e, p, v) { const { app: i, file: u, featureJoinAttribute: h, data: c, measures: F, patternDiscriminator: l, editing: d } = this.props; if (d || JSON.stringify(e.data) !== JSON.stringify(c)) { debugger; this.create(); } if (e.visible != this.props.visible) { debugger; this.g.style("display", this.props.visible ? "" : "none"); } if (e.patternsVisible != this.props.patternsVisible) { const n = M.select(this.gRef.current.parentNode.parentNode).select(`.layer_${W(this.props.id)}`); n.select(".patterns-checkbox").text(this.props.patternsVisible ? "☑ " : "☐ "), n.selectAll(".patterns-labels").style("display", this.props.patternsVisible ? "" : "none"), n.selectAll("rect").style("display", this.props.patternsVisible ? "" : "none"), n.select("svg").attr("height", this.props.patternsVisible ? 30 + (n.selectAll("rect").size() - 1) * 23 + "px" : "30px"), this.g.selectAll(".shape-pattern").style("display", this.props.patternsVisible ? "" : "none"); } e.colorLayerVisible != this.props.colorLayerVisible && (this.g.selectAll(".borders").style("fill", (s) => { debugger; return this.props.colorLayerVisible ? null : this.props.fillColor; }), this.g.selectAll(".centroids").style("display", this.props.colorLayerVisible ? "block" : "none")), e.usePattern != this.props.usePattern && (this.props.usePattern || M.select(this.gRef.current.parentNode.parentNode).select(`.layer_${W(this.props.id)}`).select("svg").remove()), this.g && this.resize(); } componentDidMount() { super.componentDidMount(); } render() { const { id: e, file: p, path: v, zoom: i, labelFilter: u = [], labelField: h, labelFontSize: c, labelColor: F, fillColor: l, borderColor: d, featureJoinAttribute: s, apiJoinAttribute: n, dvzProxyDatasetId: L, editing: f } = this.props; return /* @__PURE__ */ Z("g", { id: "data-" + e, className: "data " + e, ref: this.gRef }); } } const ft = (D) => { const { id: e, unique: p, filters: v, csv: i, app: u, group: h = "default", apiJoinAttribute: c, editing: F, patternDiscriminator: l, dvzProxyDatasetId: d, intl: s, settings: n, waitForFilters: L } = D, f = {}, x = v || {}; return x && x.forEach && x.forEach((g) => { g.value != null && g.value.filter((P) => P != null && P.toString().trim() != "").length > 0 && (f[g.param] = g.value); }), d && (f.dvzProxyDatasetId = d), /* @__PURE__ */ Z( ct, { waitForFilters: L, editing: F, params: f, app: u, csv: decodeURIComponent(i), group: h, ignoreErrors: !0, isSvg: !0, store: [u, p, e], source: c + (l != "none" ? "/" + l : ""), children: /* @__PURE__ */ Z(ut, { children: /* @__PURE__ */ Z(ht, { ...D }) }) } ); }, _t = dt(ft); export { _t as default };