data-clumps-visualizer
Version:
This is a package to identify data-clumps-visualizer
478 lines (477 loc) • 24.5 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataClumpsGraph = void 0;
const react_1 = __importStar(require("react"));
const react_graph_vis_1 = __importDefault(require("react-graph-vis"));
const button_1 = require("primereact/button");
const uuid_1 = require("uuid");
const COLOR_UNI_ROT = "#ac0634";
const COLOR_UNI_GELB = "#fbb900";
const COLOR_UNI_GRAU = "#cfcfcf";
const COLOR_PRIMARY = undefined;
const COLOR_PALETTES = generateColorPaletteFromColor(COLOR_PRIMARY);
const COLOR_FILE = COLOR_PALETTES.color_file || COLOR_UNI_GRAU;
const COLOR_FILE_TEXT = calculateBestTextColor(COLOR_FILE);
const COLOR_CLASS = COLOR_PALETTES.color_class || COLOR_UNI_GRAU;
const COLOR_CLASS_TEXT = calculateBestTextColor(COLOR_CLASS);
const COLOR_METHOD = COLOR_PALETTES.color_method || COLOR_UNI_GELB;
const COLOR_METHOD_TEXT = calculateBestTextColor(COLOR_METHOD);
const COLOR_PARAMETER = COLOR_PALETTES.color_parameter || COLOR_UNI_ROT;
const COLOR_PARAMETER_TEXT = calculateBestTextColor(COLOR_PARAMETER);
const COLOR_FIELD = COLOR_PALETTES.color_field || COLOR_UNI_ROT;
const COLOR_FIELD_TEXT = calculateBestTextColor(COLOR_FIELD);
function generateColorPaletteFromColor(baseColor) {
function adjustBrightness(color, percent) {
if (!color) {
return undefined;
}
// Convert hex to RGB
const num = parseInt(color.replace("#", ""), 16);
const r = (num >> 16) + percent;
const g = ((num >> 8) & 0x00FF) + percent;
const b = (num & 0x0000FF) + percent;
// Ensure RGB stays within 0-255
const newR = Math.min(Math.max(0, r), 255);
const newG = Math.min(Math.max(0, g), 255);
const newB = Math.min(Math.max(0, b), 255);
// Convert back to hex
return `#${((1 << 24) + (newR << 16) + (newG << 8) + newB)
.toString(16)
.slice(1)}`;
}
let isDark = false;
const COLOR_BLACK = "#000000";
let bestTextColor = calculateBestTextColor(baseColor);
if (bestTextColor === COLOR_BLACK) {
isDark = true;
}
let multiplier = -1;
if (isDark) {
multiplier = 1;
}
return {
color_file: adjustBrightness(baseColor, multiplier * 160),
color_class: adjustBrightness(baseColor, multiplier * 120),
color_method: adjustBrightness(baseColor, multiplier * 80),
color_parameter: baseColor,
color_field: adjustBrightness(baseColor, multiplier * 40), // Lighter than base
};
}
function calculateBestTextColor(backgroundColor) {
const COLOR_BLACK = "#000000";
const COLOR_WHITE = "#FFFFFF";
if (!backgroundColor) {
return undefined;
}
// only black or white for text
let color = backgroundColor;
if (color.startsWith("#")) {
color = color.substring(1);
}
// calculate highest contrast color
let r = parseInt(color.substring(0, 2), 16);
let g = parseInt(color.substring(2, 4), 16);
let b = parseInt(color.substring(4, 6), 16);
let yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
return (yiq >= 128) ? COLOR_BLACK : COLOR_WHITE;
}
const DataClumpsGraph = (props) => {
var _a, _b;
const [a, setA] = (0, react_1.useState)();
const dark_mode = props === null || props === void 0 ? void 0 : props.dark_mode;
let dataClumpsDict = props.dataClumpsDict;
const from_file_path = props === null || props === void 0 ? void 0 : props.from_file_path;
const to_file_path = props === null || props === void 0 ? void 0 : props.to_file_path;
const version = (0, react_1.useMemo)(uuid_1.v4, [dataClumpsDict, from_file_path, to_file_path, dark_mode]);
//const [dataClumpsDict, setDataClumpsDict] = useSynchedDataClumpsDict(); // we wont use synched variable here, since we want to export our functionality outside
// const [showLargeGraph, setShowLargeGraph] = useState(false);
const showLargeGraph = true;
const setShowLargeGraph = (bool) => {
};
function getInitialGraphFromDataClumpsDict(dataClumpsDict) {
//console.log("getInitialGraphFromDataClumpsDict");
let from_file_path = props === null || props === void 0 ? void 0 : props.from_file_path;
let to_file_path = props === null || props === void 0 ? void 0 : props.to_file_path;
let files_dict = {};
let classes_dict = {};
let fields_dict = {};
let methods_dict = {};
let parameters_dict = {};
if (dataClumpsDict) {
let dataClumps = (dataClumpsDict === null || dataClumpsDict === void 0 ? void 0 : dataClumpsDict.data_clumps) || {};
let dataClumpsKeys = Object.keys(dataClumps);
for (let dataClumpKey of dataClumpsKeys) {
let dataClump = dataClumps[dataClumpKey];
let file_path = dataClump.from_file_path;
let shouldAnalyzeFile = true;
if (from_file_path) {
shouldAnalyzeFile = file_path === from_file_path;
}
if (shouldAnalyzeFile) {
let data_clump_data_dict = dataClump.data_clump_data;
let dataClumpDataKeys = Object.keys(data_clump_data_dict);
for (let dataClumpDataKey of dataClumpDataKeys) {
let dataClumpData = data_clump_data_dict[dataClumpDataKey];
initNodesForDataClumpData(dataClump, dataClumpData, files_dict, classes_dict, fields_dict, methods_dict, parameters_dict);
}
}
}
}
let nodes = [];
let edges = [];
let graph = {
nodes: nodes,
edges: edges
};
let files_dict_keys = Object.keys(files_dict);
for (let file_dict_key of files_dict_keys) {
let file_dict_value = files_dict[file_dict_key];
// @ts-ignore
graph.nodes.push(file_dict_value);
let classes_or_interfaces_ids = file_dict_value.classes_or_interfaces_ids;
let classes_or_interfaces_ids_keys = Object.keys(classes_or_interfaces_ids);
for (let classes_or_interfaces_ids_key of classes_or_interfaces_ids_keys) {
graph.edges.push({
// @ts-ignore
from: file_dict_value.id,
// @ts-ignore
to: classes_or_interfaces_ids_key,
});
}
}
let classes_dict_keys = Object.keys(classes_dict);
for (let class_dict_key of classes_dict_keys) {
let class_dict_value = classes_dict[class_dict_key];
// @ts-ignore
graph.nodes.push(class_dict_value);
let field_ids = class_dict_value.field_ids;
let field_ids_keys = Object.keys(field_ids);
for (let field_ids_key of field_ids_keys) {
graph.edges.push({
// @ts-ignore
from: class_dict_value.id,
// @ts-ignore
to: field_ids_key,
});
}
let method_ids = class_dict_value.method_ids;
let method_ids_keys = Object.keys(method_ids);
for (let method_ids_key of method_ids_keys) {
graph.edges.push({
// @ts-ignore
from: class_dict_value.id,
// @ts-ignore
to: method_ids_key,
});
}
}
let fields_dict_keys = Object.keys(fields_dict);
for (let field_dict_key of fields_dict_keys) {
let field_dict_value = fields_dict[field_dict_key];
// @ts-ignore
graph.nodes.push(field_dict_value);
let related_to = field_dict_value.related_to;
let related_to_keys = Object.keys(related_to);
for (let related_to_key of related_to_keys) {
graph.edges.push({
// @ts-ignore
from: field_dict_value.id,
// @ts-ignore
to: related_to_key,
});
}
}
let method_ids = Object.keys(methods_dict);
for (let method_id of method_ids) {
let method_dict_value = methods_dict[method_id];
// @ts-ignore
graph.nodes.push(method_dict_value);
let parameter_ids = method_dict_value.parameter_ids;
let parameter_ids_keys = Object.keys(parameter_ids);
for (let parameter_ids_key of parameter_ids_keys) {
graph.edges.push({
// @ts-ignore
from: method_dict_value.id,
// @ts-ignore
to: parameter_ids_key,
});
}
}
let parameters_dict_keys = Object.keys(parameters_dict);
for (let parameter_dict_key of parameters_dict_keys) {
let parameter_dict_value = parameters_dict[parameter_dict_key];
// @ts-ignore
graph.nodes.push(parameter_dict_value);
let related_to = parameter_dict_value.related_to;
let related_to_keys = Object.keys(related_to);
for (let related_to_key of related_to_keys) {
graph.edges.push({
// @ts-ignore
from: parameter_dict_value.id,
// @ts-ignore
to: related_to_key,
});
}
}
return graph;
}
function getRawFileNode(file_path, files_dict) {
let file_node = files_dict[file_path];
let file_name = file_path;
try {
file_name = file_path.split("/").pop();
}
catch (e) {
// could not split file_path, so just use file_path as file_name
}
if (!file_node) {
file_node = {
id: file_path,
label: file_name,
color: COLOR_FILE,
font: { color: COLOR_FILE_TEXT },
classes_or_interfaces_ids: {},
};
files_dict[file_node.id] = file_node;
}
return file_node;
}
function getRawClassesOrInterfacesNode(classOrInterface_key, classOrInterface_name, classes_dict) {
//console.log("getRawClassesOrInterfacesNode: classOrInterface");
//console.log(classOrInterface)
let class_or_interface_node = classes_dict[classOrInterface_key];
if (!class_or_interface_node) {
class_or_interface_node = {
id: classOrInterface_key,
label: classOrInterface_name,
color: COLOR_CLASS,
font: { color: COLOR_CLASS_TEXT },
field_ids: {},
method_ids: {},
};
classes_dict[class_or_interface_node.id] = class_or_interface_node;
}
return class_or_interface_node;
}
function getRawMethodNode(method_key, method_name, methods_dict) {
let method_node = methods_dict[method_key];
if (!method_node) {
method_node = {
id: method_key,
label: method_name,
color: COLOR_METHOD,
font: { color: COLOR_METHOD_TEXT },
parameter_ids: {},
};
methods_dict[method_node.id] = method_node;
}
return method_node;
}
function getRawParameterNode(parameter_key, parameter_name, parameters_dict) {
let parameter_node = parameters_dict[parameter_key];
if (!parameter_node) {
parameter_node = {
id: parameter_key,
label: parameter_name,
color: COLOR_PARAMETER,
font: { color: COLOR_PARAMETER_TEXT },
related_to: {},
};
parameters_dict[parameter_node.id] = parameter_node;
}
return parameter_node;
}
function createRawLinkBetweenParameterOrFieldNodes(field_node, related_to_field_node) {
field_node.related_to[related_to_field_node.id] = related_to_field_node.id;
related_to_field_node.related_to[field_node.id] = field_node.id;
}
function initNodesForDataClumpData(dataClumpHolder, dataClumpData, files_dict, classes_dict, fields_dict, methods_dict, parameters_dict) {
let data_clump_type = dataClumpHolder.data_clump_type;
if (data_clump_type === "parameters_to_parameters_data_clump") {
//console.log("parameter_data_clump")
//console.log(dataClumpData);
let file_path_from = dataClumpHolder.from_file_path;
let file_node_from = getRawFileNode(file_path_from, files_dict);
let classOrInterfaceKey_from = dataClumpHolder.from_class_or_interface_key;
let classOrInterfaceName_from = dataClumpHolder.from_class_or_interface_name;
let class_or_interface_node_from = getRawClassesOrInterfacesNode(classOrInterfaceKey_from, classOrInterfaceName_from, classes_dict);
file_node_from.classes_or_interfaces_ids[class_or_interface_node_from.id] = class_or_interface_node_from.id;
let file_path_to = dataClumpHolder.to_file_path;
let file_node_to = getRawFileNode(file_path_to, files_dict);
let classOrInterfaceKey_to = dataClumpHolder.to_class_or_interface_key;
let classOrInterfaceName_to = dataClumpHolder.to_class_or_interface_name;
let class_or_interface_node_to = getRawClassesOrInterfacesNode(classOrInterfaceKey_to, classOrInterfaceName_to, classes_dict);
file_node_to.classes_or_interfaces_ids[class_or_interface_node_to.id] = class_or_interface_node_to.id;
let method_key_from = dataClumpHolder.from_method_key + "";
let method_name_from = dataClumpHolder.from_method_name + "";
let method_node_from = getRawMethodNode(method_key_from, method_name_from, methods_dict);
class_or_interface_node_from.method_ids[method_node_from.id] = method_node_from.id;
let method_key_to = dataClumpHolder.to_method_key + "";
let method_name_to = dataClumpHolder.to_method_name + "";
let method_node_to = getRawMethodNode(method_key_to, method_name_to, methods_dict);
class_or_interface_node_to.method_ids[method_node_to.id] = method_node_to.id;
let parameter_key_from = dataClumpData.key;
let parameter_name_from = dataClumpData.name;
let parameter_node_from = getRawParameterNode(parameter_key_from, parameter_name_from, parameters_dict);
method_node_from.parameter_ids[parameter_node_from.id] = parameter_node_from.id;
let parameter_key_to = dataClumpData.to_variable.key;
let parameter_name_to = dataClumpData.to_variable.name;
let parameter_node_to = getRawParameterNode(parameter_key_to, parameter_name_to, parameters_dict);
method_node_to.parameter_ids[parameter_node_to.id] = parameter_node_to.id;
createRawLinkBetweenParameterOrFieldNodes(parameter_node_from, parameter_node_to);
}
else if (data_clump_type === "fields_to_fields_data_clump") {
let file_path_from = dataClumpHolder.from_file_path;
let file_node_from = getRawFileNode(file_path_from, files_dict);
let classOrInterfaceKey_from = dataClumpHolder.from_class_or_interface_key;
let classOrInterfaceName_from = dataClumpHolder.from_class_or_interface_name;
let class_or_interface_node_from = getRawClassesOrInterfacesNode(classOrInterfaceKey_from, classOrInterfaceName_from, classes_dict);
file_node_from.classes_or_interfaces_ids[class_or_interface_node_from.id] = class_or_interface_node_from.id;
let file_path_to = dataClumpHolder.to_file_path;
let file_node_to = getRawFileNode(file_path_to, files_dict);
let classOrInterfaceKey_to = dataClumpHolder.to_class_or_interface_key;
let classOrInterfaceName_to = dataClumpHolder.to_class_or_interface_name;
let class_or_interface_node_to = getRawClassesOrInterfacesNode(classOrInterfaceKey_to, classOrInterfaceName_to, classes_dict);
file_node_to.classes_or_interfaces_ids[class_or_interface_node_to.id] = class_or_interface_node_to.id;
let parameter_key_from = dataClumpData.key;
let parameter_name_from = dataClumpData.name;
let parameter_node_from = getRawParameterNode(parameter_key_from, parameter_name_from, parameters_dict);
class_or_interface_node_from.field_ids[parameter_node_from.id] = parameter_node_from.id;
let parameter_key_to = dataClumpData.to_variable.key;
let parameter_name_to = dataClumpData.to_variable.name;
let parameter_node_to = getRawParameterNode(parameter_key_to, parameter_name_to, parameters_dict);
class_or_interface_node_to.field_ids[parameter_node_to.id] = parameter_node_to.id;
createRawLinkBetweenParameterOrFieldNodes(parameter_node_from, parameter_node_to);
}
else if (data_clump_type === "parameters_to_fields_data_clump") {
let file_path_from = dataClumpHolder.from_file_path;
let file_node_from = getRawFileNode(file_path_from, files_dict);
let classOrInterfaceKey_from = dataClumpHolder.from_class_or_interface_key;
let classOrInterfaceName_from = dataClumpHolder.from_class_or_interface_name;
let class_or_interface_node_from = getRawClassesOrInterfacesNode(classOrInterfaceKey_from, classOrInterfaceName_from, classes_dict);
file_node_from.classes_or_interfaces_ids[class_or_interface_node_from.id] = class_or_interface_node_from.id;
let file_path_to = dataClumpHolder.to_file_path;
let file_node_to = getRawFileNode(file_path_to, files_dict);
let classOrInterfaceKey_to = dataClumpHolder.to_class_or_interface_key;
let classOrInterfaceName_to = dataClumpHolder.to_class_or_interface_name;
let class_or_interface_node_to = getRawClassesOrInterfacesNode(classOrInterfaceKey_to, classOrInterfaceName_to, classes_dict);
file_node_to.classes_or_interfaces_ids[class_or_interface_node_to.id] = class_or_interface_node_to.id;
let method_key_from = dataClumpHolder.from_method_key + "";
let method_name_from = dataClumpHolder.from_method_name + "";
let method_node_from = getRawMethodNode(method_key_from, method_name_from, methods_dict);
class_or_interface_node_from.method_ids[method_node_from.id] = method_node_from.id;
let parameter_key_from = dataClumpData.key;
let parameter_name_from = dataClumpData.name;
let parameter_node_from = getRawParameterNode(parameter_key_from, parameter_name_from, parameters_dict);
method_node_from.parameter_ids[parameter_node_from.id] = parameter_node_from.id;
let parameter_key_to = dataClumpData.to_variable.key;
let parameter_name_to = dataClumpData.to_variable.name;
let parameter_node_to = getRawParameterNode(parameter_key_to, parameter_name_to, parameters_dict);
class_or_interface_node_to.field_ids[parameter_node_to.id] = parameter_node_to.id;
//createRawLinkBetweenParameterOrFieldNodes(parameter_node_from, parameter_node_to);
// is uni-directional so only from the parameter to the field
parameter_node_from.related_to[parameter_node_to.id] = parameter_node_to.id;
}
}
// const [state, setState] = useState({
let state = {
counter: 5,
graph: getInitialGraphFromDataClumpsDict(dataClumpsDict),
/** graph: {
nodes: [
{ id: 1, label: "Node 1", color: "#e04141" },
{ id: 2, label: "Node 2", color: "#e09c41" },
{ id: 3, label: "Node 3", color: "#e0df41" },
{ id: 4, label: "Node 4", color: "#7be041" },
{ id: 5, label: "Node 5", color: "#41e0c9" }
],
edges: [
{ from: 1, to: 2 },
{ from: 1, to: 3 },
{ from: 2, to: 4 },
{ from: 2, to: 5 }
]
}, */
events: {
select: ({ nodes, edges }) => {
console.log("Selected nodes:");
console.log(nodes);
console.log("Selected edges:");
console.log(edges);
}
}
};
//);
const { graph, events } = state;
function renderGraph() {
const edgesColor = dark_mode ? "#ffffff" : "#000000";
const options = {
layout: {
hierarchical: false,
},
edges: {
color: edgesColor
},
};
const events = {
select: function (event) {
var { nodes, edges } = event;
}
};
return (react_1.default.createElement(react_graph_vis_1.default, { key: version, graph: graph, options: options, events: events, style: { height: "100%", width: "100%" } }));
}
let amountNodes = ((_a = graph === null || graph === void 0 ? void 0 : graph.nodes) === null || _a === void 0 ? void 0 : _a.length) || 0;
let amountEdges = ((_b = graph === null || graph === void 0 ? void 0 : graph.edges) === null || _b === void 0 ? void 0 : _b.length) || 0;
function renderSecureGraph() {
let largeGraph = amountNodes > 1000;
if (largeGraph && !showLargeGraph) {
return (react_1.default.createElement("div", { style: { height: "100%", width: "100%", backgroundColor: "transparent" } },
react_1.default.createElement("div", { style: { height: "100%", width: "100%", display: "flex", alignItems: "center", flexDirection: "column" } },
react_1.default.createElement("div", { style: { display: "block" } },
react_1.default.createElement("h1", null, "Graph is very large"),
react_1.default.createElement("div", null,
"Nodes: ",
amountNodes),
react_1.default.createElement("div", null,
"Edges: ",
amountEdges),
react_1.default.createElement("h2", null, "Select a specific file")),
react_1.default.createElement("div", { style: { paddingTop: "30px", paddingBottom: "30px" } }, "or"),
react_1.default.createElement(button_1.Button, { className: "p-button-danger", icon: "pi pi-exclamation-triangle", label: "Show large graph", onClick: () => {
setShowLargeGraph(true);
} }))));
}
else {
return renderGraph();
}
}
return (react_1.default.createElement("div", { style: { height: "100%", width: "100%", backgroundColor: "transparent" } },
react_1.default.createElement("div", { style: { height: "100%", width: "100%" } }, renderSecureGraph())));
};
exports.DataClumpsGraph = DataClumpsGraph;