UNPKG

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
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, {}) }))) }))), } }) }))] }))); }