mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-17 21:00:45 +00:00
SPRINT-19: updates to various widgets for new dashboard, cleanups
This commit is contained in:
1233
package-lock.json
generated
1233
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
|||||||
"@auth0/auth0-react": "1.10.2",
|
"@auth0/auth0-react": "1.10.2",
|
||||||
"@emotion/react": "11.7.1",
|
"@emotion/react": "11.7.1",
|
||||||
"@emotion/styled": "11.6.0",
|
"@emotion/styled": "11.6.0",
|
||||||
"@kingsrook/qqq-frontend-core": "1.0.44",
|
"@kingsrook/qqq-frontend-core": "1.0.45",
|
||||||
"@mui/icons-material": "5.4.1",
|
"@mui/icons-material": "5.4.1",
|
||||||
"@mui/material": "5.11.1",
|
"@mui/material": "5.11.1",
|
||||||
"@mui/styles": "5.11.1",
|
"@mui/styles": "5.11.1",
|
||||||
@ -27,6 +27,7 @@
|
|||||||
"chroma-js": "2.4.2",
|
"chroma-js": "2.4.2",
|
||||||
"datejs": "1.0.0-rc3",
|
"datejs": "1.0.0-rc3",
|
||||||
"downshift": "3.2.10",
|
"downshift": "3.2.10",
|
||||||
|
"faker": "5.5.3",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"formik": "2.2.9",
|
"formik": "2.2.9",
|
||||||
"html-react-parser": "1.4.8",
|
"html-react-parser": "1.4.8",
|
||||||
@ -77,6 +78,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@svgr/webpack": "6.5.1",
|
"@svgr/webpack": "6.5.1",
|
||||||
"@types/chroma-js": "2.1.3",
|
"@types/chroma-js": "2.1.3",
|
||||||
|
"@types/faker": "5.5.9",
|
||||||
"@types/react-table": "7.7.9",
|
"@types/react-table": "7.7.9",
|
||||||
"@typescript-eslint/eslint-plugin": "5.10.2",
|
"@typescript-eslint/eslint-plugin": "5.10.2",
|
||||||
"@typescript-eslint/parser": "5.10.2",
|
"@typescript-eslint/parser": "5.10.2",
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
=========================================================
|
=========================================================
|
||||||
* Material Dashboard 2 PRO React TS - v1.0.0
|
* Material Dashboard 2 PRO React TS - v1.0.0
|
||||||
=========================================================
|
=========================================================
|
||||||
|
|
||||||
* Product Page: https://www.creative-tim.com/product/material-dashboard-2-pro-react-ts
|
* Product Page: https://www.creative-tim.com/product/material-dashboard-2-pro-react-ts
|
||||||
* Copyright 2022 Creative Tim (https://www.creative-tim.com)
|
* Copyright 2022 Creative Tim (https://www.creative-tim.com)
|
||||||
|
|
||||||
Coded by www.creative-tim.com
|
Coded by www.creative-tim.com
|
||||||
|
|
||||||
=========================================================
|
=========================================================
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base colors for the Material Dashboard 2 PRO React TSUI Dashboard PRO Material.
|
* The base colors for the Material Dashboard 2 PRO React TSUI Dashboard PRO Material.
|
||||||
@ -20,370 +20,405 @@ Coded by www.creative-tim.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// types
|
// types
|
||||||
interface ColorsTypes {
|
interface ColorsTypes
|
||||||
main: string;
|
{
|
||||||
focus: string;
|
main: string;
|
||||||
|
focus: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GradientsTypes {
|
interface GradientsTypes
|
||||||
main: string;
|
{
|
||||||
state: string;
|
main: string;
|
||||||
|
state: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SocialMediaColorsTypes {
|
interface SocialMediaColorsTypes
|
||||||
main: string;
|
{
|
||||||
dark: string;
|
main: string;
|
||||||
|
dark: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BadgeColorsTypes {
|
interface BadgeColorsTypes
|
||||||
background: string;
|
{
|
||||||
text: string;
|
background: string;
|
||||||
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Types {
|
interface Types
|
||||||
background:
|
{
|
||||||
| {
|
background:
|
||||||
default: string;
|
| {
|
||||||
sidenav?: string;
|
default: string;
|
||||||
card?: string;
|
sidenav?: string;
|
||||||
|
card?: string;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
white:
|
||||||
|
| {
|
||||||
|
main: string;
|
||||||
|
focus: string;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
text:
|
||||||
|
| {
|
||||||
|
main: string;
|
||||||
|
focus: string;
|
||||||
|
primary?: string;
|
||||||
|
secondary?: string;
|
||||||
|
disabled?: string;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
transparent:
|
||||||
|
| {
|
||||||
|
main: string;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
black:
|
||||||
|
| {
|
||||||
|
light: string;
|
||||||
|
main: string;
|
||||||
|
focus: string;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
primary: ColorsTypes | any;
|
||||||
|
secondary: ColorsTypes | any;
|
||||||
|
info: ColorsTypes | any;
|
||||||
|
success: ColorsTypes | any;
|
||||||
|
warning: ColorsTypes | any;
|
||||||
|
error: ColorsTypes | any;
|
||||||
|
light: ColorsTypes | any;
|
||||||
|
dark: ColorsTypes | any;
|
||||||
|
grey:
|
||||||
|
| {
|
||||||
|
[key: string | number]: string;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
gradients:
|
||||||
|
| {
|
||||||
|
primary: GradientsTypes;
|
||||||
|
secondary: GradientsTypes;
|
||||||
|
info: GradientsTypes;
|
||||||
|
success: GradientsTypes;
|
||||||
|
warning: GradientsTypes;
|
||||||
|
error: GradientsTypes;
|
||||||
|
light: GradientsTypes;
|
||||||
|
dark: GradientsTypes;
|
||||||
|
custom1: GradientsTypes;
|
||||||
|
custom2: GradientsTypes;
|
||||||
|
custom3: GradientsTypes;
|
||||||
|
custom4: GradientsTypes;
|
||||||
|
custom5: GradientsTypes;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
socialMediaColors:
|
||||||
|
| {
|
||||||
|
facebook: SocialMediaColorsTypes;
|
||||||
|
twitter: SocialMediaColorsTypes;
|
||||||
|
instagram: SocialMediaColorsTypes;
|
||||||
|
linkedin: SocialMediaColorsTypes;
|
||||||
|
pinterest: SocialMediaColorsTypes;
|
||||||
|
youtube: SocialMediaColorsTypes;
|
||||||
|
vimeo: SocialMediaColorsTypes;
|
||||||
|
slack: SocialMediaColorsTypes;
|
||||||
|
dribbble: SocialMediaColorsTypes;
|
||||||
|
github: SocialMediaColorsTypes;
|
||||||
|
reddit: SocialMediaColorsTypes;
|
||||||
|
tumblr: SocialMediaColorsTypes;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
badgeColors:
|
||||||
|
| {
|
||||||
|
primary: BadgeColorsTypes;
|
||||||
|
secondary: BadgeColorsTypes;
|
||||||
|
info: BadgeColorsTypes;
|
||||||
|
success: BadgeColorsTypes;
|
||||||
|
warning: BadgeColorsTypes;
|
||||||
|
error: BadgeColorsTypes;
|
||||||
|
light: BadgeColorsTypes;
|
||||||
|
dark: BadgeColorsTypes;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
coloredShadows:
|
||||||
|
| {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
| any;
|
||||||
|
inputBorderColor: string;
|
||||||
|
tabs:
|
||||||
|
| {
|
||||||
|
indicator:
|
||||||
|
| {
|
||||||
|
boxShadow: string;
|
||||||
}
|
}
|
||||||
| any;
|
| any;
|
||||||
white:
|
}
|
||||||
| {
|
| any;
|
||||||
main: string;
|
|
||||||
focus: string;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
text:
|
|
||||||
| {
|
|
||||||
main: string;
|
|
||||||
focus: string;
|
|
||||||
primary?: string;
|
|
||||||
secondary?: string;
|
|
||||||
disabled?: string;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
transparent:
|
|
||||||
| {
|
|
||||||
main: string;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
black:
|
|
||||||
| {
|
|
||||||
light: string;
|
|
||||||
main: string;
|
|
||||||
focus: string;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
primary: ColorsTypes | any;
|
|
||||||
secondary: ColorsTypes | any;
|
|
||||||
info: ColorsTypes | any;
|
|
||||||
success: ColorsTypes | any;
|
|
||||||
warning: ColorsTypes | any;
|
|
||||||
error: ColorsTypes | any;
|
|
||||||
light: ColorsTypes | any;
|
|
||||||
dark: ColorsTypes | any;
|
|
||||||
grey:
|
|
||||||
| {
|
|
||||||
[key: string | number]: string;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
gradients:
|
|
||||||
| {
|
|
||||||
primary: GradientsTypes;
|
|
||||||
secondary: GradientsTypes;
|
|
||||||
info: GradientsTypes;
|
|
||||||
success: GradientsTypes;
|
|
||||||
warning: GradientsTypes;
|
|
||||||
error: GradientsTypes;
|
|
||||||
light: GradientsTypes;
|
|
||||||
dark: GradientsTypes;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
socialMediaColors:
|
|
||||||
| {
|
|
||||||
facebook: SocialMediaColorsTypes;
|
|
||||||
twitter: SocialMediaColorsTypes;
|
|
||||||
instagram: SocialMediaColorsTypes;
|
|
||||||
linkedin: SocialMediaColorsTypes;
|
|
||||||
pinterest: SocialMediaColorsTypes;
|
|
||||||
youtube: SocialMediaColorsTypes;
|
|
||||||
vimeo: SocialMediaColorsTypes;
|
|
||||||
slack: SocialMediaColorsTypes;
|
|
||||||
dribbble: SocialMediaColorsTypes;
|
|
||||||
github: SocialMediaColorsTypes;
|
|
||||||
reddit: SocialMediaColorsTypes;
|
|
||||||
tumblr: SocialMediaColorsTypes;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
badgeColors:
|
|
||||||
| {
|
|
||||||
primary: BadgeColorsTypes;
|
|
||||||
secondary: BadgeColorsTypes;
|
|
||||||
info: BadgeColorsTypes;
|
|
||||||
success: BadgeColorsTypes;
|
|
||||||
warning: BadgeColorsTypes;
|
|
||||||
error: BadgeColorsTypes;
|
|
||||||
light: BadgeColorsTypes;
|
|
||||||
dark: BadgeColorsTypes;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
coloredShadows:
|
|
||||||
| {
|
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
inputBorderColor: string;
|
|
||||||
tabs:
|
|
||||||
| {
|
|
||||||
indicator:
|
|
||||||
| {
|
|
||||||
boxShadow: string;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const colors: Types = {
|
const colors: Types = {
|
||||||
background: {
|
background: {
|
||||||
default: "#f0f2f5",
|
default: "#f0f2f5",
|
||||||
},
|
},
|
||||||
|
|
||||||
text: {
|
text: {
|
||||||
main: "#7b809a",
|
main: "#7b809a",
|
||||||
focus: "#7b809a",
|
focus: "#7b809a",
|
||||||
},
|
},
|
||||||
|
|
||||||
transparent: {
|
transparent: {
|
||||||
main: "transparent",
|
main: "transparent",
|
||||||
},
|
},
|
||||||
|
|
||||||
white: {
|
white: {
|
||||||
main: "#ffffff",
|
main: "#ffffff",
|
||||||
focus: "#ffffff",
|
focus: "#ffffff",
|
||||||
},
|
},
|
||||||
|
|
||||||
black: {
|
black: {
|
||||||
light: "#000000",
|
light: "#000000",
|
||||||
main: "#000000",
|
main: "#000000",
|
||||||
focus: "#000000",
|
focus: "#000000",
|
||||||
},
|
},
|
||||||
|
|
||||||
primary: {
|
primary: {
|
||||||
main: "#e91e63",
|
main: "#e91e63",
|
||||||
focus: "#e91e63",
|
focus: "#e91e63",
|
||||||
},
|
},
|
||||||
|
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#7b809a",
|
main: "#7b809a",
|
||||||
focus: "#8f93a9",
|
focus: "#8f93a9",
|
||||||
},
|
},
|
||||||
|
|
||||||
info: {
|
info: {
|
||||||
main: "#04aaef",
|
main: "#04aaef",
|
||||||
focus: "#1662C4",
|
focus: "#1662C4",
|
||||||
},
|
},
|
||||||
|
|
||||||
success: {
|
success: {
|
||||||
main: "#4CAF50",
|
main: "#4CAF50",
|
||||||
focus: "#67bb6a",
|
focus: "#67bb6a",
|
||||||
},
|
},
|
||||||
|
|
||||||
warning: {
|
warning: {
|
||||||
main: "#fb8c00",
|
main: "#fb8c00",
|
||||||
focus: "#fc9d26",
|
focus: "#fc9d26",
|
||||||
},
|
},
|
||||||
|
|
||||||
error: {
|
error: {
|
||||||
main: "#F44335",
|
main: "#F44335",
|
||||||
focus: "#f65f53",
|
focus: "#f65f53",
|
||||||
},
|
},
|
||||||
|
|
||||||
light: {
|
light: {
|
||||||
main: "#f0f2f5",
|
main: "#f0f2f5",
|
||||||
focus: "#f0f2f5",
|
focus: "#f0f2f5",
|
||||||
},
|
},
|
||||||
|
|
||||||
dark: {
|
dark: {
|
||||||
main: "#344767",
|
main: "#344767",
|
||||||
focus: "#2c3c58",
|
focus: "#2c3c58",
|
||||||
},
|
},
|
||||||
|
|
||||||
grey: {
|
grey: {
|
||||||
100: "#f8f9fa",
|
100: "#f8f9fa",
|
||||||
200: "#f0f2f5",
|
200: "#f0f2f5",
|
||||||
300: "#dee2e6",
|
300: "#dee2e6",
|
||||||
400: "#ced4da",
|
400: "#ced4da",
|
||||||
500: "#adb5bd",
|
500: "#adb5bd",
|
||||||
600: "#6c757d",
|
600: "#6c757d",
|
||||||
700: "#495057",
|
700: "#495057",
|
||||||
800: "#343a40",
|
800: "#343a40",
|
||||||
900: "#212529",
|
900: "#212529",
|
||||||
},
|
},
|
||||||
|
|
||||||
gradients: {
|
gradients: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#EC407A",
|
main: "#EC407A",
|
||||||
state: "#D81B60",
|
state: "#D81B60",
|
||||||
},
|
},
|
||||||
|
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#747b8a",
|
main: "#747b8a",
|
||||||
state: "#495361",
|
state: "#495361",
|
||||||
},
|
},
|
||||||
|
|
||||||
info: {
|
info: {
|
||||||
main: "#49a3f1",
|
main: "#49a3f1",
|
||||||
state: "#04aaef",
|
state: "#04aaef",
|
||||||
},
|
},
|
||||||
|
|
||||||
success: {
|
success: {
|
||||||
main: "#66BB6A",
|
main: "#66BB6A",
|
||||||
state: "#43A047",
|
state: "#43A047",
|
||||||
},
|
},
|
||||||
|
|
||||||
warning: {
|
warning: {
|
||||||
main: "#FFA726",
|
main: "#FFA726",
|
||||||
state: "#FB8C00",
|
state: "#FB8C00",
|
||||||
},
|
},
|
||||||
|
|
||||||
error: {
|
error: {
|
||||||
main: "#EF5350",
|
main: "#EF5350",
|
||||||
state: "#E53935",
|
state: "#E53935",
|
||||||
},
|
},
|
||||||
|
|
||||||
light: {
|
light: {
|
||||||
main: "#EBEFF4",
|
main: "#EBEFF4",
|
||||||
state: "#CED4DA",
|
state: "#CED4DA",
|
||||||
},
|
},
|
||||||
|
|
||||||
dark: {
|
dark: {
|
||||||
main: "#42424a",
|
main: "#42424a",
|
||||||
state: "#191919",
|
state: "#191919",
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
|
||||||
socialMediaColors: {
|
custom1: {
|
||||||
facebook: {
|
main: "#3aaf85",
|
||||||
main: "#3b5998",
|
state: "#8c28c2",
|
||||||
dark: "#344e86",
|
},
|
||||||
},
|
|
||||||
|
|
||||||
twitter: {
|
custom2: {
|
||||||
main: "#55acee",
|
main: "#0077b5",
|
||||||
dark: "#3ea1ec",
|
state: "#ffe120",
|
||||||
},
|
},
|
||||||
|
|
||||||
instagram: {
|
custom3: {
|
||||||
main: "#125688",
|
main: "#ea4c89",
|
||||||
dark: "#0e456d",
|
state: "#000000",
|
||||||
},
|
},
|
||||||
|
|
||||||
linkedin: {
|
custom4: {
|
||||||
main: "#0077b5",
|
main: "#0077b5",
|
||||||
dark: "#00669c",
|
state: "#747474",
|
||||||
},
|
},
|
||||||
|
|
||||||
pinterest: {
|
custom5: {
|
||||||
main: "#cc2127",
|
main: "#0077b5",
|
||||||
dark: "#b21d22",
|
state: "#ffcefa",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
youtube: {
|
socialMediaColors: {
|
||||||
main: "#e52d27",
|
facebook: {
|
||||||
dark: "#d41f1a",
|
main: "#3b5998",
|
||||||
},
|
dark: "#344e86",
|
||||||
|
},
|
||||||
|
|
||||||
vimeo: {
|
twitter: {
|
||||||
main: "#1ab7ea",
|
main: "#55acee",
|
||||||
dark: "#13a3d2",
|
dark: "#3ea1ec",
|
||||||
},
|
},
|
||||||
|
|
||||||
slack: {
|
instagram: {
|
||||||
main: "#3aaf85",
|
main: "#125688",
|
||||||
dark: "#329874",
|
dark: "#0e456d",
|
||||||
},
|
},
|
||||||
|
|
||||||
dribbble: {
|
linkedin: {
|
||||||
main: "#ea4c89",
|
main: "#0077b5",
|
||||||
dark: "#e73177",
|
dark: "#00669c",
|
||||||
},
|
},
|
||||||
|
|
||||||
github: {
|
pinterest: {
|
||||||
main: "#24292e",
|
main: "#cc2127",
|
||||||
dark: "#171a1d",
|
dark: "#b21d22",
|
||||||
},
|
},
|
||||||
|
|
||||||
reddit: {
|
youtube: {
|
||||||
main: "#ff4500",
|
main: "#e52d27",
|
||||||
dark: "#e03d00",
|
dark: "#d41f1a",
|
||||||
},
|
},
|
||||||
|
|
||||||
tumblr: {
|
vimeo: {
|
||||||
main: "#35465c",
|
main: "#1ab7ea",
|
||||||
dark: "#2a3749",
|
dark: "#13a3d2",
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
|
||||||
badgeColors: {
|
slack: {
|
||||||
primary: {
|
main: "#3aaf85",
|
||||||
background: "#f8b3ca",
|
dark: "#329874",
|
||||||
text: "#cc084b",
|
},
|
||||||
},
|
|
||||||
|
|
||||||
secondary: {
|
dribbble: {
|
||||||
background: "#d7d9e1",
|
main: "#ea4c89",
|
||||||
text: "#6c757d",
|
dark: "#e73177",
|
||||||
},
|
},
|
||||||
|
|
||||||
info: {
|
github: {
|
||||||
background: "#aecef7",
|
main: "#24292e",
|
||||||
text: "#095bc6",
|
dark: "#171a1d",
|
||||||
},
|
},
|
||||||
|
|
||||||
success: {
|
reddit: {
|
||||||
background: "#bce2be",
|
main: "#ff4500",
|
||||||
text: "#339537",
|
dark: "#e03d00",
|
||||||
},
|
},
|
||||||
|
|
||||||
warning: {
|
tumblr: {
|
||||||
background: "#ffd59f",
|
main: "#35465c",
|
||||||
text: "#c87000",
|
dark: "#2a3749",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
error: {
|
badgeColors: {
|
||||||
background: "#fcd3d0",
|
primary: {
|
||||||
text: "#f61200",
|
background: "#f8b3ca",
|
||||||
},
|
text: "#cc084b",
|
||||||
|
},
|
||||||
|
|
||||||
light: {
|
secondary: {
|
||||||
background: "#ffffff",
|
background: "#d7d9e1",
|
||||||
text: "#c7d3de",
|
text: "#6c757d",
|
||||||
},
|
},
|
||||||
|
|
||||||
dark: {
|
info: {
|
||||||
background: "#8097bf",
|
background: "#aecef7",
|
||||||
text: "#1e2e4a",
|
text: "#095bc6",
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
|
||||||
coloredShadows: {
|
success: {
|
||||||
primary: "#e91e62",
|
background: "#bce2be",
|
||||||
secondary: "#110e0e",
|
text: "#339537",
|
||||||
info: "#00bbd4",
|
},
|
||||||
success: "#4caf4f",
|
|
||||||
warning: "#ff9900",
|
|
||||||
error: "#f44336",
|
|
||||||
light: "#adb5bd",
|
|
||||||
dark: "#404040",
|
|
||||||
},
|
|
||||||
|
|
||||||
inputBorderColor: "#d2d6da",
|
warning: {
|
||||||
|
background: "#ffd59f",
|
||||||
|
text: "#c87000",
|
||||||
|
},
|
||||||
|
|
||||||
tabs: {
|
error: {
|
||||||
indicator: { boxShadow: "#ddd" },
|
background: "#fcd3d0",
|
||||||
},
|
text: "#f61200",
|
||||||
|
},
|
||||||
|
|
||||||
|
light: {
|
||||||
|
background: "#ffffff",
|
||||||
|
text: "#c7d3de",
|
||||||
|
},
|
||||||
|
|
||||||
|
dark: {
|
||||||
|
background: "#8097bf",
|
||||||
|
text: "#1e2e4a",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
coloredShadows: {
|
||||||
|
primary: "#e91e62",
|
||||||
|
secondary: "#110e0e",
|
||||||
|
info: "#00bbd4",
|
||||||
|
success: "#4caf4f",
|
||||||
|
warning: "#ff9900",
|
||||||
|
error: "#f44336",
|
||||||
|
light: "#adb5bd",
|
||||||
|
dark: "#404040",
|
||||||
|
},
|
||||||
|
|
||||||
|
inputBorderColor: "#d2d6da",
|
||||||
|
|
||||||
|
tabs: {
|
||||||
|
indicator: {boxShadow: "#ddd"},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default colors;
|
export default colors;
|
||||||
|
@ -80,6 +80,11 @@ const MDBadgeDot: FC<Props> = forwardRef(
|
|||||||
"error",
|
"error",
|
||||||
"light",
|
"light",
|
||||||
"dark",
|
"dark",
|
||||||
|
"custom1",
|
||||||
|
"custom2",
|
||||||
|
"custom3",
|
||||||
|
"custom4",
|
||||||
|
"custom5"
|
||||||
];
|
];
|
||||||
|
|
||||||
const colorValues = {
|
const colorValues = {
|
||||||
@ -90,10 +95,14 @@ const MDBadgeDot: FC<Props> = forwardRef(
|
|||||||
"warning": "#fb8c00",
|
"warning": "#fb8c00",
|
||||||
"error": "#F44335",
|
"error": "#F44335",
|
||||||
"light": "#f0f2f5",
|
"light": "#f0f2f5",
|
||||||
"dark": "#344767"
|
"dark": "#344767",
|
||||||
|
"custom1": "#8c28c2",
|
||||||
|
"custom2": "#ffe120",
|
||||||
|
"custom3": "#000000",
|
||||||
|
"custom4": "#747474",
|
||||||
|
"custom5": "#ffcefa"
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
const validColorIndex = validColors.findIndex((el) => el === color);
|
|
||||||
return (
|
return (
|
||||||
<Box ref={ref} display="flex" alignItems="center" p={padding} {...rest}>
|
<Box ref={ref} display="flex" alignItems="center" p={padding} {...rest}>
|
||||||
<Box
|
<Box
|
||||||
|
@ -34,7 +34,8 @@ import BarChart from "qqq/components/widgets/charts/barchart/BarChart";
|
|||||||
import HorizontalBarChart from "qqq/components/widgets/charts/barchart/HorizontalBarChart";
|
import HorizontalBarChart from "qqq/components/widgets/charts/barchart/HorizontalBarChart";
|
||||||
import DefaultLineChart from "qqq/components/widgets/charts/linechart/DefaultLineChart";
|
import DefaultLineChart from "qqq/components/widgets/charts/linechart/DefaultLineChart";
|
||||||
import SmallLineChart from "qqq/components/widgets/charts/linechart/SmallLineChart";
|
import SmallLineChart from "qqq/components/widgets/charts/linechart/SmallLineChart";
|
||||||
import PieChartCard from "qqq/components/widgets/charts/piechart/PieChartCard";
|
import PieChart from "qqq/components/widgets/charts/piechart/PieChart";
|
||||||
|
import StackedBarChart from "qqq/components/widgets/charts/StackedBarChart";
|
||||||
import DividerWidget from "qqq/components/widgets/misc/Divider";
|
import DividerWidget from "qqq/components/widgets/misc/Divider";
|
||||||
import FieldValueListWidget from "qqq/components/widgets/misc/FieldValueListWidget";
|
import FieldValueListWidget from "qqq/components/widgets/misc/FieldValueListWidget";
|
||||||
import QuickSightChart from "qqq/components/widgets/misc/QuickSightChart";
|
import QuickSightChart from "qqq/components/widgets/misc/QuickSightChart";
|
||||||
@ -161,13 +162,13 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
|||||||
{
|
{
|
||||||
widgetMetaData.type === "parentWidget" && (
|
widgetMetaData.type === "parentWidget" && (
|
||||||
<ParentWidget
|
<ParentWidget
|
||||||
icon={widgetMetaData.icon}
|
|
||||||
entityPrimaryKey={entityPrimaryKey}
|
entityPrimaryKey={entityPrimaryKey}
|
||||||
tableName={tableName}
|
tableName={tableName}
|
||||||
widgetIndex={i}
|
widgetIndex={i}
|
||||||
label={widgetMetaData.label}
|
widgetMetaData={widgetMetaData}
|
||||||
data={widgetData[i]}
|
data={widgetData[i]}
|
||||||
reloadWidgetCallback={reloadWidget}
|
reloadWidgetCallback={reloadWidget}
|
||||||
|
storeDropdownSelections={widgetMetaData.storeDropdownSelections}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -184,30 +185,34 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
|||||||
{
|
{
|
||||||
widgetMetaData.type === "table" && (
|
widgetMetaData.type === "table" && (
|
||||||
<Widget
|
<Widget
|
||||||
label={widgetData[i]?.label}
|
widgetMetaData={widgetMetaData}
|
||||||
isCard={widgetMetaData.isCard}
|
|
||||||
widgetData={widgetData[i]}
|
widgetData={widgetData[i]}
|
||||||
reloadWidgetCallback={(data) => reloadWidget(i, data)}
|
reloadWidgetCallback={(data) => reloadWidget(i, data)}
|
||||||
isChild={areChildren}
|
isChild={areChildren}
|
||||||
>
|
>
|
||||||
<TableCard
|
<TableCard
|
||||||
color="info"
|
|
||||||
title={widgetMetaData.label}
|
|
||||||
linkText={widgetData[i]?.linkText}
|
|
||||||
linkURL={widgetData[i]?.linkURL}
|
|
||||||
noRowsFoundHTML={widgetData[i]?.noRowsFoundHTML}
|
noRowsFoundHTML={widgetData[i]?.noRowsFoundHTML}
|
||||||
data={widgetData[i]}
|
data={widgetData[i]}
|
||||||
dropdownOptions={widgetData[i]?.dropdownOptions}
|
|
||||||
reloadWidgetCallback={(data) => reloadWidget(i, data)}
|
|
||||||
widgetIndex={i}
|
|
||||||
/>
|
/>
|
||||||
</Widget>
|
</Widget>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
widgetMetaData.type === "stackedBarChart" && (
|
||||||
|
<Widget
|
||||||
|
widgetMetaData={widgetMetaData}
|
||||||
|
widgetData={widgetData[i]}
|
||||||
|
reloadWidgetCallback={(data) => reloadWidget(i, data)}
|
||||||
|
isChild={areChildren}
|
||||||
|
>
|
||||||
|
<StackedBarChart data={widgetData[i]?.chartData}/>
|
||||||
|
</Widget>
|
||||||
|
)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
widgetMetaData.type === "process" && widgetData[i]?.processMetaData && (
|
widgetMetaData.type === "process" && widgetData[i]?.processMetaData && (
|
||||||
<Widget
|
<Widget
|
||||||
label={widgetData[i]?.processMetaData?.label}
|
widgetMetaData={widgetMetaData}
|
||||||
widgetData={widgetData[i]}
|
widgetData={widgetData[i]}
|
||||||
reloadWidgetCallback={(data) => reloadWidget(i, data)}>
|
reloadWidgetCallback={(data) => reloadWidget(i, data)}>
|
||||||
<div>
|
<div>
|
||||||
@ -234,7 +239,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
widgetMetaData.type === "html" && (
|
widgetMetaData.type === "html" && (
|
||||||
<Widget label={widgetMetaData.label}>
|
<Widget widgetMetaData={widgetMetaData}>
|
||||||
<Box px={1} pt={0} pb={2}>
|
<Box px={1} pt={0} pb={2}>
|
||||||
<MDTypography component="div" variant="button" color="text" fontWeight="light">
|
<MDTypography component="div" variant="button" color="text" fontWeight="light">
|
||||||
{
|
{
|
||||||
@ -247,15 +252,6 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
|||||||
</Widget>
|
</Widget>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
|
||||||
widgetMetaData.type === "multiStatistics" && (
|
|
||||||
<MultiStatisticsCard
|
|
||||||
color="info"
|
|
||||||
title={widgetMetaData.label}
|
|
||||||
data={widgetData[i]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
widgetMetaData.type === "smallLineChart" && (
|
widgetMetaData.type === "smallLineChart" && (
|
||||||
<SmallLineChart
|
<SmallLineChart
|
||||||
@ -267,6 +263,25 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
widgetMetaData.type === "statistics" && (
|
||||||
|
widgetData && widgetData[i] && (
|
||||||
|
<Widget
|
||||||
|
widgetMetaData={widgetMetaData}
|
||||||
|
widgetData={widgetData[i]}
|
||||||
|
isChild={areChildren}
|
||||||
|
reloadWidgetCallback={(data) => reloadWidget(i, data)}>
|
||||||
|
<StatisticsCard
|
||||||
|
title={widgetMetaData.label}
|
||||||
|
color={colors.info.main}
|
||||||
|
icon={widgetMetaData.icon}
|
||||||
|
data={widgetData[i]}
|
||||||
|
increaseIsGood={true}
|
||||||
|
/>
|
||||||
|
</Widget>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
widgetMetaData.type === "simpleStatistics" && (
|
widgetMetaData.type === "simpleStatistics" && (
|
||||||
widgetData && widgetData[i] && (
|
widgetData && widgetData[i] && (
|
||||||
@ -280,16 +295,12 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
widgetMetaData.type === "statistics" && (
|
widgetMetaData.type === "multiStatistics" && (
|
||||||
widgetData && widgetData[i] && (
|
<MultiStatisticsCard
|
||||||
<StatisticsCard
|
color="info"
|
||||||
title={widgetMetaData.label}
|
title={widgetMetaData.label}
|
||||||
color={colors.info.main}
|
data={widgetData[i]}
|
||||||
icon={widgetMetaData.icon}
|
/>
|
||||||
data={widgetData[i]}
|
|
||||||
increaseIsGood={true}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -310,11 +321,19 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
widgetMetaData.type === "pieChart" && (
|
widgetMetaData.type === "pieChart" && (
|
||||||
<PieChartCard
|
<Widget
|
||||||
title={widgetMetaData.label}
|
widgetMetaData={widgetMetaData}
|
||||||
description={widgetData[i]?.description}
|
widgetData={widgetData[i]}
|
||||||
data={widgetData[i]?.chartData}
|
isChild={areChildren}
|
||||||
/>
|
reloadWidgetCallback={(data) => reloadWidget(i, data)}>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<PieChart
|
||||||
|
chartData={widgetData[i]?.chartData}
|
||||||
|
description={widgetData[i]?.description}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Widget>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -362,7 +381,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
|||||||
widgetMetaData.type === "childRecordList" && (
|
widgetMetaData.type === "childRecordList" && (
|
||||||
widgetData && widgetData[i] &&
|
widgetData && widgetData[i] &&
|
||||||
<RecordGridWidget
|
<RecordGridWidget
|
||||||
title={widgetMetaData.label}
|
widgetMetaData={widgetMetaData}
|
||||||
data={widgetData[i]}
|
data={widgetData[i]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -372,7 +391,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
|||||||
widgetMetaData.type === "fieldValueList" && (
|
widgetMetaData.type === "fieldValueList" && (
|
||||||
widgetData && widgetData[i] &&
|
widgetData && widgetData[i] &&
|
||||||
<FieldValueListWidget
|
<FieldValueListWidget
|
||||||
title={widgetMetaData.label}
|
widgetMetaData={widgetMetaData}
|
||||||
data={widgetData[i]}
|
data={widgetData[i]}
|
||||||
reloadWidgetCallback={(data) => reloadWidget(i, data)}
|
reloadWidgetCallback={(data) => reloadWidget(i, data)}
|
||||||
/>
|
/>
|
||||||
|
@ -50,18 +50,18 @@ export interface ParentWidgetData
|
|||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
|
widgetMetaData?: QWidgetMetaData;
|
||||||
widgetIndex: number;
|
widgetIndex: number;
|
||||||
label: string;
|
|
||||||
icon?: string;
|
|
||||||
data: ParentWidgetData;
|
data: ParentWidgetData;
|
||||||
reloadWidgetCallback?: (widgetIndex: number, params: string) => void;
|
reloadWidgetCallback?: (widgetIndex: number, params: string) => void;
|
||||||
entityPrimaryKey?: string;
|
entityPrimaryKey?: string;
|
||||||
tableName?: string;
|
tableName?: string;
|
||||||
|
storeDropdownSelections?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const qController = Client.getInstance();
|
const qController = Client.getInstance();
|
||||||
function ParentWidget({widgetIndex, label, icon, data, reloadWidgetCallback, entityPrimaryKey, tableName}: Props, ): JSX.Element
|
function ParentWidget({widgetMetaData, widgetIndex, data, reloadWidgetCallback, entityPrimaryKey, tableName, storeDropdownSelections}: Props, ): JSX.Element
|
||||||
{
|
{
|
||||||
const [childUrlParams, setChildUrlParams] = useState("");
|
const [childUrlParams, setChildUrlParams] = useState("");
|
||||||
const [qInstance, setQInstance] = useState(null as QInstance);
|
const [qInstance, setQInstance] = useState(null as QInstance);
|
||||||
@ -99,12 +99,12 @@ function ParentWidget({widgetIndex, label, icon, data, reloadWidgetCallback, ent
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return (
|
return (
|
||||||
<Widget
|
<Widget
|
||||||
icon={icon}
|
widgetMetaData={widgetMetaData}
|
||||||
label={label}
|
|
||||||
widgetData={data}
|
widgetData={data}
|
||||||
|
storeDropdownSelections={storeDropdownSelections}
|
||||||
reloadWidgetCallback={parentReloadWidgetCallback}
|
reloadWidgetCallback={parentReloadWidgetCallback}
|
||||||
>
|
>
|
||||||
<Box px={3} sx={{width: "100%"}}>
|
<Box sx={{height: "100%", width: "100%"}}>
|
||||||
<DashboardWidgets widgetMetaDataList={widgets} entityPrimaryKey={entityPrimaryKey} tableName={tableName} childUrlParams={childUrlParams} areChildren={true}/>
|
<DashboardWidgets widgetMetaDataList={widgets} entityPrimaryKey={entityPrimaryKey} tableName={tableName} childUrlParams={childUrlParams} areChildren={true}/>
|
||||||
</Box>
|
</Box>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||||
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Card from "@mui/material/Card";
|
import Card from "@mui/material/Card";
|
||||||
@ -44,21 +45,19 @@ export interface WidgetData
|
|||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
icon?: string;
|
|
||||||
label: string;
|
|
||||||
labelAdditionalComponentsLeft: LabelComponent[];
|
labelAdditionalComponentsLeft: LabelComponent[];
|
||||||
labelAdditionalComponentsRight: LabelComponent[];
|
labelAdditionalComponentsRight: LabelComponent[];
|
||||||
|
widgetMetaData?: QWidgetMetaData;
|
||||||
widgetData?: WidgetData;
|
widgetData?: WidgetData;
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
reloadWidgetCallback?: (params: string) => void;
|
reloadWidgetCallback?: (params: string) => void;
|
||||||
isChild?: boolean;
|
isChild?: boolean;
|
||||||
isCard?: boolean;
|
storeDropdownSelections?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget.defaultProps = {
|
Widget.defaultProps = {
|
||||||
isCard: true,
|
|
||||||
isChild: false,
|
isChild: false,
|
||||||
label: null,
|
widgetMetaData: {},
|
||||||
widgetData: {},
|
widgetData: {},
|
||||||
labelAdditionalComponentsLeft: [],
|
labelAdditionalComponentsLeft: [],
|
||||||
labelAdditionalComponentsRight: [],
|
labelAdditionalComponentsRight: [],
|
||||||
@ -121,6 +120,8 @@ export class Dropdown extends LabelComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT = "qqq.widgets.dropdownData";
|
||||||
|
|
||||||
|
|
||||||
function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
||||||
{
|
{
|
||||||
@ -133,7 +134,7 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
|||||||
navigate(`#/createChild=${table.name}/defaultValues=${JSON.stringify(defaultValues)}/disabledFields=${JSON.stringify(disabledFields)}`)
|
navigate(`#/createChild=${table.name}/defaultValues=${JSON.stringify(defaultValues)}/disabledFields=${JSON.stringify(disabledFields)}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderComponent(component: LabelComponent)
|
function renderComponent(component: LabelComponent, index: number)
|
||||||
{
|
{
|
||||||
if(component instanceof HeaderLink)
|
if(component instanceof HeaderLink)
|
||||||
{
|
{
|
||||||
@ -157,10 +158,23 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
|||||||
|
|
||||||
if (component instanceof Dropdown)
|
if (component instanceof Dropdown)
|
||||||
{
|
{
|
||||||
|
let defaultValue = null;
|
||||||
|
const dropdownName = props.widgetData.dropdownNameList[index];
|
||||||
|
const localStorageKey = `${WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT}.${props.widgetMetaData.name}.${dropdownName}`;
|
||||||
|
if(props.storeDropdownSelections)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// see if an existing value is stored in local storage, and if so set it in dropdown //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
defaultValue = JSON.parse(localStorage.getItem(localStorageKey));
|
||||||
|
}
|
||||||
|
|
||||||
const dropdown = component as Dropdown
|
const dropdown = component as Dropdown
|
||||||
return (
|
return (
|
||||||
<Box my={2} mr={2} sx={{float: "right"}}>
|
<Box my={2} mr={2} sx={{float: "right"}}>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
|
localStorageKey={localStorageKey}
|
||||||
|
defaultValue={defaultValue}
|
||||||
sx={{width: 200, marginLeft: "15px"}}
|
sx={{width: 200, marginLeft: "15px"}}
|
||||||
label={`Select ${dropdown.label}`}
|
label={`Select ${dropdown.label}`}
|
||||||
dropdownOptions={dropdown.options}
|
dropdownOptions={dropdown.options}
|
||||||
@ -199,12 +213,14 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
|||||||
// find the index base on selected label //
|
// find the index base on selected label //
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
const tableName = dropdownLabel.replace("Select ", "");
|
const tableName = dropdownLabel.replace("Select ", "");
|
||||||
|
let dropdownName = "";
|
||||||
let index = -1;
|
let index = -1;
|
||||||
for (let i = 0; i < props.widgetData.dropdownLabelList.length; i++)
|
for (let i = 0; i < props.widgetData.dropdownLabelList.length; i++)
|
||||||
{
|
{
|
||||||
if (tableName === props.widgetData.dropdownLabelList[i])
|
if (tableName === props.widgetData.dropdownLabelList[i])
|
||||||
{
|
{
|
||||||
index = i;
|
index = i;
|
||||||
|
dropdownName = props.widgetData.dropdownNameList[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,6 +233,22 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
|||||||
dropdownData[index] = (changedData) ? changedData.id : null;
|
dropdownData[index] = (changedData) ? changedData.id : null;
|
||||||
setDropdownData(dropdownData);
|
setDropdownData(dropdownData);
|
||||||
setCounter(counter + 1);
|
setCounter(counter + 1);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
// if should store in local storage, do so now //
|
||||||
|
// or remove if dropdown was cleared out //
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
if(props.storeDropdownSelections)
|
||||||
|
{
|
||||||
|
if (changedData?.id)
|
||||||
|
{
|
||||||
|
localStorage.setItem(`${WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT}.${props.widgetMetaData.name}.${dropdownName}`, JSON.stringify(changedData));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
localStorage.removeItem(`${WIDGET_DROPDOWN_SELECTION_LOCAL_STORAGE_KEY_ROOT}.${props.widgetMetaData.name}.${dropdownName}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,61 +277,62 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
console.log(`No reload widget callback in ${props.label}`)
|
console.log(`No reload widget callback in ${props.widgetMetaData.label}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [counter]);
|
}, [counter]);
|
||||||
|
|
||||||
const widgetContent =
|
const widgetContent =
|
||||||
<Box sx={{width: "100%"}}>
|
<Box sx={{width: "100%"}}>
|
||||||
{
|
<Box display="flex" justifyContent="space-between" alignItems="center" sx={{width: "100%"}}>
|
||||||
(props.icon || props.label) && (
|
<Box pt={2}>
|
||||||
<Box display="flex" justifyContent="space-between" alignItems="center" sx={{width: "100%"}}>
|
{
|
||||||
<Box py={2}>
|
props.widgetMetaData?.icon && (
|
||||||
{
|
<Box
|
||||||
props.icon && (
|
ml={3}
|
||||||
<Box
|
mt={-4}
|
||||||
ml={3}
|
sx={{
|
||||||
mt={-4}
|
display: "flex",
|
||||||
sx={{
|
justifyContent: "center",
|
||||||
display: "flex",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
width: "64px",
|
||||||
alignItems: "center",
|
height: "64px",
|
||||||
width: "64px",
|
borderRadius: "8px",
|
||||||
height: "64px",
|
background: colors.info.main,
|
||||||
borderRadius: "8px",
|
color: "#ffffff",
|
||||||
background: colors.info.main,
|
float: "left"
|
||||||
color: "#ffffff",
|
}}
|
||||||
float: "left"
|
>
|
||||||
}}
|
<Icon fontSize="medium" color="inherit">
|
||||||
>
|
{props.widgetMetaData.icon}
|
||||||
<Icon fontSize="medium" color="inherit">
|
</Icon>
|
||||||
{props.icon}
|
</Box>
|
||||||
</Icon>
|
|
||||||
</Box>
|
)
|
||||||
)
|
}
|
||||||
}
|
{
|
||||||
<Typography variant={props.isChild ? "h6" : "h5"} fontWeight="medium" p={3} display="inline">
|
props.widgetMetaData?.label && (
|
||||||
{props.label}
|
<Typography variant="h5" fontWeight="medium" pl={3} display="inline">
|
||||||
|
{props.widgetMetaData.label}
|
||||||
</Typography>
|
</Typography>
|
||||||
{
|
)
|
||||||
props.labelAdditionalComponentsLeft.map((component, i) =>
|
}
|
||||||
{
|
{
|
||||||
return (<span key={i}>{renderComponent(component)}</span>);
|
props.labelAdditionalComponentsLeft.map((component, i) =>
|
||||||
})
|
{
|
||||||
}
|
return (<span key={i}>{renderComponent(component, i)}</span>);
|
||||||
</Box>
|
})
|
||||||
<Box pr={1}>
|
}
|
||||||
{
|
</Box>
|
||||||
effectiveLabelAdditionalComponentsRight.map((component, i) =>
|
<Box>
|
||||||
{
|
{
|
||||||
return (<span key={i}>{renderComponent(component)}</span>);
|
effectiveLabelAdditionalComponentsRight.map((component, i) =>
|
||||||
})
|
{
|
||||||
}
|
return (<span key={i}>{renderComponent(component, i)}</span>);
|
||||||
</Box>
|
})
|
||||||
</Box>
|
}
|
||||||
)
|
</Box>
|
||||||
}
|
</Box>
|
||||||
{
|
{
|
||||||
props.widgetData?.dropdownNeedsSelectedText ? (
|
props.widgetData?.dropdownNeedsSelectedText ? (
|
||||||
<Box pb={3} pr={3} sx={{width: "100%", textAlign: "right"}}>
|
<Box pb={3} pr={3} sx={{width: "100%", textAlign: "right"}}>
|
||||||
@ -313,7 +346,7 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
|||||||
}
|
}
|
||||||
</Box>;
|
</Box>;
|
||||||
|
|
||||||
return props.isCard ? <Card sx={{width: "100%"}}>{widgetContent}</Card> : widgetContent;
|
return props.widgetMetaData?.isCard ? <Card sx={{marginTop: props.widgetMetaData?.icon ? 2 : 0, width: "100%"}}>{widgetContent}</Card> : widgetContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Widget;
|
export default Widget;
|
||||||
|
37
src/qqq/components/widgets/charts/DefaultChartData.tsx
Normal file
37
src/qqq/components/widgets/charts/DefaultChartData.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const chartColors = ["info", "warning", "primary", "success", "error", "secondary", "dark", "custom1", "custom2", "custom3", "custom4", "custom5"];
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
// structure of default chart data //
|
||||||
|
//////////////////////////////////////////
|
||||||
|
export interface DefaultChartData
|
||||||
|
{
|
||||||
|
labels: string[];
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: string;
|
||||||
|
data: number[];
|
||||||
|
backgroundColor: string;
|
||||||
|
} ]
|
||||||
|
};
|
84
src/qqq/components/widgets/charts/StackedBarChart.tsx
Normal file
84
src/qqq/components/widgets/charts/StackedBarChart.tsx
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import {BarElement, CategoryScale, Chart as ChartJS, Legend, LinearScale, Title, Tooltip,} from "chart.js";
|
||||||
|
import React from "react";
|
||||||
|
import {Bar} from "react-chartjs-2";
|
||||||
|
import colors from "qqq/assets/theme/base/colors";
|
||||||
|
import {chartColors, DefaultChartData} from "qqq/components/widgets/charts/DefaultChartData";
|
||||||
|
|
||||||
|
ChartJS.register(
|
||||||
|
CategoryScale,
|
||||||
|
LinearScale,
|
||||||
|
BarElement,
|
||||||
|
Title,
|
||||||
|
Tooltip,
|
||||||
|
Legend
|
||||||
|
);
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
responsive: true,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
stacked: true,
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
stacked: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Props
|
||||||
|
{
|
||||||
|
data: DefaultChartData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {gradients} = colors;
|
||||||
|
function StackedBarChart({data}: Props): JSX.Element
|
||||||
|
{
|
||||||
|
const handleClick = (e: Array<{}>) =>
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if(e && e.length > 0 && data?.dataset?.urls && data?.dataset?.urls.length)
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
navigate(chartData.dataset.urls[e[0]["index"]]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
data?.datasets.forEach((dataset: any, index: number) =>
|
||||||
|
{
|
||||||
|
if(! dataset.backgroundColor)
|
||||||
|
{
|
||||||
|
dataset.backgroundColor = gradients[chartColors[index]].state;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return <Box p={3}><Bar data={data} options={options} getElementsAtEvent={handleClick} /></Box>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StackedBarChart;
|
@ -19,13 +19,17 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {Card} from "@mui/material";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Card from "@mui/material/Card";
|
import Divider from "@mui/material/Divider";
|
||||||
import Icon from "@mui/material/Icon";
|
import Grid from "@mui/material/Grid";
|
||||||
import parse from "html-react-parser";
|
import parse from "html-react-parser";
|
||||||
import {ReactNode, useMemo} from "react";
|
import React, {useMemo} from "react";
|
||||||
import {Pie} from "react-chartjs-2";
|
import {Pie} from "react-chartjs-2";
|
||||||
|
import {useNavigate} from "react-router-dom";
|
||||||
|
import MDBadgeDot from "qqq/components/legacy/MDBadgeDot";
|
||||||
import MDTypography from "qqq/components/legacy/MDTypography";
|
import MDTypography from "qqq/components/legacy/MDTypography";
|
||||||
|
import {chartColors} from "qqq/components/widgets/charts/DefaultChartData";
|
||||||
import configs from "qqq/components/widgets/charts/piechart/PieChartConfigs";
|
import configs from "qqq/components/widgets/charts/piechart/PieChartConfigs";
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
@ -38,6 +42,7 @@ export interface PieChartData
|
|||||||
label: string;
|
label: string;
|
||||||
backgroundColors?: string[];
|
backgroundColors?: string[];
|
||||||
data: number[];
|
data: number[];
|
||||||
|
urls?: string[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,64 +50,78 @@ export interface PieChartData
|
|||||||
// Declaring props types for PieChart
|
// Declaring props types for PieChart
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
icon?: {
|
|
||||||
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark";
|
|
||||||
component: ReactNode;
|
|
||||||
};
|
|
||||||
title?: string;
|
|
||||||
description?: string;
|
description?: string;
|
||||||
height?: string | number;
|
chartData: PieChartData;
|
||||||
chart: PieChartData;
|
|
||||||
|
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
function PieChart({icon, title, description, height, chart}: Props): JSX.Element
|
function PieChart({description, chartData}: Props): JSX.Element
|
||||||
{
|
{
|
||||||
const {data, options} = configs(chart?.labels || [], chart?.dataset || {});
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const renderChart = (
|
if (chartData && chartData.dataset)
|
||||||
<Box py={2} pr={2} pl={icon.component ? 1 : 2}>
|
{
|
||||||
{title || description ? (
|
chartData.dataset.backgroundColors = chartColors;
|
||||||
<Box display="flex" px={description ? 1 : 0} pt={description ? 1 : 0}>
|
}
|
||||||
{icon.component && (
|
|
||||||
<Box
|
const {data, options} = configs(chartData?.labels || [], chartData?.dataset || {});
|
||||||
width="4rem"
|
|
||||||
height="4rem"
|
const handleClick = (e: Array<{}>) =>
|
||||||
borderRadius="xl"
|
{
|
||||||
display="flex"
|
if(e && e.length > 0 && chartData?.dataset?.urls && chartData?.dataset?.urls.length)
|
||||||
justifyContent="center"
|
{
|
||||||
alignItems="center"
|
// @ts-ignore
|
||||||
color="white"
|
navigate(chartData.dataset.urls[e[0]["index"]]);
|
||||||
mt={-5}
|
}
|
||||||
mr={2}
|
}
|
||||||
sx={{backgroundColor: icon.color || "info"}}
|
|
||||||
>
|
return (
|
||||||
<Icon fontSize="medium">{icon.component}</Icon>
|
<Card sx={{boxShadow: "none", height: "100%", width: "100%", display: "flex", flexGrow: 1}}>
|
||||||
|
<Box mt={3}>
|
||||||
|
<Grid container alignItems="center">
|
||||||
|
<Grid item xs={5}>
|
||||||
|
|
||||||
|
<Box py={2} pr={2} pl={2}>
|
||||||
|
{useMemo(
|
||||||
|
() => (
|
||||||
|
<Pie data={data} options={options} getElementsAtEvent={handleClick} />
|
||||||
|
),
|
||||||
|
[chartData]
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
</Grid>
|
||||||
<Box mt={icon.component ? -2 : 0}>
|
<Grid item xs={7}>
|
||||||
{title && <MDTypography variant="h6">{title}</MDTypography>}
|
<Box pr={1}>
|
||||||
<Box mb={2}>
|
{
|
||||||
<MDTypography component="div" variant="button" color="text">
|
data && data.labels ? (
|
||||||
{parse(description)}
|
(data.labels.map((label: string, index: number) => (
|
||||||
</MDTypography>
|
<Box key={index}>
|
||||||
|
<MDBadgeDot color={chartColors[index]} size="sm" badgeContent={label} />
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
))) : null
|
||||||
|
}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Grid>
|
||||||
</Box>
|
</Grid>
|
||||||
) : null}
|
<Divider />
|
||||||
{useMemo(
|
{
|
||||||
() => (
|
description && (
|
||||||
<Box height={height}>
|
<Grid container>
|
||||||
<Pie data={data} options={options} />
|
<Grid item xs={12}>
|
||||||
</Box>
|
<Box pb={2} px={2} display="flex" flexDirection={{xs: "column", sm: "row"}} mt="auto">
|
||||||
),
|
<MDTypography variant="button" color="text" fontWeight="light">
|
||||||
[chart, height]
|
{parse(description)}
|
||||||
)}
|
</MDTypography>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
||||||
return title || description ? <Card>{renderChart}</Card> : renderChart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Declaring default props for PieChart
|
// Declaring default props for PieChart
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* QQQ - Low-code Application Framework for Engineers.
|
|
||||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
|
||||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
|
||||||
* contact@kingsrook.com
|
|
||||||
* https://github.com/Kingsrook/
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import Box from "@mui/material/Box";
|
|
||||||
import Card from "@mui/material/Card";
|
|
||||||
import Divider from "@mui/material/Divider";
|
|
||||||
import Grid from "@mui/material/Grid";
|
|
||||||
import parse from "html-react-parser";
|
|
||||||
import MDBadgeDot from "qqq/components/legacy/MDBadgeDot";
|
|
||||||
import MDTypography from "qqq/components/legacy/MDTypography";
|
|
||||||
import PieChart, {PieChartData} from "qqq/components/widgets/charts/piechart/PieChart";
|
|
||||||
|
|
||||||
// Declaring props types for PieChart
|
|
||||||
interface Props
|
|
||||||
{
|
|
||||||
title?: string;
|
|
||||||
description?: string;
|
|
||||||
data: PieChartData;
|
|
||||||
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
function PieChartCard({title, description, data}: Props): JSX.Element
|
|
||||||
{
|
|
||||||
const allBackgroundColors = ["info", "warning", "primary", "success", "error", "secondary", "dark"];
|
|
||||||
|
|
||||||
if (data && data.dataset)
|
|
||||||
{
|
|
||||||
data.dataset.backgroundColors = allBackgroundColors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card sx={{height: "100%", width: "100%", display: "flex"}}>
|
|
||||||
<Box display="flex" pt={2} px={2}>
|
|
||||||
<MDTypography variant="h5">{title}</MDTypography>
|
|
||||||
</Box>
|
|
||||||
<Box mt={3}>
|
|
||||||
<Grid container alignItems="center">
|
|
||||||
<Grid item xs={7}>
|
|
||||||
<PieChart chart={data} height="9.5rem" />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={5}>
|
|
||||||
<Box pr={1}>
|
|
||||||
{
|
|
||||||
data && data.labels ? (
|
|
||||||
(data.labels.map((label: string, index: number) => (
|
|
||||||
<Box key={index}>
|
|
||||||
<MDBadgeDot color={allBackgroundColors[index]} size="sm" badgeContent={label} />
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
))) : null
|
|
||||||
}
|
|
||||||
</Box>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Divider />
|
|
||||||
{
|
|
||||||
description && (
|
|
||||||
<Grid container>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Box pb={2} px={2} display="flex" flexDirection={{xs: "column", sm: "row"}} mt="auto">
|
|
||||||
<MDTypography variant="button" color="text" fontWeight="light">
|
|
||||||
{parse(description)}
|
|
||||||
</MDTypography>
|
|
||||||
</Box>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</Box>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PieChartCard;
|
|
@ -59,16 +59,12 @@ function configs(labels: any, datasets: any)
|
|||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: true,
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: {
|
legend: {
|
||||||
display: false,
|
display: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: "index",
|
|
||||||
},
|
|
||||||
scales: {
|
scales: {
|
||||||
y: {
|
y: {
|
||||||
grid: {
|
grid: {
|
||||||
|
@ -23,7 +23,7 @@ import {Theme} from "@mui/material";
|
|||||||
import Autocomplete from "@mui/material/Autocomplete";
|
import Autocomplete from "@mui/material/Autocomplete";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import {SxProps} from "@mui/system";
|
import {SxProps} from "@mui/system";
|
||||||
import React from "react";
|
import React, {useEffect} from "react";
|
||||||
|
|
||||||
|
|
||||||
export interface DropdownOption
|
export interface DropdownOption
|
||||||
@ -37,14 +37,25 @@ export interface DropdownOption
|
|||||||
/////////////////////////
|
/////////////////////////
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
|
defaultValue?: any;
|
||||||
|
localStorageKey?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
dropdownOptions?: DropdownOption[];
|
dropdownOptions?: DropdownOption[];
|
||||||
onChangeCallback?: (dropdownLabel: string, data: any) => void;
|
onChangeCallback?: (dropdownLabel: string, data: any) => void;
|
||||||
sx?: SxProps<Theme>;
|
sx?: SxProps<Theme>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenu({label, dropdownOptions, onChangeCallback, sx}: Props): JSX.Element
|
function DropdownMenu({localStorageKey, defaultValue, label, dropdownOptions, onChangeCallback, sx}: Props): JSX.Element
|
||||||
{
|
{
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(defaultValue)
|
||||||
|
{
|
||||||
|
console.log("CALLING CALLBACK...")
|
||||||
|
onChangeCallback(label, JSON.parse(localStorage.getItem(localStorageKey)));
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleOnChange = (event: any, value: any, reason: string) =>
|
const handleOnChange = (event: any, value: any, reason: string) =>
|
||||||
{
|
{
|
||||||
onChangeCallback(label, value);
|
onChangeCallback(label, value);
|
||||||
@ -54,12 +65,14 @@ function DropdownMenu({label, dropdownOptions, onChangeCallback, sx}: Props): JS
|
|||||||
dropdownOptions ? (
|
dropdownOptions ? (
|
||||||
<span style={{whiteSpace: "nowrap"}}>
|
<span style={{whiteSpace: "nowrap"}}>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
|
defaultValue={defaultValue}
|
||||||
size="small"
|
size="small"
|
||||||
disablePortal
|
disablePortal
|
||||||
id={`${label}-combo-box`}
|
id={`${label}-combo-box`}
|
||||||
options={dropdownOptions}
|
options={dropdownOptions}
|
||||||
sx={{...sx, cursor: "pointer"}}
|
sx={{...sx, cursor: "pointer"}}
|
||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
|
isOptionEqualToValue={(option, value) => option.id === value.id}
|
||||||
renderInput={(params: any) => <TextField {...params} label={label} />}
|
renderInput={(params: any) => <TextField {...params} label={label} />}
|
||||||
renderOption={(props, option: DropdownOption) => (
|
renderOption={(props, option: DropdownOption) => (
|
||||||
<li {...props} style={{whiteSpace: "normal"}}>{option.label}</li>
|
<li {...props} style={{whiteSpace: "normal"}}>{option.label}</li>
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
|
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
|
||||||
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||||
import {Skeleton} from "@mui/material";
|
import {Skeleton} from "@mui/material";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
@ -31,19 +32,19 @@ import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
|||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
title: string;
|
widgetMetaData: QWidgetMetaData;
|
||||||
data: any;
|
data: any;
|
||||||
reloadWidgetCallback?: (params: string) => void;
|
reloadWidgetCallback?: (params: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldValueListWidget.defaultProps = {};
|
FieldValueListWidget.defaultProps = {};
|
||||||
|
|
||||||
function FieldValueListWidget({title, data, reloadWidgetCallback}: Props): JSX.Element
|
function FieldValueListWidget({widgetMetaData, data, reloadWidgetCallback}: Props): JSX.Element
|
||||||
{
|
{
|
||||||
if(data?.dropdownNeedsSelectedText)
|
if(data?.dropdownNeedsSelectedText)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<Widget label={title} widgetData={data} reloadWidgetCallback={reloadWidgetCallback}>
|
<Widget widgetMetaData={widgetMetaData} widgetData={data} reloadWidgetCallback={reloadWidgetCallback}>
|
||||||
<br />
|
<br />
|
||||||
</Widget>
|
</Widget>
|
||||||
);
|
);
|
||||||
@ -53,7 +54,7 @@ function FieldValueListWidget({title, data, reloadWidgetCallback}: Props): JSX.E
|
|||||||
{
|
{
|
||||||
const skeletons = [75, 50, 90];
|
const skeletons = [75, 50, 90];
|
||||||
return (
|
return (
|
||||||
<Widget label={title}>
|
<Widget widgetMetaData={widgetMetaData}>
|
||||||
<Box p={3} pt={0} display="flex" flexDirection="column">
|
<Box p={3} pt={0} display="flex" flexDirection="column">
|
||||||
{skeletons.map((s) =>
|
{skeletons.map((s) =>
|
||||||
(
|
(
|
||||||
@ -79,7 +80,7 @@ function FieldValueListWidget({title, data, reloadWidgetCallback}: Props): JSX.E
|
|||||||
const fieldIndentLevels = data.fieldIndentLevels ?? {};
|
const fieldIndentLevels = data.fieldIndentLevels ?? {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Widget label={title} widgetData={data} reloadWidgetCallback={reloadWidgetCallback}>
|
<Widget widgetMetaData={widgetMetaData} widgetData={data} reloadWidgetCallback={reloadWidgetCallback}>
|
||||||
<Box p={3} pt={0} display="flex" flexDirection="column">
|
<Box p={3} pt={0} display="flex" flexDirection="column">
|
||||||
{
|
{
|
||||||
fields.map((field: QFieldMetaData, index: number) => (
|
fields.map((field: QFieldMetaData, index: number) => (
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||||
|
import {QWidgetMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QWidgetMetaData";
|
||||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||||
import {DataGridPro, GridCallbackDetails, GridRowParams, MuiEvent} from "@mui/x-data-grid-pro";
|
import {DataGridPro, GridCallbackDetails, GridRowParams, MuiEvent} from "@mui/x-data-grid-pro";
|
||||||
import React, {useEffect, useState} from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
@ -30,7 +31,7 @@ import Client from "qqq/utils/qqq/Client";
|
|||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
title: string;
|
widgetMetaData: QWidgetMetaData;
|
||||||
data: any;
|
data: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ RecordGridWidget.defaultProps = {};
|
|||||||
|
|
||||||
const qController = Client.getInstance();
|
const qController = Client.getInstance();
|
||||||
|
|
||||||
function RecordGridWidget({title, data}: Props): JSX.Element
|
function RecordGridWidget({widgetMetaData, data}: Props): JSX.Element
|
||||||
{
|
{
|
||||||
const [rows, setRows] = useState([]);
|
const [rows, setRows] = useState([]);
|
||||||
const [columns, setColumns] = useState([]);
|
const [columns, setColumns] = useState([]);
|
||||||
@ -121,7 +122,7 @@ function RecordGridWidget({title, data}: Props): JSX.Element
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Widget
|
<Widget
|
||||||
label={title}
|
widgetMetaData={widgetMetaData}
|
||||||
labelAdditionalComponentsLeft={labelAdditionalComponentsLeft}
|
labelAdditionalComponentsLeft={labelAdditionalComponentsLeft}
|
||||||
labelAdditionalComponentsRight={labelAdditionalComponentsRight}
|
labelAdditionalComponentsRight={labelAdditionalComponentsRight}
|
||||||
>
|
>
|
||||||
|
@ -19,11 +19,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {CircularProgress, Typography} from "@mui/material";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Card from "@mui/material/Card";
|
|
||||||
import Divider from "@mui/material/Divider";
|
import Divider from "@mui/material/Divider";
|
||||||
import Icon from "@mui/material/Icon";
|
import React, {ReactNode} from "react";
|
||||||
import {ReactNode} from "react";
|
import {NavLink} from "react-router-dom";
|
||||||
import MDTypography from "qqq/components/legacy/MDTypography";
|
import MDTypography from "qqq/components/legacy/MDTypography";
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
@ -31,8 +31,9 @@ import MDTypography from "qqq/components/legacy/MDTypography";
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
export interface StatisticsCardData
|
export interface StatisticsCardData
|
||||||
{
|
{
|
||||||
title: string;
|
|
||||||
count: number;
|
count: number;
|
||||||
|
countFontSize: string;
|
||||||
|
countURL?: string;
|
||||||
percentageAmount: number;
|
percentageAmount: number;
|
||||||
percentageLabel: string;
|
percentageLabel: string;
|
||||||
}
|
}
|
||||||
@ -42,7 +43,6 @@ export interface StatisticsCardData
|
|||||||
/////////////////////////
|
/////////////////////////
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
title: string
|
|
||||||
data: StatisticsCardData;
|
data: StatisticsCardData;
|
||||||
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark";
|
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark";
|
||||||
icon: ReactNode;
|
icon: ReactNode;
|
||||||
@ -61,7 +61,7 @@ StatisticsCard.defaultProps = {
|
|||||||
increaseIsGood: true
|
increaseIsGood: true
|
||||||
};
|
};
|
||||||
|
|
||||||
function StatisticsCard({title, data, color, icon, increaseIsGood}: Props): JSX.Element
|
function StatisticsCard({data, color, icon, increaseIsGood}: Props): JSX.Element
|
||||||
{
|
{
|
||||||
const {count, percentageAmount, percentageLabel} = data;
|
const {count, percentageAmount, percentageLabel} = data;
|
||||||
|
|
||||||
@ -90,39 +90,30 @@ function StatisticsCard({title, data, color, icon, increaseIsGood}: Props): JSX.
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<Card sx={{height: "100%", alignItems: "stretch", flexGrow: 1, display: "flex", marginTop: 3, paddingTop: "0px"}}>
|
<Box mt={0} sx={{height: "100%", flexGrow: 1, flexDirection: "column", display: "flex", paddingTop: "0px"}}>
|
||||||
<Box display="flex" justifyContent="space-between" pt={1} px={2}>
|
<Box mt={0} display="flex" justifyContent="center">
|
||||||
<Box
|
{
|
||||||
color="#ffffff"
|
count !== undefined ? (
|
||||||
borderRadius="xl"
|
<Typography mt={0} sx={{color: "#344767", display: "flex", alignContent: "flex-end", fontSize: data?.countFontSize ? data?.countFontSize : "40px"}}>
|
||||||
display="flex"
|
{
|
||||||
justifyContent="center"
|
data.countURL ? (
|
||||||
alignItems="center"
|
<NavLink to={data.countURL}>{count.toLocaleString()}</NavLink>
|
||||||
width="4rem"
|
) : (
|
||||||
height="4rem"
|
count.toLocaleString()
|
||||||
mt={-3}
|
)
|
||||||
sx={{borderRadius: "10px", backgroundColor: color}}
|
}
|
||||||
>
|
</Typography>
|
||||||
<Icon fontSize="medium" color="inherit">
|
) : (
|
||||||
{icon}
|
<CircularProgress sx={{marginTop: "1rem", marginBottom: "20px"}} color="inherit" size={data?.countFontSize ? data.countFontSize : 30}/>
|
||||||
</Icon>
|
)
|
||||||
</Box>
|
}
|
||||||
<Box textAlign="right" lineHeight={1.25}>
|
|
||||||
<MDTypography variant="button" fontWeight="light" color="text">
|
|
||||||
{title}
|
|
||||||
</MDTypography>
|
|
||||||
{
|
|
||||||
count !== undefined ? (
|
|
||||||
<MDTypography variant="h4">{count.toLocaleString()}</MDTypography>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
{
|
{
|
||||||
percentageAmount !== undefined && percentageAmount !== 0 ? (
|
percentageAmount !== undefined && percentageAmount !== 0 ? (
|
||||||
<Box px={2}>
|
<Box pb={2}>
|
||||||
<Divider />
|
|
||||||
<MDTypography component="p" variant="button" color="text" display="flex">
|
<Divider sx={{marginTop: "0px"}} />
|
||||||
|
<MDTypography pl={3} component="p" variant="button" color="text" display="flex">
|
||||||
<MDTypography
|
<MDTypography
|
||||||
component="span"
|
component="span"
|
||||||
variant="button"
|
variant="button"
|
||||||
@ -136,7 +127,7 @@ function StatisticsCard({title, data, color, icon, increaseIsGood}: Props): JSX.
|
|||||||
</Box>
|
</Box>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
</Card>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,20 +51,12 @@ export interface TableDataInput
|
|||||||
/////////////////////////
|
/////////////////////////
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
title: string;
|
|
||||||
linkText?: string;
|
|
||||||
linkURL?: string;
|
|
||||||
noRowsFoundHTML?: string;
|
noRowsFoundHTML?: string;
|
||||||
data: TableDataInput;
|
data: TableDataInput;
|
||||||
reloadWidgetCallback?: (params: string) => void;
|
|
||||||
widgetIndex?: number;
|
|
||||||
isChild?: boolean;
|
|
||||||
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const qController = Client.getInstance();
|
const qController = Client.getInstance();
|
||||||
function TableCard({noRowsFoundHTML, data, reloadWidgetCallback}: Props): JSX.Element
|
function TableCard({noRowsFoundHTML, data}: Props): JSX.Element
|
||||||
{
|
{
|
||||||
const [qInstance, setQInstance] = useState(null as QInstance);
|
const [qInstance, setQInstance] = useState(null as QInstance);
|
||||||
|
|
||||||
|
@ -114,6 +114,14 @@ async function getDefaultFilter(tableMetaData: QTableMetaData, searchParams: URL
|
|||||||
{
|
{
|
||||||
values = await qController.possibleValues(tableMetaData.name, field.name, "", values);
|
values = await qController.possibleValues(tableMetaData.name, field.name, "", values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// log message if no values were returned //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
if (! values || values.length === 0)
|
||||||
|
{
|
||||||
|
console.warn("WARNING: No possible values were returned for [" + field.possibleValueSourceName + "] for values [" + criteria.values + "].");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultFilter.items.push({
|
defaultFilter.items.push({
|
||||||
|
Reference in New Issue
Block a user