saydata
Version:
Saydata seamlessly integrates AI-driven analytics for your customers into your app. Designed for beautiful visualization. Engineered for simplicity.
300 lines (299 loc) • 23 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect, useRef, useState } from "react";
import classes from "./Dashboard.module.scss";
import { useDashboardDetails, useDashboards, usePatchDashboard, usePatchDashboardapiKey, usePatchItem, } from "../api/dashboard";
import { dataFormater } from "../utils/util";
import { Backdrop, Button, CircularProgress, Dialog, DialogContent, DialogTitle, IconButton, InputAdornment, Popover, TextField, } from "@mui/material";
import Graphs from "../charts/Graphs";
import RowsView from "../utils/RowsView";
import { Responsive } from "react-grid-layout";
import "react-grid-layout/css/styles.css";
import { CloseRounded, MoreVertRounded, PlayArrowRounded, SendRounded, } from "@mui/icons-material";
import { v4 } from "uuid";
import { useConnection, useConnectionById } from "../api/connections";
import { useChatDetails, useAddChat, usePatchChat } from "../api/chat";
import Chats from "../chat/Chat";
export default function Dashboard(_a) {
var _b, _c;
var dashboardId = _a.dashboardId, activeConnection = _a.activeConnection, apiKey = _a.apiKey, userId = _a.userId, marginLeft = _a.marginLeft, marginTop = _a.marginTop, brandColor = _a.brandColor, backgroundColor = _a.backgroundColor;
var _d = useState(v4()), chatId = _d[0], setChatId = _d[1];
var moreButtonRef = useRef();
var connections = useConnection(apiKey).data;
var _e = useChatDetails(chatId, apiKey), chatDetails = _e.data, loadingDetails = _e.isLoading, refetch = _e.refetch;
var _f = useAddChat(chatId, apiKey), addChat = _f.mutate, addingChat = _f.isLoading;
var _g = usePatchChat(chatId, apiKey), patchChat = _g.mutate, patchingChat = _g.isLoading;
var _h = useDashboards(apiKey), dashboards = _h.data, fetchingDashboards = _h.isLoading;
var _j = usePatchDashboardapiKey(apiKey), updateDashboard = _j.mutate, updatingDashboard = _j.isLoading;
var _k = useDashboardDetails(dashboardId, apiKey), dashboardDetails = _k.data, loadingDashboard = _k.isLoading;
var _l = usePatchDashboard(dashboardId, apiKey), patchDashboard = _l.mutate, patchingDashboard = _l.isLoading;
var _m = usePatchItem(dashboardId, apiKey), patchItem = _m.mutate, patchingItem = _m.isLoading;
var _o = useConnectionById(apiKey, activeConnection), connection = _o.data, refetchConnection = _o.refetch;
var _p = useState({ items: [] }), dashboard = _p[0], setDashboard = _p[1];
var _q = useState(""), selectedTile = _q[0], setSelectedTile = _q[1];
var _r = useState(null), anchorEl = _r[0], setAnchorEl = _r[1];
var openPopover = Boolean(anchorEl);
var containerRef = useRef(null);
var containerWidth = ((_b = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) === null || _b === void 0 ? void 0 : _b.offsetWidth) || 1200;
var _s = useState(false), openChatDialog = _s[0], setChatDialog = _s[1];
var _t = useState(false), showTables = _t[0], setShowTables = _t[1];
var _u = useState(false), showSql = _u[0], setShowSql = _u[1];
var handleClick = function (e, key) {
setAnchorEl(e.currentTarget);
setSelectedTile(key);
moreButtonRef.current = e.currentTarget;
};
useEffect(function () {
var root = document.getElementById("root");
if (root) {
root.style.setProperty("--dashboard-left-margin", marginLeft);
root.style.setProperty("--dashboard-top-margin", marginTop);
root.style.setProperty("--dashboard-brand-color", brandColor);
root.style.setProperty("--dashboard-background-color", backgroundColor);
}
});
var handleClose = function () {
setAnchorEl(null);
};
var _v = useState(null), anchorElGraph = _v[0], setAnchorElGraph = _v[1];
var _w = useState(""), currentGraphText = _w[0], setCurrentGraphText = _w[1];
var handleGraphClick = function (event) {
moreButtonRef.current && setAnchorElGraph(moreButtonRef.current);
};
var handleGraphClose = function () {
setAnchorElGraph(null);
};
var openGraphPopover = Boolean(anchorElGraph);
useEffect(function () {
if (dashboardDetails === null || dashboardDetails === void 0 ? void 0 : dashboardDetails.data) {
setDashboard(dashboardDetails.data);
}
}, [dashboardDetails]);
var updateCharts = function () {
var request = {
id: dashboardId,
items: dashboard.items,
};
patchDashboard(request);
};
var updateItem = function (key) {
var _a, _b;
var blockId = (_a = selectedTile === null || selectedTile === void 0 ? void 0 : selectedTile.split("_")) === null || _a === void 0 ? void 0 : _a[0];
var type = (_b = selectedTile === null || selectedTile === void 0 ? void 0 : selectedTile.split("_")) === null || _b === void 0 ? void 0 : _b[1];
var newDashboardItems = __spreadArray([], dashboard.items, true);
var index = newDashboardItems.findIndex(function (item) { return item.chatItem.blockId === blockId && item.type === type; });
if (index >= 0) {
var it_1 = newDashboardItems[index];
if (key === "graph") {
it_1.chatItem.question = currentGraphText;
}
var request = {
key: key,
item: it_1,
};
patchItem(request, {
onSuccess: function (response) {
setCurrentGraphText("");
newDashboardItems[index] = response === null || response === void 0 ? void 0 : response.data;
setDashboard(__assign(__assign({}, dashboard), { items: newDashboardItems }));
if (key === "sql") {
setShowSql(false);
}
else if (key === "graph") {
handleGraphClose();
}
},
});
}
};
var handleGraphEnterEvent = function (e) {
if (e.keyCode === 13) {
updateItem("graph");
}
};
var deleteChart = function () {
var _a, _b;
var blockId = (_a = selectedTile === null || selectedTile === void 0 ? void 0 : selectedTile.split("_")) === null || _a === void 0 ? void 0 : _a[0];
var type = (_b = selectedTile === null || selectedTile === void 0 ? void 0 : selectedTile.split("_")) === null || _b === void 0 ? void 0 : _b[1];
var newDashboardItems = __spreadArray([], dashboard.items, true);
var index = newDashboardItems.findIndex(function (item) { return item.chatItem.blockId === blockId && item.type === type; });
if (index >= 0) {
newDashboardItems.splice(index, 1);
setDashboard(__assign(__assign({}, dashboard), { items: newDashboardItems }));
}
handleClose();
};
var updateItemBlock = function (key, blockId, type, value) {
var newDashboardItems = __spreadArray([], dashboard.items, true);
var index = newDashboardItems.findIndex(function (item) { return item.chatItem.blockId === blockId && item.type === type; });
if (index >= 0) {
var it_2 = newDashboardItems[index];
it_2.chatItem[key] = value;
newDashboardItems[index] = it_2;
setDashboard(__assign(__assign({}, dashboard), { items: newDashboardItems }));
}
};
var getConnectionName = function (id) {
var _a, _b;
return (_b = (_a = connections === null || connections === void 0 ? void 0 : connections.data) === null || _a === void 0 ? void 0 : _a.find(function (connection) { return connection.id === id; })) === null || _b === void 0 ? void 0 : _b.displayName;
};
var handleLayoutChange = function (layouts, allLayouts) {
if (dashboard === null || dashboard === void 0 ? void 0 : dashboard.items) {
var newDashboardItems_1 = __spreadArray([], dashboard.items, true);
layouts.forEach(function (layout) {
var index = newDashboardItems_1.findIndex(function (item) {
var _a, _b, _c, _d;
return item.chatItem.blockId === ((_b = (_a = layout.i) === null || _a === void 0 ? void 0 : _a.split("_")) === null || _b === void 0 ? void 0 : _b[0]) &&
item.type === ((_d = (_c = layout.i) === null || _c === void 0 ? void 0 : _c.split("_")) === null || _d === void 0 ? void 0 : _d[1]);
});
var it = newDashboardItems_1[index];
if (it) {
it.x = layout.x;
it.y = layout.y;
it.width = layout.w;
it.height = layout.h;
newDashboardItems_1[index] = it;
}
});
setDashboard(__assign(__assign({}, dashboard), { items: newDashboardItems_1 }));
}
};
var getSelectedTileProp = function (selectedTile, k) {
var _a, _b, _c, _d, _e;
var blockId = (_a = selectedTile === null || selectedTile === void 0 ? void 0 : selectedTile.split("_")) === null || _a === void 0 ? void 0 : _a[0];
var type = (_b = selectedTile === null || selectedTile === void 0 ? void 0 : selectedTile.split("_")) === null || _b === void 0 ? void 0 : _b[1];
return (_e = (_d = (_c = dashboard === null || dashboard === void 0 ? void 0 : dashboard.items) === null || _c === void 0 ? void 0 : _c.find(function (item) { return item.chatItem.blockId === blockId && item.type === type; })) === null || _d === void 0 ? void 0 : _d.chatItem) === null || _e === void 0 ? void 0 : _e[k];
};
var getAggregate = function (item) {
var _a, _b, _c, _d, _e, _f;
if (item.type === "graph") {
var yCol_1 = (_d = (_c = (_b = (_a = item.chatItem) === null || _a === void 0 ? void 0 : _a.graph) === null || _b === void 0 ? void 0 : _b.yCols) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.yCol;
var total_1 = 0.0;
(_f = (_e = item === null || item === void 0 ? void 0 : item.chatItem) === null || _e === void 0 ? void 0 : _e.rows) === null || _f === void 0 ? void 0 : _f.forEach(function (row) {
if (!isNaN(row[yCol_1])) {
total_1 += parseFloat(row[yCol_1]);
}
});
return dataFormater(total_1);
}
return "";
};
return (_jsxs("div", __assign({ className: classes.root, ref: containerRef }, { children: [_jsx(Backdrop, __assign({ sx: { color: "#fff", zIndex: function (theme) { return theme.zIndex.drawer + 1; } }, open: loadingDashboard || patchingDashboard }, { children: _jsx(CircularProgress, { sx: { color: brandColor } }) })), _jsxs("div", __assign({ className: classes.header }, { children: [_jsxs("div", __assign({ className: classes.content }, { children: [_jsx("div", __assign({ className: classes.title }, { children: dashboard === null || dashboard === void 0 ? void 0 : dashboard.title })), _jsx("div", __assign({ className: classes.description }, { children: dashboard === null || dashboard === void 0 ? void 0 : dashboard.description }))] })), _jsx(Button, __assign({ onClick: updateCharts, variant: "contained", size: "small" }, { children: "Save Dashboard" }))] })), _jsx(TextField, { onClick: function () {
setChatId(v4());
setChatDialog(true);
}, sx: {
width: "calc(100% - 48px)",
padding: "36px 12px 4px 36px",
"& .MuiOutlinedInput-root": {
"&.Mui-focused fieldset": {
borderColor: brandColor,
borderWidth: 1,
},
},
}, placeholder: "Add new metric, ask in plain english to get started...", InputProps: {
autoFocus: true,
style: {
height: 44,
borderRadius: "12px",
border: "1px solid #4B0082",
background: "#FFF",
boxShadow: "0px 2px 2px 0px #4B0082",
},
endAdornment: (_jsx(InputAdornment, __assign({ position: "end" }, { children: addingChat ? (_jsx(CircularProgress, { size: 20, sx: { color: brandColor } })) : (_jsx(IconButton, __assign({ className: classes.iconButton, style: { rotate: "-40deg", marginTop: "-5px" } }, { children: _jsx(SendRounded, {}) }))) }))),
} }), _jsx(Responsive, __assign({ rowHeight: 60, onLayoutChange: handleLayoutChange, breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }, width: containerWidth, margin: [40, 40], containerPadding: [40, 40], className: classes.gridContainer, resizeHandles: ["se"] }, { children: (_c = dashboard === null || dashboard === void 0 ? void 0 : dashboard.items) === null || _c === void 0 ? void 0 : _c.map(function (item, index) {
var _a, _b, _c, _d, _e, _f, _g, _h;
return (_jsxs("div", __assign({ "data-grid": {
x: item === null || item === void 0 ? void 0 : item.x,
y: item === null || item === void 0 ? void 0 : item.y,
w: item.width,
h: item.height,
}, className: classes.newTile }, { children: [_jsxs("div", __assign({ className: classes.top }, { children: [_jsx(TextField, { value: (_a = item.chatItem) === null || _a === void 0 ? void 0 : _a.title, size: "small", sx: {
width: "60%",
"& .MuiOutlinedInput-root": {
input: {
padding: "4px 0px 4px 2px",
},
fieldset: {
borderWidth: 0,
},
"&:hover fieldset": {
borderColor: "#666",
borderWidth: 0.5,
},
"&.Mui-focused fieldset": {
borderColor: "#666",
borderWidth: 0.5,
},
},
}, InputProps: {
sx: {
fontSize: 14,
fontWeight: 500,
color: "#666",
},
}, placeholder: "title", onChange: function (e) {
return updateItemBlock("title", item.chatItem.blockId, item.type, e.target.value);
} }), _jsx(IconButton, __assign({ className: classes.iconButtonSmall, onClick: function (e) {
return handleClick(e, item.chatItem.blockId + "_" + item.type);
} }, { children: _jsx(MoreVertRounded, {}) }))] })), _jsx("div", __assign({ className: classes.subTitle }, { children: ((_b = item === null || item === void 0 ? void 0 : item.chatItem) === null || _b === void 0 ? void 0 : _b.value)
? dataFormater((_d = (_c = item.chatItem) === null || _c === void 0 ? void 0 : _c.rows) === null || _d === void 0 ? void 0 : _d[0][(_e = item.chatItem) === null || _e === void 0 ? void 0 : _e.value])
: getAggregate(item) })), (item === null || item === void 0 ? void 0 : item.type) === "graph" ? (_jsx(Graphs, { rows: (_f = item.chatItem) === null || _f === void 0 ? void 0 : _f.rows, options: (_g = item.chatItem) === null || _g === void 0 ? void 0 : _g.graph })) : (item === null || item === void 0 ? void 0 : item.type) === "table" ? (_jsx(RowsView, { rows: (_h = item.chatItem) === null || _h === void 0 ? void 0 : _h.rows, blockId: item.chatItem.blockId, showExport: false, gridHeight: (item === null || item === void 0 ? void 0 : item.height) ? item.height * 4.5 + "rem" : "40vh" })) : (_jsx(_Fragment, {}))] }), item.chatItem.blockId + "_" + (item === null || item === void 0 ? void 0 : item.type)));
}) })), _jsxs(Dialog, __assign({ open: showTables, onClose: function () { return setShowTables(false); }, className: classes.dialog, classes: { paper: classes.paper } }, { children: [_jsxs(DialogTitle, { children: [_jsx("div", __assign({ className: classes.title }, { children: "Data" })), _jsx(IconButton, __assign({ style: { position: "absolute", top: 12, right: 12 }, onClick: function () { return setShowTables(false); } }, { children: _jsx(CloseRounded, { style: { fontSize: "16px" } }) }))] }), _jsx(DialogContent, __assign({ className: classes.content }, { children: _jsx(RowsView, { rows: getSelectedTileProp(selectedTile, "rows"), blockId: selectedTile }) }))] })), _jsxs(Dialog, __assign({ open: showSql, onClose: function () { return setShowSql(false); }, className: classes.dialog, classes: { paper: classes.paper } }, { children: [_jsxs(DialogTitle, { children: [_jsx("div", __assign({ className: classes.title }, { children: "SQL Query" })), _jsx(IconButton, __assign({ style: { position: "absolute", top: 12, right: 12 }, onClick: function () { return setShowSql(false); } }, { children: _jsx(CloseRounded, { style: { fontSize: "16px" } }) }))] }), _jsx(DialogContent, __assign({ className: classes.content }, { children: _jsx("div", __assign({ className: classes.header }, { children: _jsx(Button, __assign({ className: classes.textButton, size: "small", onClick: function (e) {
updateItem("sql");
}, startIcon: patchingItem ? (_jsx(CircularProgress, { sx: { color: brandColor }, size: 12 })) : (_jsx(PlayArrowRounded, { style: { fontSize: 18 } })) }, { children: "Rerun" })) })) }))] })), _jsxs(Dialog, __assign({ open: openChatDialog, onClose: function () { return setChatDialog(false); }, className: classes.chatDialog, classes: { paper: classes.paper } }, { children: [_jsx(Backdrop, __assign({ sx: {
color: "#fff",
zIndex: function (theme) { return theme.zIndex.drawer + 1; },
}, open: loadingDetails }, { children: _jsx(CircularProgress, { sx: { color: brandColor } }) })), _jsx(Chats, { email: userId, chatId: chatId, dashboardId: dashboardId, connections: connections, chatDetails: chatDetails, loadingDetails: loadingDetails, refetch: refetch, addChat: addChat, addingChat: addingChat, patchChat: patchChat, patchingChat: patchingChat, dashboards: dashboards, updateDashboard: updateDashboard, updatingDashboard: updatingDashboard, connection: connection, activeConnection: activeConnection, refetchConnection: refetchConnection })] })), _jsx(Popover, __assign({ id: "more-options-popper", open: openPopover, anchorEl: anchorEl, className: classes.morePopover, classes: { paper: classes.paper }, onClose: handleClose, anchorOrigin: {
vertical: "bottom",
horizontal: "right",
}, transformOrigin: {
vertical: "top",
horizontal: "right",
} }, { children: _jsxs("div", __assign({ className: classes.list }, { children: [(selectedTile === null || selectedTile === void 0 ? void 0 : selectedTile.includes("graph")) && (_jsx(Button, __assign({ variant: "text", size: "small", onClick: function (e) {
handleGraphClick(e);
handleClose();
} }, { children: "Edit Block" }))), _jsx(Button, __assign({ variant: "text", size: "small", onClick: function () {
setShowTables(true);
handleClose();
} }, { children: "Underlying Data" })), _jsx(Button, __assign({ variant: "text", size: "small", onClick: deleteChart }, { children: "Delete" }))] })) })), _jsx(Popover, __assign({ id: "graph-edit-dashboard", open: openGraphPopover, anchorEl: anchorElGraph, className: classes.graphPopper, classes: { paper: classes.paper }, onClose: handleGraphClose, anchorOrigin: {
vertical: "bottom",
horizontal: "right",
}, transformOrigin: {
vertical: "top",
horizontal: "right",
} }, { children: _jsx(TextField, { value: currentGraphText, onChange: function (e) { return setCurrentGraphText(e.target.value); }, onKeyDown: handleGraphEnterEvent, sx: {
"& .MuiOutlinedInput-root": {
"&.Mui-focused fieldset": {
border: "transparent",
},
fieldset: {
border: "transparent",
},
},
}, placeholder: "convert it to line, area, bar...", InputProps: {
style: {
height: 36,
width: 400,
},
endAdornment: (_jsx(InputAdornment, __assign({ position: "end" }, { children: patchingItem ? (_jsx(CircularProgress, { size: 16, sx: { color: brandColor } })) : (_jsx(IconButton, __assign({ onClick: function () { return updateItem("graph"); }, className: classes.iconButton }, { children: _jsx(SendRounded, {}) }))) }))),
} }) }))] })));
}