Select Git revision
candidate_cycles.PNG
Forked from
DBIS / FactDAG / factlib.js
Source project has a limited visibility.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
utils.js 7.06 KiB
import "gridstack/dist/gridstack.min.css";
import { GridStack } from "gridstack";
/**
* Request analytics engine results from rights engine.
* @param {*} token
* @param {*} url
* @returns
*/
export async function getResult(token, url) {
try {
const response = await fetch(url, {
headers: {
Authorization: `Basic ${token}`,
},
});
return await response.json();
} catch (error) {
throw Error("Fetching result from backend failed. Please check URL and TOKEN settings.");
}
}
/**
* Plots chart in each configured widget.
* @param {*} nodes
* @param {*} widgets
*/
function plotWidgets(nodes, widgets) {
for (const node of nodes) {
if (node.subGrid) {
// Handle sub grid
plotWidgets(node.subGrid.engine.nodes, widgets);
} else {
const widget = widgets[node.widgetId];
if (widget) {
plot(node, widget);
} else if (node.el.getAttribute("widgetId")) {
const widgetId = node.el.getAttribute("widgetId");
plot(node, widgets[widgetId]);
} else {
console.error(`Couldn't find widget by id ${node.widgetId}`);
}
}
}
}
/**
* Calls plot function on each widget, passing current widget div container width, height and
* updates widget content with resulting chart svg.
* @param {*} node
* @param {*} widget
*/
function plot(node, widget) {
const content = node.el.querySelector(".grid-stack-item-content");
const width = content.offsetWidth;
const height = content.offsetHeight;
content.innerHTML = widget.plot(width, height);
}
/**
* Renders single widget content for available widgets sidebar.
* @param {*} widget
* @param {*} widgetId
* @returns
*/
function createAvWidgetPlaceholder(widget, widgetId) {
const content = widget.plot(400, 400);
const div = document.createElement("div");
div.innerHTML = `<div class="newWidget grid-stack-item" widgetId="${widgetId}"><div class="grid-stack-item-content">${content}</div></div>`;
return div;
}
/**
* Renders all available widgets in sidebar.
* @param {*} widgets
*/
export function drawAvailableWidgets(widgets) {
const availableWidgets = document.getElementById("available-widgets");
for (const widgetId of Object.keys(widgets)) {
const avWidgetDiv = createAvWidgetPlaceholder(widgets[widgetId], widgetId);
availableWidgets.appendChild(avWidgetDiv, widgetId);
}
}
/**
* Handles widget drag in from sidebar by adding a widget to the widgets grid.
* @param {*} event
* @returns
*/
export function handleNewWidgetDragIn(event) {
const parentWithClass = event.srcElement.closest(".newWidget");
const targetEl = parentWithClass.cloneNode(true);
targetEl.style.removeProperty("newWidget");
return targetEl;
}
/**
* Removes all child nodes from an HTML node.
* @param {*} parent
*/
function removeAllChildNodes(parent) {
while (parent.firstChild) {
parent.removeChild(parent.firstChild);
}
}
/**
* Initial widgets grid
* @param {*} widgets
* @param {*} items
*/
export function initGrid(widgets, items) {
// Basic grid object
const grid = GridStack.init({
cellHeight: 70,
acceptWidgets: true,
removable: ".dropzone-remove",
minRow: 2,
subGrid: {
disableOneColumnMode: true,
minRow: 2,
cellHeight: 70,
margin: 5,
acceptWidgets: true, // will accept .grid-stack-item by default
locked: true,
noResize: true,
noMove: true,
removable: ".dropzone-remove",
},
subGridDynamic: true,
});
// Enables widget resize and movement on grid
function enableWidgetMoveAndResize() {
grid.enableResize(true);
grid.enableMove(true);
grid.engine.nodes.map((e) => {
if (e.subGrid) {
e.subGrid.enableResize(true);
e.subGrid.enableMove(true);
}
});
}
// Disables widget resize and movement on grid
function disableWidgetMoveAndResize() {
grid.enableResize(false);
grid.enableMove(false);
grid.engine.nodes.map((e) => {
if (e.subGrid) {
e.subGrid.enableResize(false);
e.subGrid.enableMove(false);
}
});
}
grid.load(items);
grid.setAnimation(false);
addResizeListener(grid);
plotWidgets(grid.engine.nodes, widgets);
disableWidgetMoveAndResize();
// Add resize listener for subgrid
grid.engine.nodes.map((e) => {
if (e.subGrid) {
e.subGrid.on("resizestop", function (event, el) {
plotWidgets(grid.engine.nodes, widgets);
});
}
});
// Rerender all widgets on widget removal
grid.on("removed change", function (e, items) {
plotWidgets(grid.engine.nodes, widgets);
});
// Rerender all widgets when adding a new widget
grid.on("added", function (e, items) {
plotWidgets(grid.engine.nodes, widgets);
});
// Create resize event listener and rerenders all widgets on resize
function addResizeListener(grid) {
window.addEventListener(
"resize",
function (event) {
plotWidgets(grid.engine.nodes, widgets);
},
true
);
}
/**
* Handle sidebar toggle, including enabeling/disabeling widget resize and movement.
*/
function toggleSidebar() {
const sidebar = document.getElementById("sidebar");
const isVisible = sidebar.className === "sidebar";
if (isVisible) {
disableWidgetMoveAndResize();
sidebar.className = "sidebar-hidden";
const avWidgets = document.getElementById("available-widgets");
removeAllChildNodes(avWidgets);
plotWidgets(grid.engine.nodes, widgets);
} else {
sidebar.className = "sidebar";
drawAvailableWidgets(widgets);
GridStack.setupDragIn(".newWidget", {
revert: "invalid",
scroll: false,
appendTo: "body",
helper: handleNewWidgetDragIn,
});
enableWidgetMoveAndResize();
plotWidgets(grid.engine.nodes, widgets);
}
}
/**
* Saves current grid configuration. The returned grid configuration can be loaded later (e.g. when the user revisited the dashboard).
* @returns grid configuration
*/
function save() {
const oldGrid = grid.save();
return oldGrid.map((item) => {
if (item.subGrid) {
return {
x: item.x,
y: item.y,
w: item.w,
h: item.h,
subGrid: {
x: item.subGrid.x,
y: item.subGrid.y,
w: item.subGrid.w,
h: item.subGrid.h,
children: item.subGrid.children.map((e) => ({
x: e.x,
y: e.y,
w: e.w,
h: e.h,
widgetId: e.widgetId,
})),
},
};
} else {
return {
x: item.x,
y: item.y,
w: item.w,
h: item.h,
widgetId: item.widgetId,
};
}
});
}
/**
* Loads a grid configuration. Should be used along with the save function.
* @param {*} items
*/
function load(items) {
grid.removeAll();
grid.load(items);
plotWidgets(grid.engine.nodes, widgets);
disableWidgetMoveAndResize();
}
return {
grid,
toggleSidebar,
save,
load,
enableWidgetMoveAndResize,
disableWidgetMoveAndResize,
};
}