@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
JavaScript
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
};