bananas-commerce-admin 0.17.20 → 0.17.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/esm/components/ActionMenu/ActionMenuItem.js +2 -2
  2. package/dist/esm/components/ActionMenu/ActionMenuItem.js.map +1 -1
  3. package/dist/esm/components/ActionMenu/index.js +23 -3
  4. package/dist/esm/components/ActionMenu/index.js.map +1 -1
  5. package/dist/esm/components/Chart.js +49 -0
  6. package/dist/esm/components/Chart.js.map +1 -0
  7. package/dist/esm/components/Icons/AreaChartIcon.js +7 -0
  8. package/dist/esm/components/Icons/AreaChartIcon.js.map +1 -0
  9. package/dist/esm/components/StatsDataTable.js +94 -0
  10. package/dist/esm/components/StatsDataTable.js.map +1 -0
  11. package/dist/esm/components/Table/TableHead.js +3 -3
  12. package/dist/esm/components/Table/TableHead.js.map +1 -1
  13. package/dist/esm/components/TitleBar/index.js +5 -2
  14. package/dist/esm/components/TitleBar/index.js.map +1 -1
  15. package/dist/esm/components/charts/LineChart.js +2 -1
  16. package/dist/esm/components/charts/LineChart.js.map +1 -1
  17. package/dist/esm/extensions/pos/contrib/PurchaseCountWidget.js +2 -2
  18. package/dist/esm/extensions/pos/contrib/PurchaseCountWidget.js.map +1 -1
  19. package/dist/esm/util/format_date.js +23 -0
  20. package/dist/esm/util/format_date.js.map +1 -0
  21. package/dist/types/components/ActionMenu/ActionMenuItem.d.ts +1 -1
  22. package/dist/types/components/Chart.d.ts +16 -0
  23. package/dist/types/components/Icons/AreaChartIcon.d.ts +4 -0
  24. package/dist/types/components/StatsDataTable.d.ts +11 -0
  25. package/dist/types/components/Table/TableHead.d.ts +2 -0
  26. package/dist/types/components/charts/LineChart.d.ts +1 -0
  27. package/dist/types/types/index.d.ts +1 -0
  28. package/dist/types/util/format_date.d.ts +2 -0
  29. package/package.json +1 -1
  30. package/src/components/ActionMenu/ActionMenuItem.tsx +3 -3
  31. package/src/components/ActionMenu/index.tsx +30 -3
  32. package/src/components/Chart.tsx +117 -0
  33. package/src/components/Icons/AreaChartIcon.tsx +19 -0
  34. package/src/components/StatsDataTable.tsx +152 -0
  35. package/src/components/Table/TableHead.tsx +10 -3
  36. package/src/components/TitleBar/index.tsx +8 -2
  37. package/src/components/charts/LineChart.tsx +3 -0
  38. package/src/extensions/pos/contrib/PurchaseCountWidget.tsx +6 -4
  39. package/src/types/index.ts +1 -1
  40. package/src/util/format_date.ts +28 -0
@@ -4,8 +4,8 @@ import { ListItemIcon, ListItemText, MenuItem } from "@mui/material";
4
4
  import Logo from "../Logo";
5
5
  export const ActionMenuItem = ({ operation, onAction }) => {
6
6
  const handleClick = useCallback(() => {
7
- onAction(operation.id);
8
- }, [operation.id, onAction]);
7
+ onAction(operation);
8
+ }, [operation, onAction]);
9
9
  return (React.createElement(MenuItem, { onClick: handleClick },
10
10
  operation.component?.icon && (React.createElement(ListItemIcon, { sx: { width: 20 } },
11
11
  React.createElement(Logo, { src: operation.component.icon }))),
@@ -1 +1 @@
1
- {"version":3,"file":"ActionMenuItem.js","sourceRoot":"","sources":["../../../../src/components/ActionMenu/ActionMenuItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,IAAI,MAAM,SAAS,CAAC;AAO3B,MAAM,CAAC,MAAM,cAAc,GAAkC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;IACvF,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE7B,OAAO,CACL,oBAAC,QAAQ,IAAC,OAAO,EAAE,WAAW;QAC3B,SAAS,CAAC,SAAS,EAAE,IAAI,IAAI,CAC5B,oBAAC,YAAY,IAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YAC7B,oBAAC,IAAI,IAAC,GAAG,EAAE,SAAS,CAAC,SAAS,CAAC,IAAI,GAAI,CAC1B,CAChB;QACD,oBAAC,YAAY,QAAE,SAAS,CAAC,SAAS,EAAE,KAAK,IAAI,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,EAAE,CAAgB,CACrF,CACZ,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,IAAI,CAAC,cAAc,CAAC,CAAC"}
1
+ {"version":3,"file":"ActionMenuItem.js","sourceRoot":"","sources":["../../../../src/components/ActionMenu/ActionMenuItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,IAAI,MAAM,SAAS,CAAC;AAO3B,MAAM,CAAC,MAAM,cAAc,GAAkC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;IACvF,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACtB,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE1B,OAAO,CACL,oBAAC,QAAQ,IAAC,OAAO,EAAE,WAAW;QAC3B,SAAS,CAAC,SAAS,EAAE,IAAI,IAAI,CAC5B,oBAAC,YAAY,IAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YAC7B,oBAAC,IAAI,IAAC,GAAG,EAAE,SAAS,CAAC,SAAS,CAAC,IAAI,GAAI,CAC1B,CAChB;QACD,oBAAC,YAAY,QAAE,SAAS,CAAC,SAAS,EAAE,KAAK,IAAI,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,EAAE,CAAgB,CACrF,CACZ,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,IAAI,CAAC,cAAc,CAAC,CAAC"}
@@ -7,12 +7,16 @@ import Menu from "@mui/material/Menu";
7
7
  import { enqueueSnackbar } from "notistack";
8
8
  import { useApi } from "../../contexts/ApiContext";
9
9
  import { useI18n } from "../../contexts/I18nContext";
10
+ import { useUser } from "../../contexts/UserContext";
11
+ import { hasAccess } from "../../util/has_access";
10
12
  import { usePage } from "../Page";
11
13
  import ActionMenuItem from "./ActionMenuItem";
12
14
  export const ActionMenu = () => {
13
15
  const [anchorEl, setAnchorEl] = useState(null);
16
+ const [renderedComponent, setRenderedComponent] = useState();
14
17
  const params = useParams();
15
18
  const page = usePage();
19
+ const { user } = useUser();
16
20
  const api = useApi();
17
21
  const { t } = useI18n();
18
22
  const title = useCallback((operation) => t(operation.component?.title ?? operation.summary ?? operation.id), [t]);
@@ -24,8 +28,17 @@ export const ActionMenu = () => {
24
28
  setAnchorEl(null);
25
29
  };
26
30
  const handleAction = async (operation) => {
31
+ if (operation.component != null) {
32
+ let component = operation.component.component;
33
+ setAnchorEl(null);
34
+ if (component instanceof Promise) {
35
+ component = await component;
36
+ }
37
+ setRenderedComponent(() => component);
38
+ return;
39
+ }
27
40
  try {
28
- const action = api.operations[operation];
41
+ const action = api.operations[operation.id];
29
42
  const response = await action.call({ params });
30
43
  if (response.ok) {
31
44
  enqueueSnackbar(t(`Completed successfully: ${title(action)}`), {
@@ -55,12 +68,19 @@ export const ActionMenu = () => {
55
68
  },
56
69
  },
57
70
  }, onClose: handleClose }, page?.contrib
58
- .filter((operation) => operation.component?.variant === "action")
71
+ .filter((operation) => operation.component?.variant === "action" &&
72
+ hasAccess(user, operation.component.permission, operation.component.group))
59
73
  .map((operation) => (React.createElement(ActionMenuItem, { key: operation.id, operation: operation, onAction: handleAction })))),
60
74
  React.createElement(Button, { "aria-haspopup": true, disableElevation: true, "aria-expanded": open ? "true" : "false", endIcon: React.createElement(KeyboardArrowDownIcon, null), sx: {
61
75
  borderRadius: 6,
62
76
  height: 46,
63
- }, variant: "outlined", onClick: handleClick }, "Actions")));
77
+ }, variant: "outlined", onClick: handleClick }, "Actions"),
78
+ renderedComponent &&
79
+ React.createElement(renderedComponent, {
80
+ close: () => setRenderedComponent(undefined),
81
+ data: {},
82
+ refresh: () => { },
83
+ })));
64
84
  };
65
85
  export default ActionMenu;
66
86
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/ActionMenu/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/ActionMenu/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import React, { useCallback, useState } from "react";
2
+ import { BarChartRounded, ShowChartRounded, TableRowsRounded } from "@mui/icons-material";
3
+ import { ToggleButton, ToggleButtonGroup, Tooltip } from "@mui/material";
4
+ import { useDashboardFilter } from "../contexts/DashboardFilterContext";
5
+ import { useI18n } from "../contexts/I18nContext";
6
+ import BarChart from "./charts/BarChart";
7
+ import LineChart from "./charts/LineChart";
8
+ import AreaChartIcon from "./Icons/AreaChartIcon";
9
+ import StatsDataTable from "./StatsDataTable";
10
+ const chartData = {
11
+ line: {
12
+ Icon: ShowChartRounded,
13
+ name: "Line Chart",
14
+ },
15
+ area: {
16
+ Icon: AreaChartIcon,
17
+ name: "Area Chart",
18
+ },
19
+ bar: {
20
+ Icon: BarChartRounded,
21
+ name: "Bar Chart",
22
+ },
23
+ table: {
24
+ Icon: TableRowsRounded,
25
+ name: "Table",
26
+ },
27
+ };
28
+ export default function Chart({ data, charts, dataTable = true, dataKeyX, dataKeyY, csvFileName, }) {
29
+ const { t } = useI18n();
30
+ const { filter } = useDashboardFilter();
31
+ const [selectedChart, setSelectedChart] = useState(charts[0]);
32
+ const chartsWithTable = dataTable ? [...charts, "table"] : charts;
33
+ const handleSelectedChartChange = useCallback((_, newChart) => {
34
+ if (newChart !== null) {
35
+ setSelectedChart(newChart);
36
+ }
37
+ }, []);
38
+ return (React.createElement(React.Fragment, null,
39
+ chartsWithTable.length > 1 && (React.createElement(ToggleButtonGroup, { exclusive: true, sx: { position: "absolute", right: 16, top: 16 }, unselectable: "off", value: selectedChart, onChange: handleSelectedChartChange }, chartsWithTable.map((chart) => {
40
+ const { Icon, name } = chartData[chart];
41
+ return (React.createElement(Tooltip, { key: chart, title: t(name) },
42
+ React.createElement(ToggleButton, { size: "small", value: chart },
43
+ React.createElement(Icon, { fontSize: "small" }))));
44
+ }))),
45
+ selectedChart === "bar" && (React.createElement(BarChart, { dataKeyX: dataKeyX, dataKeyY: dataKeyY, dataset: data.map(({ date, ...props }) => ({ ...props, date: new Date(date) })), granularity: filter.granularity })),
46
+ (selectedChart === "line" || selectedChart === "area") && (React.createElement(LineChart, { area: selectedChart === "area", dataKeyX: dataKeyX, dataKeyY: dataKeyY, dataset: data.map(({ date, ...props }) => ({ ...props, date: new Date(date) })), granularity: filter.granularity })),
47
+ selectedChart === "table" && (React.createElement(StatsDataTable, { csvFileName: csvFileName, data: data, dateKey: dataKeyX }))));
48
+ }
49
+ //# sourceMappingURL=Chart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Chart.js","sourceRoot":"","sources":["../../../src/components/Chart.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ import { SvgIcon } from "@mui/material";
3
+ const AreaChartIcon = (props) => (React.createElement(SvgIcon, { ...props, viewBox: "0 0 24 24" },
4
+ React.createElement("path", { d: "M3 17L9 10L14 15L21 7V15Q21 17 19 17H3Z", fill: "currentColor", opacity: "0.4" }),
5
+ React.createElement("path", { d: "M4 16L9 10L14 15L20 8", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2" })));
6
+ export default AreaChartIcon;
7
+ //# sourceMappingURL=AreaChartIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AreaChartIcon.js","sourceRoot":"","sources":["../../../../src/components/Icons/AreaChartIcon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,OAAO,EAAgB,MAAM,eAAe,CAAC;AAEtD,MAAM,aAAa,GAAG,CAAC,KAAmB,EAAE,EAAE,CAAC,CAC7C,oBAAC,OAAO,OAAK,KAAK,EAAE,OAAO,EAAC,WAAW;IACrC,8BAAM,CAAC,EAAC,yCAAyC,EAAC,IAAI,EAAC,cAAc,EAAC,OAAO,EAAC,KAAK,GAAG;IACtF,8BACE,CAAC,EAAC,uBAAuB,EACzB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,WAAW,EAAC,GAAG,GACf,CACM,CACX,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,94 @@
1
+ import React, { useCallback, useMemo } from "react";
2
+ import { Button, Stack, TableBody, TableRow } from "@mui/material";
3
+ import { useDashboardFilter } from "../contexts/DashboardFilterContext";
4
+ import { formatDate } from "../util/format_date";
5
+ import { TableCell } from "./Table/TableCell";
6
+ import TableHead from "./Table/TableHead";
7
+ import TableHeading from "./Table/TableHeading";
8
+ import Table from "./Table";
9
+ export default function StatsDataTable({ data, dateKey, csvFileName }) {
10
+ const { filter } = useDashboardFilter();
11
+ const mappedData = useMemo(() => {
12
+ return data
13
+ .map((item) => {
14
+ const dateEntry = getDateEntry(item, dateKey);
15
+ if (dateEntry === undefined)
16
+ return undefined;
17
+ const [key, date] = dateEntry;
18
+ const { [key]: _, ...rest } = item;
19
+ return { [key]: date, ...rest };
20
+ })
21
+ .filter((item) => item !== undefined);
22
+ }, [data, dateKey]);
23
+ const handleExportToCSV = useCallback(() => {
24
+ if (mappedData.length === 0)
25
+ return;
26
+ const headers = Object.keys(mappedData[0]);
27
+ const csvRows = [
28
+ headers.join(","), // Header row
29
+ ...mappedData.map((row) => headers
30
+ .map((key) => {
31
+ const value = row[key];
32
+ if (value instanceof Date)
33
+ return `"${value.toISOString()}"`;
34
+ if (typeof value === "string")
35
+ return `"${value.replace(/"/g, '""')}"`; // Escape quotes
36
+ return value;
37
+ })
38
+ .join(",")),
39
+ ];
40
+ const csvContent = csvRows.join("\n");
41
+ const blob = new Blob([csvContent], { type: "text/csv" });
42
+ const url = URL.createObjectURL(blob);
43
+ const link = document.createElement("a");
44
+ link.href = url;
45
+ link.download = `${csvFileName || "data"}_${filter.startDate.toISO()?.split("T")[0]}_${filter.endDate.toISO()?.split("T")[0]}.csv`;
46
+ document.body.appendChild(link);
47
+ link.click();
48
+ document.body.removeChild(link);
49
+ URL.revokeObjectURL(url);
50
+ }, [mappedData, filter.startDate, filter.endDate, filter.granularity]);
51
+ return (React.createElement(Stack, { maxHeight: 300 },
52
+ React.createElement(Table, { count: mappedData.length },
53
+ React.createElement(TableHead, { tableRowProps: {
54
+ sx: {
55
+ position: "sticky",
56
+ top: 0,
57
+ bgcolor: "background.paper",
58
+ backgroundImage: "var(--Paper-overlay)",
59
+ boxShadow: "inset 0 -1px var(--mui-palette-divider)",
60
+ },
61
+ } }, mappedData.length > 0 &&
62
+ Object.keys(mappedData[0]).map((key) => {
63
+ return React.createElement(TableHeading, { key: key }, formatKey(key));
64
+ })),
65
+ React.createElement(TableBody, { sx: { overflowY: "auto" } }, mappedData.map((item, i) => (React.createElement(TableRow, { key: i }, Object.entries(item).map(([key, value]) => (React.createElement(TableCell, { key: key, sx: { borderBottomWidth: i === mappedData.length - 1 ? 0 : 1 } }, value instanceof Date ? formatDate(value, filter.granularity) : value.toString())))))))),
66
+ React.createElement(Stack, { alignItems: "flex-end", pt: 2, px: 2, spacing: 1, sx: { borderTop: "1px solid", borderColor: "divider" } },
67
+ React.createElement(Button, { color: "inherit", variant: "outlined", onClick: handleExportToCSV }, "Export to CSV"))));
68
+ }
69
+ function formatKey(key) {
70
+ return key
71
+ .split("_")
72
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
73
+ .join(" ");
74
+ }
75
+ function getDateEntry(item, dateKey) {
76
+ if (dateKey !== undefined && item.hasOwnProperty(dateKey)) {
77
+ let date = item[dateKey];
78
+ date = typeof date === "string" ? new Date(date) : date;
79
+ if (!(date instanceof Date))
80
+ return undefined;
81
+ return [dateKey, date];
82
+ }
83
+ const dateEntry = Object.entries(item).find(([_, value]) => isDateOrString(value));
84
+ if (dateEntry === undefined) {
85
+ return undefined;
86
+ }
87
+ const dateObj = dateEntry[1] instanceof Date ? dateEntry[1] : new Date(dateEntry[1]);
88
+ return [dateEntry[0], dateObj];
89
+ }
90
+ function isDateOrString(value) {
91
+ return ((value instanceof Date && !Number.isNaN(value.getTime())) ||
92
+ (typeof value === "string" && !Number.isNaN(Date.parse(value))));
93
+ }
94
+ //# sourceMappingURL=StatsDataTable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatsDataTable.js","sourceRoot":"","sources":["../../../src/components/StatsDataTable.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
- import { Stack, TableHead as MuiTableHead, TableRow, Typography } from "@mui/material";
3
- export const TableHead = ({ children, icon, title }) => (React.createElement(MuiTableHead, null,
2
+ import { Stack, TableHead as MuiTableHead, TableRow, Typography, } from "@mui/material";
3
+ export const TableHead = ({ children, icon, title, tableRowProps }) => (React.createElement(MuiTableHead, null,
4
4
  title != null && (React.createElement(Stack, { alignItems: "center", direction: "row", gap: 1, p: 2, pb: 0, sx: {
5
5
  color: "text.primary",
6
6
  wordSpacing: "6px",
@@ -8,6 +8,6 @@ export const TableHead = ({ children, icon, title }) => (React.createElement(Mui
8
8
  } },
9
9
  icon,
10
10
  React.createElement(Typography, { fontWeight: 600, variant: "body1" }, title))),
11
- React.createElement(TableRow, null, children)));
11
+ React.createElement(TableRow, { ...tableRowProps }, children)));
12
12
  export default TableHead;
13
13
  //# sourceMappingURL=TableHead.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TableHead.js","sourceRoot":"","sources":["../../../../src/components/Table/TableHead.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,SAAS,IAAI,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAOvF,MAAM,CAAC,MAAM,SAAS,GAA6B,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAChF,oBAAC,YAAY;IACV,KAAK,IAAI,IAAI,IAAI,CAChB,oBAAC,KAAK,IACJ,UAAU,EAAC,QAAQ,EACnB,SAAS,EAAC,KAAK,EACf,GAAG,EAAE,CAAC,EACN,CAAC,EAAE,CAAC,EACJ,EAAE,EAAE,CAAC,EACL,EAAE,EAAE;YACF,KAAK,EAAE,cAAc;YACrB,WAAW,EAAE,KAAK;YAClB,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;SACnC;QAEA,IAAI;QACL,oBAAC,UAAU,IAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAC,OAAO,IACzC,KAAK,CACK,CACP,CACT;IAED,oBAAC,QAAQ,QAAE,QAAQ,CAAY,CAClB,CAChB,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"TableHead.js","sourceRoot":"","sources":["../../../../src/components/Table/TableHead.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EACL,KAAK,EACL,SAAS,IAAI,YAAY,EACzB,QAAQ,EAER,UAAU,GACX,MAAM,eAAe,CAAC;AAQvB,MAAM,CAAC,MAAM,SAAS,GAA6B,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAC/F,oBAAC,YAAY;IACV,KAAK,IAAI,IAAI,IAAI,CAChB,oBAAC,KAAK,IACJ,UAAU,EAAC,QAAQ,EACnB,SAAS,EAAC,KAAK,EACf,GAAG,EAAE,CAAC,EACN,CAAC,EAAE,CAAC,EACJ,EAAE,EAAE,CAAC,EACL,EAAE,EAAE;YACF,KAAK,EAAE,cAAc;YACrB,WAAW,EAAE,KAAK;YAClB,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;SACnC;QAEA,IAAI;QACL,oBAAC,UAAU,IAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAC,OAAO,IACzC,KAAK,CACK,CACP,CACT;IAED,oBAAC,QAAQ,OAAK,aAAa,IAAG,QAAQ,CAAY,CACrC,CAChB,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -5,6 +5,8 @@ import NavigateNextIcon from "@mui/icons-material/NavigateNext";
5
5
  import { AppBar, Breadcrumbs, IconButton, Link, Stack, Toolbar, Typography, } from "@mui/material";
6
6
  import { useI18n } from "../../contexts/I18nContext";
7
7
  import { useRouter } from "../../contexts/RouterContext";
8
+ import { useUser } from "../../contexts/UserContext";
9
+ import { hasAccess } from "../../util/has_access";
8
10
  import ActionMenu from "../ActionMenu";
9
11
  import { usePage } from "../Page";
10
12
  export const TitleBar = ({ back = false, title, children, ...props }) => {
@@ -12,6 +14,7 @@ export const TitleBar = ({ back = false, title, children, ...props }) => {
12
14
  const { navigate, getCurrent, routes } = useRouter();
13
15
  const routerNavigate = useNavigate();
14
16
  const page = usePage();
17
+ const { user } = useUser();
15
18
  if (typeof back === "boolean" && back)
16
19
  back = -1;
17
20
  const { route: currentRoute } = getCurrent();
@@ -39,8 +42,8 @@ export const TitleBar = ({ back = false, title, children, ...props }) => {
39
42
  React.createElement(Link, { key: "home", color: "inherit", underline: "hover", onClick: () => routerNavigate("/", { replace: true }) }, t("Home")),
40
43
  breadcrumbRoutes.map((route) => (React.createElement(Link, { key: route.id, color: "inherit", underline: "hover", onClick: () => navigate(route) }, route.title)))))),
41
44
  children,
42
- page?.contrib.filter((operation) => operation.component?.variant === "action").length >
43
- 0 && (React.createElement(Stack, { width: "fit-content" },
45
+ page?.contrib.filter((operation) => operation.component?.variant === "action" &&
46
+ hasAccess(user, operation.component.permission, operation.component.group)).length > 0 && (React.createElement(Stack, { width: "fit-content" },
44
47
  React.createElement(ActionMenu, null))))));
45
48
  };
46
49
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/TitleBar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,aAAa,MAAM,+BAA+B,CAAC;AAC1D,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAChE,OAAO,EACL,MAAM,EAEN,WAAW,EACX,UAAU,EACV,IAAI,EACJ,KAAK,EACL,OAAO,EACP,UAAU,GACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAa,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,UAAU,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAOlC,MAAM,CAAC,MAAM,QAAQ,GAA4B,CAAC,EAAE,IAAI,GAAG,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE;IAC/F,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC;IACxB,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IACrD,MAAM,cAAc,GAAG,WAAW,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,IAAI,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI;QAAE,IAAI,GAAG,CAAC,CAAC,CAAC;IAEjD,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,UAAU,EAAG,CAAC;IAC9C,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CACpC,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,EAAE,KAAK,YAAY,CAAC,EAAE;QAC5B,KAAK,CAAC,MAAM,KAAK,MAAM;QACvB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAC3C,CAAC;IAEF,OAAO,CACL,oBAAC,MAAM,IAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAC,QAAQ,EAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,KAAM,KAAK;QAC5F,oBAAC,OAAO,IACN,EAAE,EAAE;gBACF,OAAO,EAAE,MAAM;gBACf,KAAK,EAAE,MAAM;gBACb,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE;gBACrB,aAAa,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE;gBAC1C,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;aACzB,EACD,OAAO,EAAC,OAAO;YAEf,oBAAC,KAAK,IAAC,UAAU,EAAC,QAAQ,EAAC,SAAS,EAAC,KAAK,EAAC,QAAQ,EAAE,CAAC;gBACnD,IAAI,CAAC,CAAC,CAAC,CACN,oBAAC,UAAU,kBACE,MAAM,EACjB,KAAK,EAAC,SAAS,EACf,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,OAAO,EACZ,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,eAAe,EAAE,kBAAkB,EAAE,EACpD,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAmC,CAAC;oBAE5D,oBAAC,aAAa,OAAG,CACN,CACd,CAAC,CAAC,CAAC,IAAI;gBAER,oBAAC,KAAK;oBACH,KAAK,CAAC,CAAC,CAAC,CACP,oBAAC,UAAU,IAAC,KAAK,EAAC,cAAc,EAAC,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,OAAO,EAAC,IAAI,IACnE,KAAK,CACK,CACd,CAAC,CAAC,CAAC,IAAI;oBAER,oBAAC,WAAW,kBACC,aAAa,EACxB,SAAS,EAAE,oBAAC,gBAAgB,IAAC,QAAQ,EAAC,SAAS,GAAG,EAClD,EAAE,EAAE;4BACF,QAAQ,EAAE,QAAQ;4BAClB,2BAA2B,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE;4BACxC,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;yBACzB;wBAED,oBAAC,IAAI,IACH,GAAG,EAAC,MAAM,EACV,KAAK,EAAC,SAAS,EACf,SAAS,EAAC,OAAO,EACjB,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,IAEpD,CAAC,CAAC,MAAM,CAAC,CACL;wBAEN,gBAAgB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAC/B,oBAAC,IAAI,IACH,GAAG,EAAE,KAAK,CAAC,EAAE,EACb,KAAK,EAAC,SAAS,EACf,SAAS,EAAC,OAAO,EACjB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAE7B,KAAK,CAAC,KAAK,CACP,CACR,CAAC,CACU,CACR,CACF;YACP,QAAQ;YACR,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,MAAM;gBACpF,CAAC,IAAI,CACL,oBAAC,KAAK,IAAC,KAAK,EAAC,aAAa;gBACxB,oBAAC,UAAU,OAAG,CACR,CACT,CACO,CACH,CACV,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/TitleBar/index.tsx"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@ const StyledLineChart = styled(MuiLineChart, {
11
11
  stroke: theme.palette.divider,
12
12
  },
13
13
  }));
14
- export const LineChart = ({ dataset, series, dataKeyX, dataKeyY, height = 300, granularity = "day", yAxisOptions, legendProps, }) => {
14
+ export const LineChart = ({ dataset, series, dataKeyX, dataKeyY, height = 300, area, granularity = "day", yAxisOptions, legendProps, }) => {
15
15
  const theme = useTheme();
16
16
  return (React.createElement(StyledLineChart, { dataset: dataset, grid: { horizontal: true }, height: height, series: series ?? [
17
17
  {
@@ -19,6 +19,7 @@ export const LineChart = ({ dataset, series, dataKeyX, dataKeyY, height = 300, g
19
19
  showMark: false,
20
20
  curve: "monotoneX",
21
21
  color: theme.palette.graphColorPrimary?.main ?? theme.palette.primary.main,
22
+ area,
22
23
  },
23
24
  ], slotProps: {
24
25
  legend: {
@@ -1 +1 @@
1
- {"version":3,"file":"LineChart.js","sourceRoot":"","sources":["../../../../src/components/charts/LineChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,EAAE,SAAS,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAIpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAQ5D,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,EAAE;IAC3C,IAAI,EAAE,cAAc;IACpB,IAAI,EAAE,OAAO;CACd,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACf,KAAK,CAAC,WAAW,CAAC;IAChB,0CAA0C,EAAE;QAC1C,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO;KAC9B;CACF,CAAC,CACH,CAAC;AAaF,MAAM,CAAC,MAAM,SAAS,GAA6B,CAAC,EAClD,OAAO,EACP,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,MAAM,GAAG,GAAG,EACZ,WAAW,GAAG,KAAK,EACnB,YAAY,EACZ,WAAW,GACZ,EAAE,EAAE;IACH,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IAEzB,OAAO,CACL,oBAAC,eAAe,IACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,EAC1B,MAAM,EAAE,MAAM,EACd,MAAM,EACJ,MAAM,IAAI;YACR;gBACE,OAAO,EAAE,QAAQ;gBACjB,QAAQ,EAAE,KAAK;gBACf,KAAK,EAAE,WAAW;gBAClB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI;aAC3E;SACF,EAEH,SAAS,EAAE;YACT,MAAM,EAAE;gBACN,SAAS,EAAE,KAAK;gBAChB,QAAQ,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE;gBACnD,OAAO,EAAE,CAAC;gBACV,aAAa,EAAE,EAAE;gBACjB,cAAc,EAAE,EAAE;gBAClB,OAAO,EAAE,EAAE;gBACX,UAAU,EAAE;oBACV,QAAQ,EAAE,QAAQ;iBACnB;gBACD,GAAG,WAAW;aACf;YACD,yEAAyE;YACzE,UAAU;YACV,cAAc;YACd,eAAe;YACf,+BAA+B;YAC/B,OAAO;YACP,YAAY;SACb,EACD,KAAK,EAAE;YACL;gBACE,OAAO,EAAE,QAAQ;gBACjB,UAAU,EAAE,CAAC;gBACb,SAAS,EAAE,OAAO;gBAClB,cAAc,EAAE,qBAAqB,CAAC,WAAW,CAAC;aACnD;SACF,EACD,KAAK,EAAE;YACL;gBACE,GAAG,EAAE,CAAC;gBACN,UAAU,EAAE,CAAC;gBACb,WAAW,EAAE,CAAC;gBACd,GAAG,YAAY;aAChB;SACF,GACD,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"LineChart.js","sourceRoot":"","sources":["../../../../src/components/charts/LineChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,EAAE,SAAS,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAIpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAQ5D,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,EAAE;IAC3C,IAAI,EAAE,cAAc;IACpB,IAAI,EAAE,OAAO;CACd,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACf,KAAK,CAAC,WAAW,CAAC;IAChB,0CAA0C,EAAE;QAC1C,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO;KAC9B;CACF,CAAC,CACH,CAAC;AAcF,MAAM,CAAC,MAAM,SAAS,GAA6B,CAAC,EAClD,OAAO,EACP,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,MAAM,GAAG,GAAG,EACZ,IAAI,EACJ,WAAW,GAAG,KAAK,EACnB,YAAY,EACZ,WAAW,GACZ,EAAE,EAAE;IACH,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IAEzB,OAAO,CACL,oBAAC,eAAe,IACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,EAC1B,MAAM,EAAE,MAAM,EACd,MAAM,EACJ,MAAM,IAAI;YACR;gBACE,OAAO,EAAE,QAAQ;gBACjB,QAAQ,EAAE,KAAK;gBACf,KAAK,EAAE,WAAW;gBAClB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI;gBAC1E,IAAI;aACL;SACF,EAEH,SAAS,EAAE;YACT,MAAM,EAAE;gBACN,SAAS,EAAE,KAAK;gBAChB,QAAQ,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE;gBACnD,OAAO,EAAE,CAAC;gBACV,aAAa,EAAE,EAAE;gBACjB,cAAc,EAAE,EAAE;gBAClB,OAAO,EAAE,EAAE;gBACX,UAAU,EAAE;oBACV,QAAQ,EAAE,QAAQ;iBACnB;gBACD,GAAG,WAAW;aACf;YACD,yEAAyE;YACzE,UAAU;YACV,cAAc;YACd,eAAe;YACf,+BAA+B;YAC/B,OAAO;YACP,YAAY;SACb,EACD,KAAK,EAAE;YACL;gBACE,OAAO,EAAE,QAAQ;gBACjB,UAAU,EAAE,CAAC;gBACb,SAAS,EAAE,OAAO;gBAClB,cAAc,EAAE,qBAAqB,CAAC,WAAW,CAAC;aACnD;SACF,EACD,KAAK,EAAE;YACL;gBACE,GAAG,EAAE,CAAC;gBACN,UAAU,EAAE,CAAC;gBACb,WAAW,EAAE,CAAC;gBACd,GAAG,YAAY;aAChB;SACF,GACD,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import React, { useMemo } from "react";
2
2
  import { Stack, Typography } from "@mui/material";
3
- import BarChart from "../../../components/charts/BarChart";
3
+ import Chart from "../../../components/Chart";
4
4
  import WidgetCard from "../../../components/WidgetCard";
5
5
  import { useApi } from "../../../contexts/ApiContext";
6
6
  import { useDashboardFilter } from "../../../contexts/DashboardFilterContext";
@@ -41,7 +41,7 @@ const PurchaseCountWidget = ({ data: initialData, sx }) => {
41
41
  }, [api, user]);
42
42
  return (React.createElement(React.Fragment, null,
43
43
  React.createElement(WidgetCard, { gridColumn: { md: "span 6", sm: "span 1" }, gridRow: "span 2", sx: sx, title: t(`${granularityLabel(filter.granularity)} Purchases`) },
44
- React.createElement(BarChart, { dataKeyX: "date", dataKeyY: "count", dataset: data.map(({ date, count }) => ({ date: new Date(date), count })), granularity: filter.granularity })),
44
+ React.createElement(Chart, { charts: ["bar", "area"], csvFileName: "purchase_count", data: data.map((item) => ({ ...item })), dataKeyX: "date", dataKeyY: "count", dataTable: true })),
45
45
  React.createElement(WidgetCard, { gridColumn: { md: isFourColumn ? "span 3" : "span 4", sm: "span 1" }, gridRow: "span 1", sx: sx, title: t("Purchase Count") },
46
46
  React.createElement(Stack, { direction: "column", height: "100%", px: 2 },
47
47
  React.createElement(Stack, { borderBottom: "1px solid", borderColor: "divider", height: "100%" },
@@ -1 +1 @@
1
- {"version":3,"file":"PurchaseCountWidget.js","sourceRoot":"","sources":["../../../../../src/extensions/pos/contrib/PurchaseCountWidget.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PurchaseCountWidget.js","sourceRoot":"","sources":["../../../../../src/extensions/pos/contrib/PurchaseCountWidget.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export const formatDate = (date, granularity, variant = "short", locale = "sv-SE") => {
2
+ let options = {};
3
+ if (granularity === "day") {
4
+ options = {
5
+ day: "numeric",
6
+ month: "long",
7
+ ...(variant === "long" && { year: "numeric" }),
8
+ };
9
+ }
10
+ else if (granularity === "month") {
11
+ options = {
12
+ month: "long",
13
+ year: "numeric",
14
+ };
15
+ }
16
+ else if (granularity === "year") {
17
+ options = {
18
+ year: "numeric",
19
+ };
20
+ }
21
+ return new Intl.DateTimeFormat(locale, options).format(date);
22
+ };
23
+ //# sourceMappingURL=format_date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format_date.js","sourceRoot":"","sources":["../../../src/util/format_date.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,IAAU,EACV,WAAwB,EACxB,UAA4B,OAAO,EACnC,SAAiB,OAAO,EACxB,EAAE;IACF,IAAI,OAAO,GAA+B,EAAE,CAAC;IAC7C,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,GAAG;YACR,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,MAAM;YACb,GAAG,CAAC,OAAO,KAAK,MAAM,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;SAC/C,CAAC;IACJ,CAAC;SAAM,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;QACnC,OAAO,GAAG;YACR,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,SAAS;SAChB,CAAC;IACJ,CAAC;SAAM,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAClC,OAAO,GAAG;YACR,IAAI,EAAE,SAAS;SAChB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC/D,CAAC,CAAC"}
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { ApiOperation } from "../../api";
3
3
  export interface ActionMenuItemProps {
4
4
  operation: ApiOperation;
5
- onAction: (operationId: string) => Promise<void>;
5
+ onAction: (operations: ApiOperation) => Promise<void>;
6
6
  }
7
7
  export declare const ActionMenuItem: React.FC<ActionMenuItemProps>;
8
8
  declare const _default: React.NamedExoticComponent<ActionMenuItemProps>;
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+ export type ChartType = "line" | "area" | "bar";
3
+ export type ChartsWithTableType = ChartType | "table";
4
+ export interface DataItem {
5
+ date: string;
6
+ [key: string]: string | number | boolean | Date;
7
+ }
8
+ export interface ChartProps {
9
+ data: DataItem[];
10
+ charts: ChartType[];
11
+ dataTable?: boolean;
12
+ dataKeyX: string;
13
+ dataKeyY?: string;
14
+ csvFileName?: string;
15
+ }
16
+ export default function Chart({ data, charts, dataTable, dataKeyX, dataKeyY, csvFileName, }: ChartProps): React.JSX.Element;
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import { SvgIconProps } from "@mui/material";
3
+ declare const AreaChartIcon: (props: SvgIconProps) => React.JSX.Element;
4
+ export default AreaChartIcon;
@@ -0,0 +1,11 @@
1
+ import React from "react";
2
+ interface DataItem {
3
+ [key: string]: string | number | boolean | Date;
4
+ }
5
+ interface StatsDataTableProps {
6
+ data: DataItem[];
7
+ dateKey?: string;
8
+ csvFileName?: string;
9
+ }
10
+ export default function StatsDataTable({ data, dateKey, csvFileName }: StatsDataTableProps): React.JSX.Element;
11
+ export {};
@@ -1,7 +1,9 @@
1
1
  import React, { PropsWithChildren } from "react";
2
+ import { TableRowProps } from "@mui/material";
2
3
  export interface TableHeadProps extends PropsWithChildren {
3
4
  title?: string;
4
5
  icon?: React.ReactNode;
6
+ tableRowProps?: TableRowProps;
5
7
  }
6
8
  export declare const TableHead: React.FC<TableHeadProps>;
7
9
  export default TableHead;
@@ -16,6 +16,7 @@ export interface LineChartProps {
16
16
  dataKeyX: string;
17
17
  dataKeyY?: string;
18
18
  height?: number;
19
+ area?: boolean;
19
20
  granularity?: Granularity;
20
21
  yAxisOptions?: object;
21
22
  legendProps?: ChartsLegendProps;
@@ -51,6 +51,7 @@ export interface NavigationItem {
51
51
  export type NavigationOverrides = Record<string, NavigationItem | null | undefined | false>;
52
52
  export type ContribComponent<T = any> = React.ComponentType<PageProps<T> & OpenAPI.Request & {
53
53
  sx?: SxProps;
54
+ close?: () => void;
54
55
  }>;
55
56
  /**
56
57
  * The variant of the component, either a tab, inline or action menu item.
@@ -0,0 +1,2 @@
1
+ import { Granularity } from "../types";
2
+ export declare const formatDate: (date: Date, granularity: Granularity, variant?: "short" | "long", locale?: string) => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bananas-commerce-admin",
3
- "version": "0.17.20",
3
+ "version": "0.17.22",
4
4
  "description": "What's this, an admin for apes?",
5
5
  "keywords": [
6
6
  "admin",
@@ -8,13 +8,13 @@ import Logo from "../Logo";
8
8
 
9
9
  export interface ActionMenuItemProps {
10
10
  operation: ApiOperation;
11
- onAction: (operationId: string) => Promise<void>;
11
+ onAction: (operations: ApiOperation) => Promise<void>;
12
12
  }
13
13
 
14
14
  export const ActionMenuItem: React.FC<ActionMenuItemProps> = ({ operation, onAction }) => {
15
15
  const handleClick = useCallback(() => {
16
- onAction(operation.id);
17
- }, [operation.id, onAction]);
16
+ onAction(operation);
17
+ }, [operation, onAction]);
18
18
 
19
19
  return (
20
20
  <MenuItem onClick={handleClick}>
@@ -11,14 +11,19 @@ import { enqueueSnackbar } from "notistack";
11
11
  import { ApiOperation } from "../../api";
12
12
  import { useApi } from "../../contexts/ApiContext";
13
13
  import { useI18n } from "../../contexts/I18nContext";
14
+ import { useUser } from "../../contexts/UserContext";
15
+ import { ContribComponent } from "../../types";
16
+ import { hasAccess } from "../../util/has_access";
14
17
  import { usePage } from "../Page";
15
18
 
16
19
  import ActionMenuItem from "./ActionMenuItem";
17
20
 
18
21
  export const ActionMenu: React.FC = () => {
19
22
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
23
+ const [renderedComponent, setRenderedComponent] = useState<ContribComponent>();
20
24
  const params = useParams();
21
25
  const page = usePage();
26
+ const { user } = useUser();
22
27
  const api = useApi();
23
28
  const { t } = useI18n();
24
29
  const title = useCallback(
@@ -36,9 +41,20 @@ export const ActionMenu: React.FC = () => {
36
41
  setAnchorEl(null);
37
42
  };
38
43
 
39
- const handleAction = async (operation: string) => {
44
+ const handleAction = async (operation: ApiOperation) => {
45
+ if (operation.component != null) {
46
+ let component = operation.component.component;
47
+ setAnchorEl(null);
48
+ if (component instanceof Promise) {
49
+ component = await component;
50
+ }
51
+
52
+ setRenderedComponent(() => component);
53
+ return;
54
+ }
55
+
40
56
  try {
41
- const action = api.operations[operation];
57
+ const action = api.operations[operation.id];
42
58
 
43
59
  const response = await action.call({ params });
44
60
 
@@ -76,7 +92,11 @@ export const ActionMenu: React.FC = () => {
76
92
  onClose={handleClose}
77
93
  >
78
94
  {page?.contrib
79
- .filter((operation) => operation.component?.variant === "action")
95
+ .filter(
96
+ (operation) =>
97
+ operation.component?.variant === "action" &&
98
+ hasAccess(user, operation.component.permission, operation.component.group),
99
+ )
80
100
  .map((operation) => (
81
101
  <ActionMenuItem key={operation.id} operation={operation} onAction={handleAction} />
82
102
  ))}
@@ -96,6 +116,13 @@ export const ActionMenu: React.FC = () => {
96
116
  >
97
117
  Actions
98
118
  </Button>
119
+
120
+ {renderedComponent &&
121
+ React.createElement(renderedComponent, {
122
+ close: () => setRenderedComponent(undefined),
123
+ data: {},
124
+ refresh: () => {},
125
+ })}
99
126
  </>
100
127
  );
101
128
  };
@@ -0,0 +1,117 @@
1
+ import React, { useCallback, useState } from "react";
2
+
3
+ import { BarChartRounded, ShowChartRounded, TableRowsRounded } from "@mui/icons-material";
4
+ import { ToggleButton, ToggleButtonGroup, Tooltip } from "@mui/material";
5
+
6
+ import { useDashboardFilter } from "../contexts/DashboardFilterContext";
7
+ import { useI18n } from "../contexts/I18nContext";
8
+
9
+ import BarChart from "./charts/BarChart";
10
+ import LineChart from "./charts/LineChart";
11
+ import AreaChartIcon from "./Icons/AreaChartIcon";
12
+ import StatsDataTable from "./StatsDataTable";
13
+
14
+ export type ChartType = "line" | "area" | "bar";
15
+ export type ChartsWithTableType = ChartType | "table";
16
+
17
+ export interface DataItem {
18
+ date: string;
19
+ [key: string]: string | number | boolean | Date;
20
+ }
21
+
22
+ export interface ChartProps {
23
+ data: DataItem[];
24
+ charts: ChartType[];
25
+ dataTable?: boolean;
26
+ dataKeyX: string;
27
+ dataKeyY?: string;
28
+ csvFileName?: string;
29
+ }
30
+
31
+ const chartData = {
32
+ line: {
33
+ Icon: ShowChartRounded,
34
+ name: "Line Chart",
35
+ },
36
+ area: {
37
+ Icon: AreaChartIcon,
38
+ name: "Area Chart",
39
+ },
40
+ bar: {
41
+ Icon: BarChartRounded,
42
+ name: "Bar Chart",
43
+ },
44
+ table: {
45
+ Icon: TableRowsRounded,
46
+ name: "Table",
47
+ },
48
+ };
49
+
50
+ export default function Chart({
51
+ data,
52
+ charts,
53
+ dataTable = true,
54
+ dataKeyX,
55
+ dataKeyY,
56
+ csvFileName,
57
+ }: ChartProps) {
58
+ const { t } = useI18n();
59
+ const { filter } = useDashboardFilter();
60
+ const [selectedChart, setSelectedChart] = useState<ChartsWithTableType>(charts[0]);
61
+
62
+ const chartsWithTable: ChartsWithTableType[] = dataTable ? [...charts, "table"] : charts;
63
+
64
+ const handleSelectedChartChange = useCallback(
65
+ (_: React.MouseEvent<HTMLElement>, newChart: string) => {
66
+ if (newChart !== null) {
67
+ setSelectedChart(newChart as ChartsWithTableType);
68
+ }
69
+ },
70
+ [],
71
+ );
72
+
73
+ return (
74
+ <>
75
+ {chartsWithTable.length > 1 && (
76
+ <ToggleButtonGroup
77
+ exclusive
78
+ sx={{ position: "absolute", right: 16, top: 16 }}
79
+ unselectable="off"
80
+ value={selectedChart}
81
+ onChange={handleSelectedChartChange}
82
+ >
83
+ {chartsWithTable.map((chart) => {
84
+ const { Icon, name } = chartData[chart];
85
+ return (
86
+ <Tooltip key={chart} title={t(name)}>
87
+ <ToggleButton size="small" value={chart}>
88
+ <Icon fontSize="small" />
89
+ </ToggleButton>
90
+ </Tooltip>
91
+ );
92
+ })}
93
+ </ToggleButtonGroup>
94
+ )}
95
+ {selectedChart === "bar" && (
96
+ <BarChart
97
+ dataKeyX={dataKeyX}
98
+ dataKeyY={dataKeyY}
99
+ dataset={data.map(({ date, ...props }) => ({ ...props, date: new Date(date) }))}
100
+ granularity={filter.granularity}
101
+ />
102
+ )}
103
+ {(selectedChart === "line" || selectedChart === "area") && (
104
+ <LineChart
105
+ area={selectedChart === "area"}
106
+ dataKeyX={dataKeyX}
107
+ dataKeyY={dataKeyY}
108
+ dataset={data.map(({ date, ...props }) => ({ ...props, date: new Date(date) }))}
109
+ granularity={filter.granularity}
110
+ />
111
+ )}
112
+ {selectedChart === "table" && (
113
+ <StatsDataTable csvFileName={csvFileName} data={data} dateKey={dataKeyX} />
114
+ )}
115
+ </>
116
+ );
117
+ }
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+
3
+ import { SvgIcon, SvgIconProps } from "@mui/material";
4
+
5
+ const AreaChartIcon = (props: SvgIconProps) => (
6
+ <SvgIcon {...props} viewBox="0 0 24 24">
7
+ <path d="M3 17L9 10L14 15L21 7V15Q21 17 19 17H3Z" fill="currentColor" opacity="0.4" />
8
+ <path
9
+ d="M4 16L9 10L14 15L20 8"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeLinecap="round"
13
+ strokeLinejoin="round"
14
+ strokeWidth="2"
15
+ />
16
+ </SvgIcon>
17
+ );
18
+
19
+ export default AreaChartIcon;
@@ -0,0 +1,152 @@
1
+ import React, { useCallback, useMemo } from "react";
2
+
3
+ import { Button, Stack, TableBody, TableRow } from "@mui/material";
4
+
5
+ import { useDashboardFilter } from "../contexts/DashboardFilterContext";
6
+ import { formatDate } from "../util/format_date";
7
+
8
+ import { TableCell } from "./Table/TableCell";
9
+ import TableHead from "./Table/TableHead";
10
+ import TableHeading from "./Table/TableHeading";
11
+ import Table from "./Table";
12
+
13
+ interface DataItem {
14
+ [key: string]: string | number | boolean | Date;
15
+ }
16
+
17
+ interface StatsDataTableProps {
18
+ data: DataItem[];
19
+ dateKey?: string;
20
+ csvFileName?: string;
21
+ }
22
+
23
+ export default function StatsDataTable({ data, dateKey, csvFileName }: StatsDataTableProps) {
24
+ const { filter } = useDashboardFilter();
25
+
26
+ const mappedData = useMemo(() => {
27
+ return data
28
+ .map((item) => {
29
+ const dateEntry = getDateEntry(item, dateKey);
30
+ if (dateEntry === undefined) return undefined;
31
+
32
+ const [key, date] = dateEntry;
33
+ const { [key]: _, ...rest } = item;
34
+
35
+ return { [key]: date, ...rest };
36
+ })
37
+ .filter((item) => item !== undefined);
38
+ }, [data, dateKey]);
39
+
40
+ const handleExportToCSV = useCallback(() => {
41
+ if (mappedData.length === 0) return;
42
+
43
+ const headers = Object.keys(mappedData[0]);
44
+ const csvRows = [
45
+ headers.join(","), // Header row
46
+ ...mappedData.map((row) =>
47
+ headers
48
+ .map((key) => {
49
+ const value = row[key];
50
+ if (value instanceof Date) return `"${value.toISOString()}"`;
51
+ if (typeof value === "string") return `"${value.replace(/"/g, '""')}"`; // Escape quotes
52
+ return value;
53
+ })
54
+ .join(","),
55
+ ),
56
+ ];
57
+
58
+ const csvContent = csvRows.join("\n");
59
+ const blob = new Blob([csvContent], { type: "text/csv" });
60
+ const url = URL.createObjectURL(blob);
61
+
62
+ const link = document.createElement("a");
63
+ link.href = url;
64
+ link.download = `${csvFileName || "data"}_${filter.startDate.toISO()?.split("T")[0]}_${filter.endDate.toISO()?.split("T")[0]}.csv`;
65
+ document.body.appendChild(link);
66
+ link.click();
67
+ document.body.removeChild(link);
68
+ URL.revokeObjectURL(url);
69
+ }, [mappedData, filter.startDate, filter.endDate, filter.granularity]);
70
+
71
+ return (
72
+ <Stack maxHeight={300}>
73
+ <Table count={mappedData.length}>
74
+ <TableHead
75
+ tableRowProps={{
76
+ sx: {
77
+ position: "sticky",
78
+ top: 0,
79
+ bgcolor: "background.paper",
80
+ backgroundImage: "var(--Paper-overlay)",
81
+ boxShadow: "inset 0 -1px var(--mui-palette-divider)",
82
+ },
83
+ }}
84
+ >
85
+ {mappedData.length > 0 &&
86
+ Object.keys(mappedData[0]).map((key) => {
87
+ return <TableHeading key={key}>{formatKey(key)}</TableHeading>;
88
+ })}
89
+ </TableHead>
90
+ <TableBody sx={{ overflowY: "auto" }}>
91
+ {mappedData.map((item, i) => (
92
+ <TableRow key={i}>
93
+ {Object.entries(item).map(([key, value]) => (
94
+ <TableCell
95
+ key={key}
96
+ sx={{ borderBottomWidth: i === mappedData.length - 1 ? 0 : 1 }}
97
+ >
98
+ {value instanceof Date ? formatDate(value, filter.granularity) : value.toString()}
99
+ </TableCell>
100
+ ))}
101
+ </TableRow>
102
+ ))}
103
+ </TableBody>
104
+ </Table>
105
+ <Stack
106
+ alignItems="flex-end"
107
+ pt={2}
108
+ px={2}
109
+ spacing={1}
110
+ sx={{ borderTop: "1px solid", borderColor: "divider" }}
111
+ >
112
+ <Button color="inherit" variant="outlined" onClick={handleExportToCSV}>
113
+ Export to CSV
114
+ </Button>
115
+ </Stack>
116
+ </Stack>
117
+ );
118
+ }
119
+
120
+ function formatKey(key: string) {
121
+ return key
122
+ .split("_")
123
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
124
+ .join(" ");
125
+ }
126
+
127
+ function getDateEntry(item: DataItem, dateKey?: string): [string, Date] | undefined {
128
+ if (dateKey !== undefined && item.hasOwnProperty(dateKey)) {
129
+ let date = item[dateKey];
130
+ date = typeof date === "string" ? new Date(date) : date;
131
+ if (!(date instanceof Date)) return undefined;
132
+
133
+ return [dateKey, date];
134
+ }
135
+
136
+ const dateEntry = Object.entries(item).find(([_, value]) => isDateOrString(value)) as
137
+ | [string, Date | string]
138
+ | undefined;
139
+ if (dateEntry === undefined) {
140
+ return undefined;
141
+ }
142
+
143
+ const dateObj = dateEntry[1] instanceof Date ? dateEntry[1] : new Date(dateEntry[1]);
144
+ return [dateEntry[0], dateObj];
145
+ }
146
+
147
+ function isDateOrString(value: unknown): value is Date | string {
148
+ return (
149
+ (value instanceof Date && !Number.isNaN(value.getTime())) ||
150
+ (typeof value === "string" && !Number.isNaN(Date.parse(value)))
151
+ );
152
+ }
@@ -1,13 +1,20 @@
1
1
  import React, { PropsWithChildren } from "react";
2
2
 
3
- import { Stack, TableHead as MuiTableHead, TableRow, Typography } from "@mui/material";
3
+ import {
4
+ Stack,
5
+ TableHead as MuiTableHead,
6
+ TableRow,
7
+ TableRowProps,
8
+ Typography,
9
+ } from "@mui/material";
4
10
 
5
11
  export interface TableHeadProps extends PropsWithChildren {
6
12
  title?: string;
7
13
  icon?: React.ReactNode;
14
+ tableRowProps?: TableRowProps;
8
15
  }
9
16
 
10
- export const TableHead: React.FC<TableHeadProps> = ({ children, icon, title }) => (
17
+ export const TableHead: React.FC<TableHeadProps> = ({ children, icon, title, tableRowProps }) => (
11
18
  <MuiTableHead>
12
19
  {title != null && (
13
20
  <Stack
@@ -29,7 +36,7 @@ export const TableHead: React.FC<TableHeadProps> = ({ children, icon, title }) =
29
36
  </Stack>
30
37
  )}
31
38
 
32
- <TableRow>{children}</TableRow>
39
+ <TableRow {...tableRowProps}>{children}</TableRow>
33
40
  </MuiTableHead>
34
41
  );
35
42
 
@@ -16,6 +16,8 @@ import {
16
16
 
17
17
  import { useI18n } from "../../contexts/I18nContext";
18
18
  import { RouteInfo, useRouter } from "../../contexts/RouterContext";
19
+ import { useUser } from "../../contexts/UserContext";
20
+ import { hasAccess } from "../../util/has_access";
19
21
  import ActionMenu from "../ActionMenu";
20
22
  import { usePage } from "../Page";
21
23
 
@@ -29,6 +31,7 @@ export const TitleBar: React.FC<TitleBarProps> = ({ back = false, title, childre
29
31
  const { navigate, getCurrent, routes } = useRouter();
30
32
  const routerNavigate = useNavigate();
31
33
  const page = usePage();
34
+ const { user } = useUser();
32
35
 
33
36
  if (typeof back === "boolean" && back) back = -1;
34
37
 
@@ -105,8 +108,11 @@ export const TitleBar: React.FC<TitleBarProps> = ({ back = false, title, childre
105
108
  </Stack>
106
109
  </Stack>
107
110
  {children}
108
- {page?.contrib.filter((operation) => operation.component?.variant === "action").length >
109
- 0 && (
111
+ {page?.contrib.filter(
112
+ (operation) =>
113
+ operation.component?.variant === "action" &&
114
+ hasAccess(user, operation.component.permission, operation.component.group),
115
+ ).length > 0 && (
110
116
  <Stack width="fit-content">
111
117
  <ActionMenu />
112
118
  </Stack>
@@ -33,6 +33,7 @@ export interface LineChartProps {
33
33
  dataKeyX: string;
34
34
  dataKeyY?: string;
35
35
  height?: number;
36
+ area?: boolean;
36
37
  granularity?: Granularity;
37
38
  yAxisOptions?: object;
38
39
  legendProps?: ChartsLegendProps;
@@ -44,6 +45,7 @@ export const LineChart: React.FC<LineChartProps> = ({
44
45
  dataKeyX,
45
46
  dataKeyY,
46
47
  height = 300,
48
+ area,
47
49
  granularity = "day",
48
50
  yAxisOptions,
49
51
  legendProps,
@@ -62,6 +64,7 @@ export const LineChart: React.FC<LineChartProps> = ({
62
64
  showMark: false,
63
65
  curve: "monotoneX",
64
66
  color: theme.palette.graphColorPrimary?.main ?? theme.palette.primary.main,
67
+ area,
65
68
  },
66
69
  ]
67
70
  }
@@ -2,7 +2,7 @@ import React, { useMemo } from "react";
2
2
 
3
3
  import { Stack, Typography } from "@mui/material";
4
4
 
5
- import BarChart from "../../../components/charts/BarChart";
5
+ import Chart from "../../../components/Chart";
6
6
  import WidgetCard from "../../../components/WidgetCard";
7
7
  import { useApi } from "../../../contexts/ApiContext";
8
8
  import { useDashboardFilter } from "../../../contexts/DashboardFilterContext";
@@ -64,11 +64,13 @@ const PurchaseCountWidget: ContribComponent<PurchaseCountItem[]> = ({ data: init
64
64
  sx={sx}
65
65
  title={t(`${granularityLabel(filter.granularity)} Purchases`)}
66
66
  >
67
- <BarChart
67
+ <Chart
68
+ charts={["bar", "area"]}
69
+ csvFileName="purchase_count"
70
+ data={data.map((item) => ({ ...item }))}
68
71
  dataKeyX="date"
69
72
  dataKeyY="count"
70
- dataset={data.map(({ date, count }) => ({ date: new Date(date), count }))}
71
- granularity={filter.granularity}
73
+ dataTable={true}
72
74
  />
73
75
  </WidgetCard>
74
76
 
@@ -60,7 +60,7 @@ export type NavigationOverrides = Record<string, NavigationItem | null | undefin
60
60
 
61
61
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
62
  export type ContribComponent<T = any> = React.ComponentType<
63
- PageProps<T> & OpenAPI.Request & { sx?: SxProps }
63
+ PageProps<T> & OpenAPI.Request & { sx?: SxProps; close?: () => void }
64
64
  >;
65
65
 
66
66
  /**
@@ -0,0 +1,28 @@
1
+ import { Granularity } from "../types";
2
+
3
+ export const formatDate = (
4
+ date: Date,
5
+ granularity: Granularity,
6
+ variant: "short" | "long" = "short",
7
+ locale: string = "sv-SE",
8
+ ) => {
9
+ let options: Intl.DateTimeFormatOptions = {};
10
+ if (granularity === "day") {
11
+ options = {
12
+ day: "numeric",
13
+ month: "long",
14
+ ...(variant === "long" && { year: "numeric" }),
15
+ };
16
+ } else if (granularity === "month") {
17
+ options = {
18
+ month: "long",
19
+ year: "numeric",
20
+ };
21
+ } else if (granularity === "year") {
22
+ options = {
23
+ year: "numeric",
24
+ };
25
+ }
26
+
27
+ return new Intl.DateTimeFormat(locale, options).format(date);
28
+ };