diff --git a/jams-react-client/src/assets/img/BG-ID_Jami.png b/jams-react-client/src/assets/img/BG-ID_Jami.png new file mode 100644 index 0000000000000000000000000000000000000000..ddd8f6bdd634939f9debf2b4a355e00ff32ffc7e Binary files /dev/null and b/jams-react-client/src/assets/img/BG-ID_Jami.png differ diff --git a/jams-react-client/src/assets/img/BTN_Edit.svg b/jams-react-client/src/assets/img/BTN_Edit.svg deleted file mode 100644 index f2a8829a446dd3f645eb4349276b61d12ad3070c..0000000000000000000000000000000000000000 --- a/jams-react-client/src/assets/img/BTN_Edit.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="6" height="6" viewBox="0 0 6 6"><defs><style>.a{fill:#005699;}</style></defs><g transform="translate(-4 -3.375)"><g transform="translate(3.567 3.567)"><path class="a" d="M2.19,6H0V3.81L3.84,0,6,2.19,4.41,3.75l-.3-.3.36-.36L2.88,1.5.42,3.99V5.58H2.01l1.2-1.2.3.3L2.19,6ZM3.81.6h0l-.63.63L4.77,2.82l.63-.63L3.81.6Z" transform="translate(0.434 -0.192)"/></g></g></svg> \ No newline at end of file diff --git a/jams-react-client/src/assets/img/jami_id.svg b/jams-react-client/src/assets/img/jami_id.svg index 5d05c029fc55284e3254686d7227c3e2488b4a77..d48b225b05994e89bf67fdf40e67b9c10bd151e6 100644 --- a/jams-react-client/src/assets/img/jami_id.svg +++ b/jams-react-client/src/assets/img/jami_id.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="29.352" height="10.357" viewBox="0 0 29.352 10.357"><defs><style>.a,.b{fill:#fff;}.b{stroke:#fff;stroke-miterlimit:10;stroke-width:0.5px;}</style></defs><g transform="translate(0 0.25)"><g transform="translate(0 0)"><path class="a" d="M0,6.84H0v-.7a1.891,1.891,0,0,0,1.333-.562,1.887,1.887,0,0,0,.551-1.338v-2.5h.7v2.5A2.6,2.6,0,0,1,0,6.84ZM2.235.95A.475.475,0,0,1,1.761.475.469.469,0,0,1,2.235,0a.475.475,0,0,1,.474.475A.481.481,0,0,1,2.235.95Z" transform="translate(0 1.461)"/><path class="a" d="M6.051,5.168V1.862a1.165,1.165,0,0,0-2.329.01v3.3h-.7V1.862a1.16,1.16,0,1,0-2.32.01v3.3H0V1.862A1.858,1.858,0,0,1,3.371.779a1.864,1.864,0,0,1,3.38,1.093v3.3Z" transform="translate(8.75 3.085)"/><path class="a" d="M.824,6.793h-.7V1.738h.7V6.792ZM.474.95A.469.469,0,0,1,0,.475a.473.473,0,1,1,.947,0A.469.469,0,0,1,.474.95Z" transform="translate(15.871 1.461)"/><path class="a" d="M5.187,5.2H2.593A2.6,2.6,0,1,1,5.187,2.6V5.2ZM2.593.686a1.916,1.916,0,0,0,0,3.832H4.5V2.6A1.915,1.915,0,0,0,2.593.686Z" transform="translate(3.115 3.109)"/><path class="a" d="M.824,6.793h-.7V1.738h.7V6.792ZM.474.95A.469.469,0,0,1,0,.475a.474.474,0,1,1,.947,0A.469.469,0,0,1,.474.95Z" transform="translate(20.764 1.461)"/><path class="a" d="M2.12,5.048H0V0H2.12A3.072,3.072,0,0,1,3.537.317a2.341,2.341,0,0,1,.959.891,2.534,2.534,0,0,1,.341,1.316A2.531,2.531,0,0,1,4.5,3.84a2.339,2.339,0,0,1-.959.891A3.077,3.077,0,0,1,2.12,5.048ZM.719.627V4.421H2.077a2.329,2.329,0,0,0,1.075-.238,1.722,1.722,0,0,0,.715-.667,1.932,1.932,0,0,0,.252-.991,1.935,1.935,0,0,0-.252-.992A1.726,1.726,0,0,0,3.152.865,2.334,2.334,0,0,0,2.077.627Z" transform="translate(22.022 3.202)"/><path class="b" d="M8.372,9.857H0V2.083A2.078,2.078,0,0,1,2.068,0h6.3A2.078,2.078,0,0,1,10.44,2.083V7.774A2.078,2.078,0,0,1,8.372,9.857ZM2.068.242A1.836,1.836,0,0,0,.24,2.083V9.615H8.372A1.836,1.836,0,0,0,10.2,7.774V2.083A1.836,1.836,0,0,0,8.372.242Z" transform="translate(18.662)"/></g></g></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="30" height="24" viewBox="0 0 30 24"><defs><style>.a{fill:#005699;}.b,.d{fill:none;}.b{stroke:#005699;stroke-width:1.5px;}.c{stroke:none;}</style></defs><g transform="translate(7.328 6.159)"><g transform="translate(0 0)"><path class="a" d="M-2124.191-3452.351h.007a1.335,1.335,0,0,0,.972-.341,1.106,1.106,0,0,0,.351-.847.958.958,0,0,0-.34-.76,1.407,1.407,0,0,0-.983-.337h-.012a1.365,1.365,0,0,0-.977.342,1.1,1.1,0,0,0-.053,1.549l.055.056a1.364,1.364,0,0,0,.973.341Z" transform="translate(2125.521 3454.638)"/></g><g transform="translate(0.358 0.062)"><path class="a" d="M-2123.846-3442.183h9.042a8,8,0,0,0,3.567-.767,5.651,5.651,0,0,0,2.353-2.118,6.555,6.555,0,0,0,0-6.4,5.651,5.651,0,0,0-2.351-2.114,7.975,7.975,0,0,0-3.562-.766h-3.427v8.653h2.057v-7.142h1.216a4.586,4.586,0,0,1,4.953,4.187,4.586,4.586,0,0,1-4.187,4.954,4.585,4.585,0,0,1-.772,0h-6.942v-6.035h-1.946v6.035h0Z" transform="translate(2123.846 3454.35)"/></g></g><g class="b"><path class="c" d="M5,0H25a5,5,0,0,1,5,5V24a0,0,0,0,1,0,0H5a5,5,0,0,1-5-5V5A5,5,0,0,1,5,0Z"/><path class="d" d="M5,.75H25A4.25,4.25,0,0,1,29.25,5V22.5a.75.75,0,0,1-.75.75H5A4.25,4.25,0,0,1,.75,19V5A4.25,4.25,0,0,1,5,.75Z"/></g></svg> \ No newline at end of file diff --git a/jams-react-client/src/components/CustomUiPreview/CustomUiPreview.js b/jams-react-client/src/components/CustomUiPreview/CustomUiPreview.js index c1819729e7dd8c6b92120d583a711b1154a3cd05..f03f04abc0b1f85ad1b761f699e54e11953345d7 100644 --- a/jams-react-client/src/components/CustomUiPreview/CustomUiPreview.js +++ b/jams-react-client/src/components/CustomUiPreview/CustomUiPreview.js @@ -2,7 +2,8 @@ import React from "react"; import { makeStyles } from "@mui/styles"; -import logoImage from "assets/img/logo-jami-net.svg"; +import backgroundImage from "assets/img/BG-ID_Jami.png"; +import logoImage from "assets/img/favicon_jami.png"; import TipBox from "./TipBox"; import JamiIdCard from "./JamiIdCard"; @@ -12,7 +13,7 @@ import { url_port } from "../../globalUrls"; const styles = { root: { - height: "250px", + height: "350px", position: (props) => (props.isOldPreview ? "relative" : "absolute"), left: 0, right: 0, @@ -27,7 +28,7 @@ const styles = { top: "50%", transform: "translate(-50%, -50%)", width: "100%", - height: "250px", + height: "350px", borderRadius: "5px", backgroundColor: "white", @@ -35,49 +36,50 @@ const styles = { boxShadow: "0px 3px 6px #0000005C", }, sidebar: { - // minWidth: "100px", + minWidth: "100px", width: "100px", height: "100%", backgroundColor: "#f4f4f4", borderRadius: "5px 0px 0px 5px", }, - mainContent: { + welcomeScreen: { + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "center", flex: 1, + padding: "2rem", + borderRadius: "0px 5px 5px 0px", + backgroundColor: (props) => props.backgroundColor, backgroundImage: (props) => `url(${props.backgroundUrl})`, backgroundSize: "cover", backgroundPosition: "center", - borderRadius: "0px 5px 5px 0px", - - display: "flex", - flexDirection: "column", - justifyContent: "center", - alignItems: "center", }, - welcomeRow: { + mainContent: { display: "flex", - flexDirection: (props) => (props.isCompactDisplay ? "column" : "row"), + flexDirection: "column", width: "400px", - height: "100px", + // height: "100px", justifyContent: "center", alignItems: "center", marginBottom: "0.5rem", }, logo: { - width: "50%", + height: "40px", objectFit: "contain", - height: "100%", - marginRight: "1rem", + scale: (props) => props.logoSize / 100, }, welcomeCard: { display: "flex", - flexDirection: (props) => (props.hasLogo ? "column" : "row"), - borderRadius: "9px", - backgroundColor: (props) => - props.isCompactDisplay ? "transparent" : "#f4f4f4", + flexDirection: "column", + // justifyContent: "center", + alignItems: "center", + borderRadius: "3px", + backgroundColor: (props) => props.mainBoxColor, padding: "10px", - width: (props) => (props.hasLogo ? "50%" : "100%"), + width: "50%", }, title: { margin: 0, @@ -86,6 +88,7 @@ const styles = { }, description: { fontSize: "8px", + textAlign: "center", }, tipRow: { display: "flex", @@ -111,8 +114,12 @@ export default function CustomUiPreview({ hasBackground, backgroundColor, backgroundUrl, + tipBoxAndIdColor, + hasMainBoxColor, + mainBoxColor, hasLogo, logoUrl, + logoSize, } = uiCustomization; if (!title) { @@ -131,26 +138,25 @@ export default function CustomUiPreview({ } if (hasBackground === false) { - backgroundColor = "white"; - backgroundUrl = ""; - } - if (backgroundUrl !== "") { - backgroundColor = "white"; - } - if (backgroundUrl) { + backgroundColor = ""; + backgroundUrl = backgroundImage; + } else if (backgroundUrl) { backgroundUrl = encodeURI(`${url_path}:${url_port}/${backgroundUrl}`); } + if (!hasMainBoxColor) { + mainBoxColor = ""; + } + const isCompactDisplay = !hasTitle && !hasDescription && !hasTips; const classes = useStyles({ - backgroundColor, - backgroundUrl, - isCompactDisplay, isOldPreview, opacity, - hasTitle, - hasLogo, + backgroundColor, + backgroundUrl, + mainBoxColor, + logoSize, }); const tip1 = i18next.t( @@ -164,26 +170,27 @@ export default function CustomUiPreview({ <div className={classes.root}> <div className={classes.previewWindow}> <div className={classes.sidebar}></div> - <div className={classes.mainContent}> - <div className={classes.welcomeRow}> + <div className={classes.welcomeScreen}> + <div className={classes.mainContent}> {hasLogo ? ( <img src={logoUrl} alt="logo" className={classes.logo}></img> ) : null} <div className={classes.welcomeCard}> - <div> - {hasTitle ? <h4 className={classes.title}>{title}</h4> : null} - {hasDescription ? ( - <p className={classes.description}>{description}</p> - ) : null} - </div> - <JamiIdCard isCompactDisplay={isCompactDisplay} /> + {hasTitle ? <h4 className={classes.title}>{title}</h4> : null} + {hasDescription ? ( + <p className={classes.description}>{description}</p> + ) : null} + <JamiIdCard + isCompactDisplay={isCompactDisplay} + color={tipBoxAndIdColor} + /> </div> </div> {hasTips ? ( <div className={classes.tipRow}> - <TipBox text={tip1} /> - <TipBox text={tip2} /> - <TipBox text={tip3} /> + <TipBox text={tip1} color={tipBoxAndIdColor} /> + <TipBox text={tip2} color={tipBoxAndIdColor} /> + <TipBox text={tip3} color={tipBoxAndIdColor} /> </div> ) : null} </div> diff --git a/jams-react-client/src/components/CustomUiPreview/JamiIdCard.js b/jams-react-client/src/components/CustomUiPreview/JamiIdCard.js index f6a6e3442e8f5bb24d9a7b5abbdf8c823e93192d..78e1a4bd45b27f3cd899cb2716977096f4d67646 100644 --- a/jams-react-client/src/components/CustomUiPreview/JamiIdCard.js +++ b/jams-react-client/src/components/CustomUiPreview/JamiIdCard.js @@ -4,49 +4,53 @@ import { makeStyles } from "@mui/styles"; import jamiIdImage from "assets/img/jami_id.svg"; import copySvg from "assets/img/BTN_Copy.svg"; -import editSvg from "assets/img/BTN_Edit.svg"; import shareSvg from "assets/img/BTN_Share.svg"; import { infoColor } from "assets/jss/material-dashboard-react"; const styles = { root: { - backgroundColor: (props) => (props.isCompactDisplay ? "#f4f4f4" : "white"), - maxWidth: (props) => (props.isCompactDisplay ? "100%" : "150px"), - width: (props) => (props.isCompactDisplay ? "100%" : "150px"), - height: (props) => (props.isCompactDisplay ? "20px" : "40px"), + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "center", position: "relative", - borderRadius: "9px", - overflow: "hidden", - margin: "auto", + width: "150px", + height: "20px", + borderRadius: "5px", + }, + main: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "center", + gap: "4px", + width: "100px", + height: "100%", + borderRadius: "5px 0px 0px 5px", + backgroundColor: (props) => props.color, }, logo: { - position: "absolute", - left: "-1px", - top: 0, - backgroundColor: infoColor[0], - borderRadius: "20px 20px 20px 0px", - padding: "0px 5px 0px 5px", + marginLeft: "5px", + height: "12px", }, nameplate: { - position: "absolute", - left: "50%", - top: "50%", - transform: (props) => - props.isCompactDisplay ? "translate(-50%, -50%)" : "translate(-50%, 50%)", + flex: 2, textAlign: "center", - fontSize: "5px", + fontSize: "12px", + color: infoColor[0], }, icons: { - position: "absolute", - right: "0", - height: "16px", - top: (props) => (props.isCompactDisplay ? "50%" : "0"), - transform: (props) => - props.isCompactDisplay ? "translate(0%, -50%)" : "none", - marginRight: "2px", + display: "flex", + flexDirection: "row", + alignItems: "center", + gap: "6px", + padding: "0px 6px 0px 6px", + height: "100%", + marginLeft: "1px", + borderRadius: "0px 5px 5px 0px", + backgroundColor: (props) => props.color, }, icon: { - margin: "5px", width: "6px", height: "6px", }, @@ -54,19 +58,16 @@ const styles = { const useStyles = makeStyles(styles); -export default function JamiIdCard({ isCompactDisplay }) { - const classes = useStyles({ isCompactDisplay }); +export default function JamiIdCard({ color, isCompactDisplay }) { + const classes = useStyles({ color, isCompactDisplay }); return ( <div className={classes.root}> - <div className={classes.logo}> - <img src={jamiIdImage} alt="jami id" /> + <div className={classes.main}> + <img className={classes.logo} src={jamiIdImage} alt="jami id" /> + <div className={classes.nameplate}>placeholder</div> </div> - - <div className={classes.nameplate}>placeholder</div> - <div className={classes.icons}> - <img src={editSvg} alt="edit" className={classes.icon} /> <img src={copySvg} alt="copy" className={classes.icon} /> <img src={shareSvg} alt="share" className={classes.icon} /> </div> diff --git a/jams-react-client/src/components/CustomUiPreview/TipBox.js b/jams-react-client/src/components/CustomUiPreview/TipBox.js index 1df6a6450a2e7e1fc0ee34f7d45f415e7305d80d..7106c3ea24da766c1b4acb8b91abba139355ab80 100644 --- a/jams-react-client/src/components/CustomUiPreview/TipBox.js +++ b/jams-react-client/src/components/CustomUiPreview/TipBox.js @@ -7,9 +7,9 @@ const styles = { root: { maxWidth: "115px", flexBasis: "100%", - backgroundColor: "#f4f4f4", + backgroundColor: (props) => props.color, padding: "0px 5px 5px 5px", - borderRadius: "10px", + borderRadius: "3px", }, img: { verticalAlign: "middle", @@ -27,8 +27,8 @@ const styles = { const useStyles = makeStyles(styles); -export default function TipBox({ text }) { - const classes = useStyles(); +export default function TipBox({ color, text }) { + const classes = useStyles({ color }); return ( <div className={classes.root}> diff --git a/jams-react-client/src/views/Blueprint/ColorPickerPopup.js b/jams-react-client/src/views/Blueprint/ColorPickerPopup.js new file mode 100644 index 0000000000000000000000000000000000000000..5cde80a89550ba9ab510606d59adaf06c947783a --- /dev/null +++ b/jams-react-client/src/views/Blueprint/ColorPickerPopup.js @@ -0,0 +1,72 @@ +import React, { useState } from "react"; +import { makeStyles } from "@mui/styles"; +import { HexAlphaColorPicker, HexColorPicker } from "react-colorful"; + +const styles = { + root: { + position: "relative", + padding: "0 20px", + }, + colorButtonStyle: { + borderRadius: "50%", + width: "20px", + height: "20px", + border: "1px solid grey", + outline: "none", + cursor: "pointer", + }, + popover: { + position: "absolute", + left: "60px", + bottom: 0, + zIndex: "2", + }, + cover: { + position: "fixed", + top: "0px", + right: "0px", + bottom: "0px", + left: "0px", + backgroundColor: "#00000040", + }, +}; + +const useStyles = makeStyles(styles); + +export default function ColorPickerPopup({ hasAlphaChannel, color, onChange }) { + const classes = useStyles(); + + const [displayColorPicker, setDisplayColorPicker] = useState(false); + + const handleClickColor = () => { + setDisplayColorPicker(!displayColorPicker); + }; + + const handleCloseColor = () => { + setDisplayColorPicker(false); + }; + + return ( + <div className={classes.root}> + <button + style={{ + backgroundColor: color, + }} + className={classes.colorButtonStyle} + onClick={() => { + handleClickColor(); + }} + /> + {displayColorPicker && ( + <div className={classes.popover}> + <div className={classes.cover} onClick={handleCloseColor} /> + {hasAlphaChannel ? ( + <HexAlphaColorPicker color={color} onChange={onChange} /> + ) : ( + <HexColorPicker color={color} onChange={onChange} /> + )} + </div> + )} + </div> + ); +} diff --git a/jams-react-client/src/views/Blueprint/EditBlueprintUi.js b/jams-react-client/src/views/Blueprint/EditBlueprintUi.js index 263a9ba9e38249f8085bdbb6903e2da5664a3640..451a67997350d1fcb0939a60ac1f4e29cd093652 100644 --- a/jams-react-client/src/views/Blueprint/EditBlueprintUi.js +++ b/jams-react-client/src/views/Blueprint/EditBlueprintUi.js @@ -33,7 +33,7 @@ import { PolicyDataContext } from "./PolicyDataContext"; const styles = { ...dashboardStyle, card: { - minWidth: "500px", + minWidth: "600px", }, cardBody: { flexGrow: 1, @@ -110,7 +110,15 @@ export default function EditBlueprintUi({ blueprintName }) { const [opacity, setOpacity] = useState(0); const handleUpdateUi = (field, value) => { - const newUiCustomization = { ...uiCustomization, [field]: value }; + let newUiCustomization; + + if (typeof field === "object") { + // If field is an object, it means that the whole uiCustomization object is passed + newUiCustomization = field; + } else { + newUiCustomization = { ...uiCustomization, [field]: value }; + } + const newUi = newUiCustomization.isCustomizationEnabled ? newUiCustomization : DEFAULT_UI_CUSTOMIZATION; @@ -118,7 +126,10 @@ export default function EditBlueprintUi({ blueprintName }) { if ( field === "title" || field === "description" || - field === "backgroundColor" + field === "backgroundColor" || + field === "tipBoxAndIdColor" || + field === "mainBoxColor" || + field === "logoSize" ) { // Don't fade in for those fields setOldUiCustomization(newUiCustomization); @@ -149,18 +160,16 @@ export default function EditBlueprintUi({ blueprintName }) { const newUrl = `${api_path_get_image}/${blueprintName}/${imgType}/${acceptedFiles[0].name}`; if (imgType === "background") { - setUiCustomization({ + handleUpdateUi({ ...uiCustomization, backgroundUrl: newUrl, backgroundColor: "", }); - handleUpdateUi("backgroundUrl", newUrl); } else if (imgType === "logo") { - setUiCustomization({ + handleUpdateUi({ ...uiCustomization, logoUrl: newUrl, }); - handleUpdateUi("logoUrl", newUrl); } }) .catch((error) => { diff --git a/jams-react-client/src/views/Blueprint/EditBlueprintUiForm.js b/jams-react-client/src/views/Blueprint/EditBlueprintUiForm.js index a1ad28a200fc554ba1d6293b1f2426d0b2778a4c..400d840540b9f34dad6987ded75209dc5bb44cb2 100644 --- a/jams-react-client/src/views/Blueprint/EditBlueprintUiForm.js +++ b/jams-react-client/src/views/Blueprint/EditBlueprintUiForm.js @@ -1,41 +1,17 @@ -import React, { useState } from "react"; +import React from "react"; import Checkbox from "@mui/material/Checkbox"; import Switch from "@mui/material/Switch"; -import { HexColorPicker } from "react-colorful"; import FormGroup from "@mui/material/FormGroup"; import FormControlLabel from "@mui/material/FormControlLabel"; -import { TextField } from "@mui/material"; -import { makeStyles } from "@mui/styles"; +import { Box, Button, Slider, TextField } from "@mui/material"; import Typography from "@mui/material/Typography"; import CustomImgDropZone from "components/CustomImgDropZone/CustomImgDropZone"; import i18next from "i18next"; - -const styles = { - colorButtonStyle: { - borderRadius: "50%", - width: "20px", - height: "20px", - border: "1px solid grey", - outline: "none", - cursor: "pointer", - }, - popover: { - position: "absolute", - zIndex: "2", - }, - cover: { - position: "fixed", - top: "0px", - right: "0px", - bottom: "0px", - left: "0px", - }, -}; - -const useStyles = makeStyles(styles); +import ColorPickerPopup from "./ColorPickerPopup"; +import { DEFAULT_UI_CUSTOMIZATION } from "./policyData.constants"; const IsCustomizationEnabledForm = ({ isCustomizationEnabled, @@ -102,6 +78,7 @@ const TitleForm = ({ uiCustomization, handleUpdateUi }) => { }} fullWidth inputProps={{ maxLength: 40 }} + variant="standard" /> </FormGroup> ); @@ -150,6 +127,7 @@ const DescriptionForm = ({ uiCustomization, handleUpdateUi }) => { }} fullWidth inputProps={{ maxLength: 100 }} + variant="standard" /> </> )} @@ -204,90 +182,113 @@ const CustomBackgroundForm = ({ handleImgDrop, bgFile, }) => { - const classes = useStyles(); - - const [displayColorPicker, setDisplayColorPicker] = useState(false); - - const handleClickColor = () => { - setDisplayColorPicker(!displayColorPicker); - }; - const setBgFile = (value) => { handleUpdateUi("bgFile", value); }; - const handleCloseColor = () => { - setDisplayColorPicker(false); - }; + return ( + <> + <span> + {i18next.t( + "instruction_background", + "Choose a background color or a background image" + )} + </span> + <FormGroup + row + style={{ + display: "flex", + alignItems: "center", + justifyContent: "left", + flexDirection: "row", + padding: "10px 0", + }} + > + <ColorPickerPopup + color={uiCustomization.backgroundColor} + onChange={(color) => { + handleColorChange(color); + handleUpdateUi("backgroundColor", color); + }} + /> + + <div style={{ padding: "0 20px" }}> + <Typography>{i18next.t("or", "or")}</Typography> + </div> + + <div style={{ padding: "0 20px" }}> + <CustomImgDropZone + onDrop={(files) => { + handleImgDrop(files, "background"); + }} + label={i18next + .t("upload_an_image", "Upload an image") + .toUpperCase()} + file={bgFile} + setFile={setBgFile} + handleDelete={(e) => { + handleUpdateUi("backgroundUrl", ""); + e.preventDefault(); + e.stopPropagation(); + }} + /> + </div> + </FormGroup> + </> + ); +}; +const TipBoxAndIdColorForm = ({ uiCustomization, handleUpdateUi }) => { return ( - <FormGroup row> - {uiCustomization.hasBackground && ( + <> + <span> + {i18next.t("tip_box_id_color", "Tip Box's and Jami ID color")} + </span> + <ColorPickerPopup + hasAlphaChannel + color={uiCustomization.tipBoxAndIdColor} + onChange={(color) => { + handleUpdateUi("tipBoxAndIdColor", color); + }} + /> + </> + ); +}; + +const MainBoxColorForm = ({ uiCustomization, handleUpdateUi }) => { + return ( + <> + <FormGroup row> + <FormControlLabel + control={ + <Checkbox + checked={uiCustomization.hasMainBoxColor} + color="primary" + onChange={(e) => { + handleUpdateUi("hasMainBoxColor", e.target.checked); + }} + name="hasMainBoxColor" + /> + } + label={i18next.t( + "enable_main_box", + "Add a box behind the title, description and the Jami ID" + )} + /> + </FormGroup> + {uiCustomization.hasMainBoxColor && ( <> - <span> - {i18next.t( - "instruction_background", - "Choose a background color or a background image" - )} - </span> - <FormGroup - style={{ - display: "flex", - alignItems: "center", - justifyContent: "left", - flexDirection: "row", - padding: "10px 0", + <span>{i18next.t("main_box_color", "Box color")}</span> + <ColorPickerPopup + hasAlphaChannel + color={uiCustomization.mainBoxColor} + onChange={(color) => { + handleUpdateUi("mainBoxColor", color); }} - > - <div style={{ padding: "0 20px" }}> - <button - style={{ - backgroundColor: uiCustomization.backgroundColor, - }} - className={classes.colorButtonStyle} - onClick={() => { - handleClickColor(); - }} - /> - {displayColorPicker && ( - <div className={classes.popover}> - <div className={classes.cover} onClick={handleCloseColor} /> - <HexColorPicker - color={uiCustomization.backgroundColor} - onChange={(color) => { - handleColorChange(color); - handleUpdateUi("backgroundColor", color); - }} - /> - </div> - )} - </div> - - <div style={{ padding: "0 20px" }}> - <Typography>{i18next.t("or", "or")}</Typography> - </div> - - <div style={{ padding: "0 20px" }}> - <CustomImgDropZone - onDrop={(files) => { - handleImgDrop(files, "background"); - }} - label={i18next - .t("upload_an_image", "Upload an image") - .toUpperCase()} - file={bgFile} - setFile={setBgFile} - handleDelete={(e) => { - handleUpdateUi("backgroundUrl", ""); - e.preventDefault(); - e.stopPropagation(); - }} - /> - </div> - </FormGroup> + /> </> )} - </FormGroup> + </> ); }; @@ -348,6 +349,25 @@ const LogoForm = ({ ); }; +const LogoSizeForm = ({ uiCustomization, handleUpdateUi }) => { + return ( + <Box sx={{ width: "200px" }}> + <span>{i18next.t("logo_size", "Size")}</span> + <Slider + size="small" + min={10} + max={100} + valueLabelDisplay="auto" + value={uiCustomization.logoSize} + onChange={(e, value) => { + handleUpdateUi("logoSize", value); + }} + sx={{ marginLeft: "1rem" }} + /> + </Box> + ); +}; + const EditBlueprintUiForm = ({ uiCustomization, setUiCustomization, @@ -409,25 +429,55 @@ const EditBlueprintUiForm = ({ uiCustomization={uiCustomization} handleUpdateUi={handleUpdateUi} /> - <CustomBackgroundForm + {uiCustomization.hasBackground && ( + <CustomBackgroundForm + uiCustomization={uiCustomization} + handleColorChange={handleColorChange} + handleUpdateUi={handleUpdateUi} + handleImgDrop={handleImgDrop} + bgFile={bgFile} + /> + )} + <TipBoxAndIdColorForm + uiCustomization={uiCustomization} + handleUpdateUi={handleUpdateUi} + /> + + <MainBoxColorForm uiCustomization={uiCustomization} - handleColorChange={handleColorChange} handleUpdateUi={handleUpdateUi} - handleImgDrop={handleImgDrop} - bgFile={bgFile} /> + <HasLogoForm uiCustomization={uiCustomization} handleUpdateUi={handleUpdateUi} /> {uiCustomization.hasLogo && ( - <LogoForm - handleImgDrop={handleImgDrop} - handleDeleteLogo={handleDeleteLogo} - handleUpdateUi={handleUpdateUi} - logoFile={logoFile} - /> + <> + <LogoForm + handleImgDrop={handleImgDrop} + handleDeleteLogo={handleDeleteLogo} + handleUpdateUi={handleUpdateUi} + logoFile={logoFile} + /> + <LogoSizeForm + uiCustomization={uiCustomization} + handleUpdateUi={handleUpdateUi} + /> + </> )} + + <Button + variant="outlined" + onClick={() => { + handleUpdateUi({ + ...DEFAULT_UI_CUSTOMIZATION, + isCustomizationEnabled: true, + }); + }} + > + {i18next.t("default_settings", "Default Settings").toUpperCase()} + </Button> </> )} </> diff --git a/jams-react-client/src/views/Blueprint/parsePolicyData.js b/jams-react-client/src/views/Blueprint/parsePolicyData.js index c9bbd1011327f9f80c172fe9d1a386afbf6f13e2..48f7afa8dea1da71133111777b7ac9c9325acf70 100644 --- a/jams-react-client/src/views/Blueprint/parsePolicyData.js +++ b/jams-react-client/src/views/Blueprint/parsePolicyData.js @@ -60,6 +60,17 @@ const setConfigurationSettings = (policyData) => { return policyData; }; +const convertArgbToRgba = (argb) => { + if (argb.length === 7) { + return argb; + } + if (argb.length !== 9) { + throw new Error(`Invalid argb value: "${argb}}"`); + } + + return "#" + argb.substr(3, 6) + argb.substr(1, 2); +}; + const setCustomizationSettings = (policyData) => { if (!policyData.uiCustomization) { policyData.uiCustomization = DEFAULT_UI_CUSTOMIZATION; @@ -85,11 +96,19 @@ const setCustomizationSettings = (policyData) => { ui.backgroundUrl = result.backgroundColorOrUrl; } + ui.tipBoxAndIdColor = result.tipBoxAndIdColor + ? convertArgbToRgba(result.tipBoxAndIdColor) + : DEFAULT_UI_CUSTOMIZATION.tipBoxAndIdColor; + + ui.hasMainBoxColor = result.mainBoxColor !== undefined; + ui.mainBoxColor = result.mainBoxColor + ? convertArgbToRgba(result.mainBoxColor) + : DEFAULT_UI_CUSTOMIZATION.mainBoxColor; + // Get the name of the file from the url ui.hasLogo = result.logoUrl !== ""; - if (ui.hasLogo) { - ui.logoUrl = result.logoUrl; - } + ui.logoUrl = result.logoUrl; + ui.logoSize = result.logoSize; policyData.uiCustomization = ui; return policyData; diff --git a/jams-react-client/src/views/Blueprint/policyData.constants.js b/jams-react-client/src/views/Blueprint/policyData.constants.js index f5fcd93d9e6b125bf0232b9c9d5a2ac1863f9f93..e90b9b0bbfb14e040a1f8d3e571412c17af28078 100644 --- a/jams-react-client/src/views/Blueprint/policyData.constants.js +++ b/jams-react-client/src/views/Blueprint/policyData.constants.js @@ -10,8 +10,13 @@ export const DEFAULT_UI_CUSTOMIZATION = { backgroundColor: "", backgroundUrl: "", + tipBoxAndIdColor: "#ffffffff", + hasMainBoxColor: false, + mainBoxColor: "#ffffff80", + hasLogo: true, logoUrl: "", + logoSize: 100, }; export const DEFAULT_POLICY_DATA = { diff --git a/jams-react-client/src/views/Blueprint/updatePolicyData.js b/jams-react-client/src/views/Blueprint/updatePolicyData.js index f301649fac3ce976a2ec4e5b2a8bfa40150a8e80..6b6368bf57b3534529a4b03014dd5faec7df49db 100644 --- a/jams-react-client/src/views/Blueprint/updatePolicyData.js +++ b/jams-react-client/src/views/Blueprint/updatePolicyData.js @@ -4,6 +4,7 @@ import i18next from "i18next"; import configApiCall from "api"; import { api_path_blueprints } from "globalUrls"; import { debounce } from "lodash"; +import { DEFAULT_UI_CUSTOMIZATION } from "./policyData.constants"; const updatePerms = (data, field, value) => { data.defaultModerators = data.blueprintModerators @@ -50,6 +51,17 @@ const updateConfig = (data) => { return data; }; +const convertRgbaToArgb = (rgba) => { + if (rgba.length === 7) { + return rgba; + } + if (rgba.length !== 9) { + throw new Error(`Invalid rgba value: "${rgba}}"`); + } + + return "#" + rgba.substr(7, 2) + rgba.substr(1, 6); +}; + const updateUiCustomization = (data) => { if (data.uiCustomization.isCustomizationEnabled === false) { return data; @@ -66,8 +78,13 @@ const updateUiCustomization = (data) => { backgroundColor, backgroundUrl, + tipBoxAndIdColor, + hasMainBoxColor, + mainBoxColor, + hasLogo, logoUrl, + logoSize, } = data.uiCustomization; const ui = {}; @@ -87,7 +104,7 @@ const updateUiCustomization = (data) => { if (hasBackground === false) { ui.backgroundType = "default"; - } else if (backgroundUrl !== "") { + } else if (backgroundUrl) { ui.backgroundType = "image"; ui.backgroundColorOrUrl = backgroundUrl; } else if (backgroundColor !== "") { @@ -97,11 +114,21 @@ const updateUiCustomization = (data) => { ui.backgroundType = "default"; } + if (tipBoxAndIdColor !== DEFAULT_UI_CUSTOMIZATION.tipBoxAndIdColor) { + ui.tipBoxAndIdColor = convertRgbaToArgb(tipBoxAndIdColor); + } + if (hasMainBoxColor === true && mainBoxColor) { + ui.mainBoxColor = convertRgbaToArgb(mainBoxColor); + } + if (hasLogo === false) { ui.logoUrl = ""; } else if (logoUrl !== "") { ui.logoUrl = logoUrl; } + if (logoSize !== DEFAULT_UI_CUSTOMIZATION.logoSize) { + ui.logoSize = logoSize; + } console.log("updateUiCustomization", ui); data.uiCustomization = JSON.stringify(ui);