From 6badd1e4bfa82a794e555355706a6d68040675ad Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:53:56 +0300 Subject: [PATCH 01/18] Fix transition issues Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../HURUmap/IndicatorTitle/Action.js | 20 ++++++++++--------- .../HURUmap/IndicatorTitle/Download.js | 8 ++++++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Action.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Action.js index a29226bd0..ba77c59f0 100644 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Action.js +++ b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Action.js @@ -79,15 +79,17 @@ function Action({ children, header, icon, title, id, ...props }) { > {({ TransitionProps }) => ( - - - - {header} - - - {children} - - +
+ + + + {header} + + + {children} + + +
)} diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js index 6523f5d37..510457da3 100644 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js +++ b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js @@ -41,8 +41,12 @@ function Download({ const [layout, setLayout] = useState(0); useEffect(() => { - const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); - setView(viewProp); + try { + const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); + setView(viewProp); + } catch (error) { + console.error("Error creating view", error); + } }, [spec]); const setImageLayout = async (e, type) => { From 73c0b69fc96f58e2b0ccd38d3b16278394f7312b Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:37:33 +0300 Subject: [PATCH 02/18] working indicator tile --- .../src/components/HURUmap/Chart/index.js | 3 +- packages/hurumap-core/package.json | 10 +- .../hurumap-core/src/IndicatorTitle/Action.js | 96 ++++ .../src/IndicatorTitle/Download.js | 426 ++++++++++++++++++ .../src/IndicatorTitle/IndicatorTitle.js | 118 +++++ .../hurumap-core/src/IndicatorTitle/Share.js | 234 ++++++++++ .../src/IndicatorTitle/ShareButton.js | 49 ++ .../hurumap-core/src/IndicatorTitle/index.js | 3 + packages/hurumap-core/src/assets/Email.svg | 1 + packages/hurumap-core/src/assets/Facebook.svg | 1 + .../hurumap-core/src/assets/Group4462.svg | 1 + .../hurumap-core/src/assets/Group5002.svg | 9 + packages/hurumap-core/src/assets/Group922.svg | 19 + packages/hurumap-core/src/assets/Group923.svg | 19 + packages/hurumap-core/src/assets/LinkedIn.svg | 1 + packages/hurumap-core/src/assets/Twitter.svg | 1 + packages/hurumap-core/src/assets/WhatsApp.svg | 1 + packages/hurumap-core/src/index.js | 1 + packages/hurumap-core/src/utils/utils.js | 8 + pnpm-lock.yaml | 233 +++++++--- turbo.json | 3 + 21 files changed, 1178 insertions(+), 59 deletions(-) create mode 100644 packages/hurumap-core/src/IndicatorTitle/Action.js create mode 100644 packages/hurumap-core/src/IndicatorTitle/Download.js create mode 100644 packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.js create mode 100644 packages/hurumap-core/src/IndicatorTitle/Share.js create mode 100644 packages/hurumap-core/src/IndicatorTitle/ShareButton.js create mode 100644 packages/hurumap-core/src/IndicatorTitle/index.js create mode 100644 packages/hurumap-core/src/assets/Email.svg create mode 100644 packages/hurumap-core/src/assets/Facebook.svg create mode 100644 packages/hurumap-core/src/assets/Group4462.svg create mode 100644 packages/hurumap-core/src/assets/Group5002.svg create mode 100644 packages/hurumap-core/src/assets/Group922.svg create mode 100644 packages/hurumap-core/src/assets/Group923.svg create mode 100644 packages/hurumap-core/src/assets/LinkedIn.svg create mode 100644 packages/hurumap-core/src/assets/Twitter.svg create mode 100644 packages/hurumap-core/src/assets/WhatsApp.svg create mode 100644 packages/hurumap-core/src/utils/utils.js diff --git a/apps/pesayetu/src/components/HURUmap/Chart/index.js b/apps/pesayetu/src/components/HURUmap/Chart/index.js index 903460bba..c733c333e 100644 --- a/apps/pesayetu/src/components/HURUmap/Chart/index.js +++ b/apps/pesayetu/src/components/HURUmap/Chart/index.js @@ -1,3 +1,4 @@ +import { IndicatorTitle } from "@hurumap/core"; import { Source } from "@hurumap/next"; import { useMediaQuery } from "@mui/material"; import { ThemeProvider, StyledEngineProvider } from "@mui/material/styles"; @@ -12,7 +13,7 @@ import Filters from "./Filters"; import { calculateTooltipPosition, idify } from "./utils"; import ChartTooltip from "@/pesayetu/components/HURUmap/ChartTooltip"; -import IndicatorTitle from "@/pesayetu/components/HURUmap/IndicatorTitle"; +// import IndicatorTitle from "@/pesayetu/components/HURUmap/IndicatorTitle"; import theme from "@/pesayetu/theme"; const useStyles = makeStyles(() => ({ diff --git a/packages/hurumap-core/package.json b/packages/hurumap-core/package.json index 2ff1cc6db..1d047103e 100644 --- a/packages/hurumap-core/package.json +++ b/packages/hurumap-core/package.json @@ -67,6 +67,14 @@ "react-leaflet": "^4.2.1" }, "dependencies": { - "prop-types": "^15.8.1" + "@commons-ui/core": "workspace:*", + "@mui/icons-material": "^5.16.1", + "clsx": "^2.1.1", + "papaparse": "^5.4.1", + "prop-types": "^15.8.1", + "react-copy-to-clipboard": "^5.1.0", + "react-share": "^5.1.0", + "vega": "^5.30.0", + "xlsx": "^0.18.5" } } diff --git a/packages/hurumap-core/src/IndicatorTitle/Action.js b/packages/hurumap-core/src/IndicatorTitle/Action.js new file mode 100644 index 000000000..0ee856137 --- /dev/null +++ b/packages/hurumap-core/src/IndicatorTitle/Action.js @@ -0,0 +1,96 @@ +import CloseIcon from "@mui/icons-material/Close"; +import { + Popper, + Fade, + Paper, + ButtonBase, + Typography, + IconButton, + ClickAwayListener, + Tooltip, + Box, +} from "@mui/material"; +import React, { useState } from "react"; + +function Action({ children, header, icon, title, id, ...props }) { + const [anchorEl, setAnchorEl] = useState(null); + + const handleClick = (event) => { + setAnchorEl(anchorEl ? null : event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + return ( + + + + {icon} + + + ({ + zIndex: theme.zIndex.drawer, + })} + > + {({ TransitionProps }) => ( + +
+ + ({ + background: theme.palette.background.default, + border: `1px solid ${theme.palette.grey.light}`, + width: theme.typography.pxToRem(180), + boxShadow: "0px 3px 6px #00000029", + borderRadius: 0, + marginTop: theme.typography.pxToRem(-40), + })} + > + ({ + background: theme.palette.background.paper, + height: theme.typography.pxToRem(36), + display: "flex", + justifyContent: "space-between", + alignItems: "center", + width: "100%", + paddingLeft: theme.typography.pxToRem(16), + paddingRight: theme.typography.pxToRem(10), + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + > + {header} + + + + {children} + + +
+
+ )} +
+
+ ); +} + +export default Action; diff --git a/packages/hurumap-core/src/IndicatorTitle/Download.js b/packages/hurumap-core/src/IndicatorTitle/Download.js new file mode 100644 index 000000000..0c6fcc492 --- /dev/null +++ b/packages/hurumap-core/src/IndicatorTitle/Download.js @@ -0,0 +1,426 @@ +import { ButtonBase, IconButton, Grid, Typography } from "@mui/material"; +import { useTheme } from "@mui/material/styles"; +// import Image from "next/image"; +import Papa from "papaparse"; +import React, { useState, useEffect } from "react"; +import * as vega from "vega"; +import * as XLSX from "xlsx"; + +import cfalogo from "@/hurumap/core/assets/Group4462.svg"; +import projectlogo from "@/hurumap/core/assets/Group5002.svg"; +import Layout1 from "@/hurumap/core/assets/Group922.svg"; +import Layout2 from "@/hurumap/core/assets/Group923.svg"; +import { idify } from "@/hurumap/core/utils/utils"; +// import config, { hurumapArgs } from "@/pesayetu/config"; + +function Download({ + title, + chartValue, + handleChartValueChange, + disableToggle, + spec, + source, + height, + data, + currentFilters, + profileNames, + isCompare, + ...props +}) { + // const classes = useStyles(props); + const [view, setView] = useState(null); + const { palette } = useTheme(); + + // const { + // indicatorTitle: { + // download: { values, layouts, imageTypes, fileTypes }, + // }, + // } = hurumapArgs; + const values = ["Percentage", "Value"]; + const layouts = [Layout1, Layout2]; + const imageTypes = ["PNG", "SVG"]; + const fileTypes = ["CSV", "XLSX", "JSON"]; + const [layout, setLayout] = useState(0); + + useEffect(() => { + try { + const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); + setView(viewProp); + } catch (error) { + console.error("Error creating view", error); + } + }, [spec]); + + const setImageLayout = async (e, type) => { + e.preventDefault(); + e.stopPropagation(); + setLayout(type); + }; + + const splitString = (str) => { + // eslint-disable-next-line prefer-regex-literals + const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); + const chunks = str.match(regex); + return chunks; + }; + + currentFilters?.forEach(({ name, value }) => { + const filterName = idify(name); + view?.signal(`${filterName}Filter`, true); + view?.signal(`${filterName}FilterValue`, value); + }); + + const chartTitle = splitString(title)?.slice(0, 3); + const subtitle = currentFilters?.reduce((acc, cur) => { + return `${acc}${cur.name}: ${cur.value},`; + }, ""); + const secondaryName = isCompare + ? ` vs ${profileNames?.secondary?.split("-")[0]}` + : ""; + const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; + + const handleImageDownload = async (e, type) => { + e.preventDefault(); + e.stopPropagation(); + + const totalHeight = height + 300; // chartHeight + extra space for legends, logo + title; + view?.signal("totalHeight", totalHeight); + view?.signal("chartTitle", chartTitle); + view?.signal("chartSubtitle", chartSubtitle.toUpperCase()); + view?.signal("chartSource", source ? `Source: ${source}` : ""); + view?.signal("projectLogoUrl", projectlogo); + view?.signal("logoWidth", 60); + view?.signal("logoUrl", cfalogo); + view?.signal("background", palette.common.white); + + if (layout === 0) { + view?.signal("titleY", 20); + view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); + view?.signal("chartY", 50); + view?.signal("titleGroupY", 0); + view?.signal("sourceGroupY", totalHeight - 80); + view?.signal("sourceGroupH", 60); + view?.signal("sourceY", 30); + } else { + view?.signal("titleY", 25); + view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); + view?.signal("chartY", 60); + view?.signal( + "titleGroupY", + totalHeight - 80 + (chartTitle.length - 1) * 15, + ); + view?.signal("sourceGroupY", 1); + view?.signal("sourceGroupH", 60); + view?.signal("sourceY", 30); + } + await view?.runAsync(); + + const imgType = type.toLowerCase(); + // const url = await view.toImageURL(imgType, config.images.scaleFactor); + const url = await view.toImageURL(imgType, 2); + + /* eslint-env browser */ + const link = document.createElement("a"); + link.download = `${title}.${imgType}`; + link.href = url; + /* eslint-env browser */ + document.body.appendChild(link); + link.click(); + /* eslint-env browser */ + document.body.removeChild(link); + }; + + const handleDataDownload = async (e, type) => { + e.preventDefault(); + e.stopPropagation(); + + const fileType = type.toLowerCase(); + const fileName = `${title}.${fileType}`; + let href; + + if (fileType === "json") { + href = `data:text/json;charset=utf-8,${encodeURIComponent( + JSON.stringify(data), + )}`; + } else if (fileType === "csv") { + href = `data:text/csv;charset=utf-8,${Papa.unparse(data)}`; + } else { + const table = XLSX.utils.json_to_sheet(data); + const wb = XLSX.utils.book_new(); // make Workbook of Excel + // add Worksheet to Workbook + XLSX.utils.book_append_sheet(wb, table, title); + // export Excel file + XLSX.writeFile(wb, fileName); + return; + } + /* eslint-env browser */ + const link = document.createElement("a"); + link.href = href; + link.download = fileName; + /* eslint-env browser */ + document.body.appendChild(link); + link.click(); + link.remove(); + }; + + return ( + + {!disableToggle && ( + <> + ({ + height: theme.typography.pxToRem(36), + })} + > + {values.map((v) => ( + ({ + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRight: `1px solid ${theme.palette.background.paper}`, + "&:last-of-type": { + borderRight: 0, + }, + "&:hover": { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }, + ...(chartValue === v && { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }), + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + onClick={() => handleChartValueChange(v)} + > + {v} + + + ))} + + ({ + height: theme.typography.pxToRem(36), + background: theme.palette.background.paper, + display: "flex", + alignItems: "center", + paddingLeft: theme.typography.pxToRem(16), + justifyContent: "space-between", + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + > + Download chart as: + + + + )} + ({ + height: theme.typography.pxToRem(36), + })} + > + {imageTypes.map((p) => ( + ({ + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRight: `1px solid ${theme.palette.background.paper}`, + "&:last-of-type": { + borderRight: 0, + }, + "&:hover": { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }, + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + })} + onClick={(e) => handleImageDownload(e, p)} + > + {p} + + + ))} + + ({ + height: theme.typography.pxToRem(36), + display: "flex", + alignItems: "center", + paddingLeft: theme.typography.pxToRem(16), + border: `1px solid ${theme.palette.grey.light}`, + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + > + Layout option: + + + ({ + height: theme.typography.pxToRem(36), + })} + > + {layouts.map((p, index) => ( + ({ + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRight: `1px solid ${theme.palette.background.paper}`, + "&:last-of-type": { + borderRight: 0, + }, + "&:hover": { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }, + ...(layout === index && { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }), + })} + > + { + setImageLayout(e, index); + }} + size="large" + > + layout + + + ))} + + ({ + height: theme.typography.pxToRem(36), + background: theme.palette.background.paper, + display: "flex", + alignItems: "center", + paddingLeft: theme.typography.pxToRem(16), + justifyContent: "space-between", + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + > + Download data as: + + + ({ + height: theme.typography.pxToRem(36), + })} + > + {fileTypes.map((f) => ( + ({ + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRight: `1px solid ${theme.palette.background.paper}`, + "&:last-of-type": { + borderRight: 0, + }, + "&:hover": { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }, + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + onClick={(e) => handleDataDownload(e, f)} + > + {f} + + + ))} + + + ); +} + +export default Download; diff --git a/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.js b/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.js new file mode 100644 index 000000000..1f57c3302 --- /dev/null +++ b/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.js @@ -0,0 +1,118 @@ +import { RichTypography } from "@commons-ui/core"; +import DownloadIcon from "@mui/icons-material/Download"; +import InfoIcon from "@mui/icons-material/Info"; +import ShareIcon from "@mui/icons-material/Share"; +import { Box, Grid } from "@mui/material"; +import React from "react"; + +import Action from "./Action"; +import Download from "./Download"; +import Share from "./Share"; + +const IndicatorTitle = React.forwardRef(function IndicatorTitle( + { children, description, disableToggle, title, view, ...props }, + ref, +) { + const actions = [ + description && { + id: "act-description", + title: "Description", + header: "Learn More", + children: ( + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + padding: `${theme.typography.pxToRem(18)} ${theme.typography.pxToRem( + 20, + )} ${theme.typography.pxToRem(31)} ${theme.typography.pxToRem(16)}`, + "& > p > span": { + display: "inline-block", + }, + })} + > + {description} + + ), + icon: , + }, + { + id: "act-download", + title: "Download", + header: disableToggle ? "Download chart as" : "Chart value as:", + children: ( + + ), + icon: , + }, + { + id: "act-share", + title: "Share", + header: "Share chart via:", + children: , + icon: , + }, + ]; + + return ( + ({ + paddingTop: theme.typography.pxToRem(24), + paddingBottom: theme.typography.pxToRem(25), + ...props.sx, + })} + ref={ref} + > + + + {children || title} + + ({ + justifyContent: "flex-start", + marginTop: theme.typography.pxToRem(20), + marginBottom: theme.typography.pxToRem(20), + [theme.breakpoints.up("md")]: { + justifyContent: "flex-end", + margin: 0, + }, + })} + > + {actions + .filter((a) => a?.id) + .map((act) => ( + ({ + marginRight: theme.typography.pxToRem(14), + "&:last-of-type": { + marginRight: 0, + }, + })} + > + + + ))} + + + + ); +}); + +export default IndicatorTitle; diff --git a/packages/hurumap-core/src/IndicatorTitle/Share.js b/packages/hurumap-core/src/IndicatorTitle/Share.js new file mode 100644 index 000000000..eb84e3604 --- /dev/null +++ b/packages/hurumap-core/src/IndicatorTitle/Share.js @@ -0,0 +1,234 @@ +import ContentCopyIcon from "@mui/icons-material/ContentCopy"; +import { Grid, TextField, Typography, SvgIcon, Box } from "@mui/material"; +// import clsx from "clsx"; +// import PropTypes from "prop-types"; +import React, { useState, useEffect } from "react"; +import { CopyToClipboard } from "react-copy-to-clipboard"; + +import ShareButton from "./ShareButton"; +// import useStyles from "./useStyles"; + +// import { ReactComponent as CopyIcon } from "@/pesayetu/assets/icons/Group 5062.svg"; +// import site from "@/pesayetu/utils/site"; + +function Share({ + title, + chartType, + geoCode, + indicatorId, + isCompare, + ...props +}) { + // const classes = useStyles(props); + const [copied, setCopied] = useState(false); + + const handleOnCopy = () => { + setCopied((prev) => !prev); + }; + + useEffect(() => { + let timer; + if (copied) { + timer = setTimeout(() => { + setCopied(false); + }, 3000); + } + return () => timer && clearTimeout(timer); + }, [copied]); + + // Embed url + const url = new URL( + `/embed/${geoCode.toLowerCase()}/${indicatorId}`, + process.env.NEXT_PUBLIC_APP_URL, + ).toString(); + + const shareData = [ + { name: "Facebook", props: { quote: title, hashtag: "#PesaYetu" } }, + { + name: "Twitter", + props: { title, via: "Code4Africa", related: ["Code4Africa"] }, + }, + { + name: "LinkedIn", + props: { + summary: title, + source: process.env.NEXT_PUBLIC_APP_URL, + }, + }, + { name: "WhatsApp", props: { quote: title } }, + { name: "Email", props: { subject: title } }, + { name: "CopyUrl" }, + ]; + + const className = `wrapper-${geoCode}-${indicatorId}`; + + const code = `
+ +
+ `; + + return ( + + {shareData.map((social) => ( + + {social.name === "CopyUrl" ? ( + ({ + backgroundColor: `${theme.palette.background.default} !important`, + filter: "opacity(0.6)", + width: "100%", + border: `solid 1px ${theme.palette.background.paper} !important`, + paddingTop: `${theme.typography.pxToRem(5)} !important`, + "&:hover": { + border: "solid 1px #666666 !important", + backgroundColor: `${theme.palette.grey.light} !important`, + }, + })} + > + + ({ + marginLeft: theme.typography.pxToRem(16), + })} + /> + + + ) : ( + + )} + + ))} + + {copied ? ( + ({ + height: theme.typography.pxToRem(36), + display: "flex", + alignItems: "center", + paddingLeft: theme.typography.pxToRem(16), + border: `1px solid ${theme.palette.grey.light}`, + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + > + Copied! + + + ) : null} + + ({ + height: theme.typography.pxToRem(36), + display: "flex", + alignItems: "center", + paddingLeft: theme.typography.pxToRem(16), + border: `1px solid ${theme.palette.grey.light}`, + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + > + Embed on your website: + + + ({ + height: theme.typography.pxToRem(36), + display: "flex", + alignItems: "center", + paddingLeft: theme.typography.pxToRem(16), + border: `1px solid ${theme.palette.grey.light}`, + })} + > + ({ + "& .MuiInputBase-input": { + background: theme.palette.background.paper, + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + }, + })} + /> + + + ); +} + +export default Share; diff --git a/packages/hurumap-core/src/IndicatorTitle/ShareButton.js b/packages/hurumap-core/src/IndicatorTitle/ShareButton.js new file mode 100644 index 000000000..f96ef19e5 --- /dev/null +++ b/packages/hurumap-core/src/IndicatorTitle/ShareButton.js @@ -0,0 +1,49 @@ +import React from "react"; +import { + TwitterShareButton, + LinkedinShareButton, + FacebookShareButton, + EmailShareButton, + WhatsappShareButton, +} from "react-share"; + +import { ReactComponent as EmailIcon } from "@/hurumap/core/assets/Email.svg"; +import { ReactComponent as FacebookIcon } from "@/hurumap/core/assets/Facebook.svg"; +import { ReactComponent as LinkedInIcon } from "@/hurumap/core/assets/LinkedIn.svg"; +import { ReactComponent as TwitterIcon } from "@/hurumap/core/assets/Twitter.svg"; +import { ReactComponent as WhatsAppIcon } from "@/hurumap/core/assets/WhatsApp.svg"; + +const componentMap = { + Facebook: { icon: FacebookIcon, button: FacebookShareButton }, + Twitter: { icon: TwitterIcon, button: TwitterShareButton }, + LinkedIn: { icon: LinkedInIcon, button: LinkedinShareButton }, + WhatsApp: { icon: WhatsAppIcon, button: WhatsappShareButton }, + Email: { icon: EmailIcon, button: EmailShareButton }, +}; + +function ShareButton({ name, url, ...props }) { + const SocialButtonComponent = componentMap[name].button; + const SocialIcon = componentMap[name].icon; + + return ( + ({ + backgroundColor: `${theme.palette.background.default} !important`, + filter: "opacity(0.6)", + width: "100%", + border: `solid 1px ${theme.palette.background.paper} !important`, + paddingTop: `${theme.typography.pxToRem(5)} !important`, + "&:hover": { + border: "solid 1px #666666 !important", + backgroundColor: `${theme.palette.grey.light} !important`, + }, + })} + > + + + ); +} + +export default ShareButton; diff --git a/packages/hurumap-core/src/IndicatorTitle/index.js b/packages/hurumap-core/src/IndicatorTitle/index.js new file mode 100644 index 000000000..394f337ec --- /dev/null +++ b/packages/hurumap-core/src/IndicatorTitle/index.js @@ -0,0 +1,3 @@ +import IndicatorTitle from "./IndicatorTitle"; + +export default IndicatorTitle; diff --git a/packages/hurumap-core/src/assets/Email.svg b/packages/hurumap-core/src/assets/Email.svg new file mode 100644 index 000000000..3e44b8779 --- /dev/null +++ b/packages/hurumap-core/src/assets/Email.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/Facebook.svg b/packages/hurumap-core/src/assets/Facebook.svg new file mode 100644 index 000000000..56c40db42 --- /dev/null +++ b/packages/hurumap-core/src/assets/Facebook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/Group4462.svg b/packages/hurumap-core/src/assets/Group4462.svg new file mode 100644 index 000000000..277cf32a8 --- /dev/null +++ b/packages/hurumap-core/src/assets/Group4462.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/Group5002.svg b/packages/hurumap-core/src/assets/Group5002.svg new file mode 100644 index 000000000..511d34de6 --- /dev/null +++ b/packages/hurumap-core/src/assets/Group5002.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/hurumap-core/src/assets/Group922.svg b/packages/hurumap-core/src/assets/Group922.svg new file mode 100644 index 000000000..d5d131c3b --- /dev/null +++ b/packages/hurumap-core/src/assets/Group922.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/packages/hurumap-core/src/assets/Group923.svg b/packages/hurumap-core/src/assets/Group923.svg new file mode 100644 index 000000000..82ecb1b26 --- /dev/null +++ b/packages/hurumap-core/src/assets/Group923.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/packages/hurumap-core/src/assets/LinkedIn.svg b/packages/hurumap-core/src/assets/LinkedIn.svg new file mode 100644 index 000000000..744718823 --- /dev/null +++ b/packages/hurumap-core/src/assets/LinkedIn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/Twitter.svg b/packages/hurumap-core/src/assets/Twitter.svg new file mode 100644 index 000000000..ebef26dec --- /dev/null +++ b/packages/hurumap-core/src/assets/Twitter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/WhatsApp.svg b/packages/hurumap-core/src/assets/WhatsApp.svg new file mode 100644 index 000000000..85385c727 --- /dev/null +++ b/packages/hurumap-core/src/assets/WhatsApp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/hurumap-core/src/index.js b/packages/hurumap-core/src/index.js index 3149c42c1..abc8ef5f0 100644 --- a/packages/hurumap-core/src/index.js +++ b/packages/hurumap-core/src/index.js @@ -2,3 +2,4 @@ export { default as LocationTag } from "./LocationTag"; export { default as LocationHighlight } from "./LocationHighlight"; export { default as Location } from "./Location"; +export { default as IndicatorTitle } from "./IndicatorTitle"; diff --git a/packages/hurumap-core/src/utils/utils.js b/packages/hurumap-core/src/utils/utils.js new file mode 100644 index 000000000..be0107532 --- /dev/null +++ b/packages/hurumap-core/src/utils/utils.js @@ -0,0 +1,8 @@ +/* eslint-disable import/prefer-default-export */ +export function idify(string) { + return string + .replace(/^\s+|\s+$/g, "") + .replace(/[^a-z0-9]/g, "") + .replace(/\s+/g, "_") + .replace(/_+/g, "_"); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 44abde036..5f4f5ff85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -486,7 +486,7 @@ importers: version: 3.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-config-commons-ui: specifier: workspace:* version: link:../../packages/jest-config-commons-ui @@ -854,7 +854,7 @@ importers: version: 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@storybook/addon-interactions': specifier: ^8.2.2 - version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) + version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@storybook/addon-links': specifier: ^8.2.2 version: 8.2.2(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) @@ -866,13 +866,13 @@ importers: version: 8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)) '@storybook/nextjs': specifier: ^8.2.2 - version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(babel-plugin-macros@3.1.0)(esbuild@0.21.5)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(next@14.2.5(@babel/core@7.24.8)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(type-fest@4.21.0)(typescript@5.5.3)(webpack-hot-middleware@2.26.1)(webpack@5.93.0(esbuild@0.21.5)) + version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(babel-plugin-macros@3.1.0)(esbuild@0.21.5)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(next@14.2.5(@babel/core@7.24.8)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(type-fest@4.21.0)(typescript@5.5.3)(webpack-hot-middleware@2.26.1)(webpack@5.93.0(esbuild@0.21.5)) '@storybook/react': specifier: ^8.2.2 version: 8.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(typescript@5.5.3) '@storybook/test': specifier: ^8.2.2 - version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) + version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@svgr/webpack': specifier: ^8.1.0 version: 8.1.0(typescript@5.5.3) @@ -929,7 +929,7 @@ importers: version: 3.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-config-commons-ui: specifier: workspace:* version: link:../../packages/jest-config-commons-ui @@ -1010,7 +1010,7 @@ importers: version: 5.0.0-alpha.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(formik@2.4.6(react@18.3.1))(react@18.3.1)(tiny-warning@1.0.3) formik-mui-lab: specifier: ^1.0.0 - version: 1.0.0(uwokqjev6b7ignvfnuri4yvwiy) + version: 1.0.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/lab@5.0.0-alpha.155(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.16.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(formik@2.4.6(react@18.3.1))(react@18.3.1)(tiny-warning@1.0.3) jwt-decode: specifier: ^4.0.0 version: 4.0.0 @@ -1101,7 +1101,7 @@ importers: version: 3.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-config-commons-ui: specifier: workspace:* version: link:../../packages/jest-config-commons-ui @@ -1543,7 +1543,7 @@ importers: version: 3.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + version: 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) jest-config-commons-ui: specifier: workspace:* version: link:../jest-config-commons-ui @@ -1601,7 +1601,7 @@ importers: version: link:../eslint-config-commons-ui jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + version: 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) jest-config-commons-ui: specifier: workspace:* version: link:../jest-config-commons-ui @@ -1631,7 +1631,7 @@ importers: dependencies: '@testing-library/jest-dom': specifier: ^6.4.6 - version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(babel-plugin-macros@3.1.0)) + version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3))) '@testing-library/react': specifier: ^14.3.1 version: 14.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1671,7 +1671,7 @@ importers: version: 3.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + version: 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) jest-config-commons-ui: specifier: workspace:* version: link:../jest-config-commons-ui @@ -1769,9 +1769,33 @@ importers: packages/hurumap-core: dependencies: + '@commons-ui/core': + specifier: workspace:* + version: link:../commons-ui-core + '@mui/icons-material': + specifier: ^5.16.1 + version: 5.16.1(@mui/material@5.16.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + clsx: + specifier: ^2.1.1 + version: 2.1.1 + papaparse: + specifier: ^5.4.1 + version: 5.4.1 prop-types: specifier: ^15.8.1 version: 15.8.1 + react-copy-to-clipboard: + specifier: ^5.1.0 + version: 5.1.0(react@18.3.1) + react-share: + specifier: ^5.1.0 + version: 5.1.0(react@18.3.1) + vega: + specifier: ^5.30.0 + version: 5.30.0(encoding@0.1.13) + xlsx: + specifier: ^0.18.5 + version: 0.18.5 devDependencies: '@babel/core': specifier: ^7.24.8 @@ -1811,7 +1835,7 @@ importers: version: 3.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + version: 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) jest-config-commons-ui: specifier: workspace:* version: link:../jest-config-commons-ui @@ -1875,7 +1899,7 @@ importers: version: link:../eslint-config-commons-ui jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + version: 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) jest-config-commons-ui: specifier: workspace:* version: link:../jest-config-commons-ui @@ -1927,7 +1951,7 @@ importers: version: 3.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + version: 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) prettier: specifier: ^3.3.2 version: 3.3.2 @@ -16208,7 +16232,42 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) + jest-config: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.7 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3))': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.14.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -18560,11 +18619,11 @@ snapshots: '@storybook/global': 5.0.0 storybook: 8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)) - '@storybook/addon-interactions@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))': + '@storybook/addon-interactions@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))': dependencies: '@storybook/global': 5.0.0 '@storybook/instrumenter': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) - '@storybook/test': 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) + '@storybook/test': 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) polished: 4.3.1 storybook: 8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)) ts-dedent: 2.2.0 @@ -19030,7 +19089,7 @@ snapshots: '@storybook/mdx2-csf@1.1.0': {} - '@storybook/nextjs@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(babel-plugin-macros@3.1.0)(esbuild@0.21.5)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(next@14.2.5(@babel/core@7.24.8)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(type-fest@4.21.0)(typescript@5.5.3)(webpack-hot-middleware@2.26.1)(webpack@5.93.0(esbuild@0.21.5))': + '@storybook/nextjs@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(babel-plugin-macros@3.1.0)(esbuild@0.21.5)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(next@14.2.5(@babel/core@7.24.8)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(type-fest@4.21.0)(typescript@5.5.3)(webpack-hot-middleware@2.26.1)(webpack@5.93.0(esbuild@0.21.5))': dependencies: '@babel/core': 7.24.8 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.8) @@ -19049,7 +19108,7 @@ snapshots: '@storybook/builder-webpack5': 8.2.2(esbuild@0.21.5)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(typescript@5.5.3) '@storybook/preset-react-webpack': 8.2.2(esbuild@0.21.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(typescript@5.5.3) '@storybook/react': 8.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(typescript@5.5.3) - '@storybook/test': 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) + '@storybook/test': 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@types/node': 18.19.39 '@types/semver': 7.5.8 babel-loader: 9.1.3(@babel/core@7.24.8)(webpack@5.93.0(esbuild@0.21.5)) @@ -19375,12 +19434,12 @@ snapshots: memoizerific: 1.11.3 qs: 6.12.3 - '@storybook/test@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))': + '@storybook/test@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))': dependencies: '@storybook/csf': 0.1.11 '@storybook/instrumenter': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@testing-library/dom': 10.1.0 - '@testing-library/jest-dom': 6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)) + '@testing-library/jest-dom': 6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))) '@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0) '@vitest/expect': 1.6.0 '@vitest/spy': 1.6.0 @@ -19670,7 +19729,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))': + '@testing-library/jest-dom@6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.8 @@ -19683,7 +19742,7 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 '@types/jest': 29.5.12 - jest: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + jest: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) '@testing-library/jest-dom@6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10))': dependencies: @@ -19700,7 +19759,7 @@ snapshots: '@types/jest': 29.5.12 jest: 29.7.0(@types/node@20.14.10) - '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(babel-plugin-macros@3.1.0))': + '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.8 @@ -19713,7 +19772,7 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 '@types/jest': 29.5.12 - jest: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + jest: 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) '@testing-library/react@14.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: @@ -21413,7 +21472,22 @@ snapshots: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) + jest-config: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + create-jest@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -22345,7 +22419,7 @@ snapshots: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) eslint-plugin-react: 7.34.3(eslint@8.57.0) @@ -22403,12 +22477,12 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0): dependencies: debug: 4.3.5 enhanced-resolve: 5.17.0 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 @@ -22504,14 +22578,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -22562,7 +22636,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.14.0 is-glob: 4.0.3 @@ -22617,7 +22691,7 @@ snapshots: '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 optionalDependencies: - jest: 29.7.0(@types/node@20.14.10) + jest: 29.7.0 transitivePeerDependencies: - supports-color - typescript @@ -23204,8 +23278,8 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - formik-mui-lab@1.0.0(uwokqjev6b7ignvfnuri4yvwiy): - dependencies: + ? formik-mui-lab@1.0.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/lab@5.0.0-alpha.155(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.16.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(formik@2.4.6(react@18.3.1))(react@18.3.1)(tiny-warning@1.0.3) + : dependencies: '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/lab': 5.0.0-alpha.155(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -24296,6 +24370,26 @@ snapshots: - babel-plugin-macros - supports-color + jest-cli@29.7.0: + dependencies: + '@jest/core': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@20.14.10) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@20.14.10) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + optional: true + jest-cli@29.7.0(@types/node@20.14.10): dependencies: '@jest/core': 29.7.0 @@ -24344,7 +24438,26 @@ snapshots: create-jest: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) + jest-config: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3)) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-cli@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)): + dependencies: + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -24416,7 +24529,7 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)): + jest-config@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)): dependencies: '@babel/core': 7.24.8 '@jest/test-sequencer': 29.7.0 @@ -24442,7 +24555,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 20.14.10 - ts-node: 10.9.2(@types/node@20.14.10)(typescript@5.5.3) + ts-node: 10.9.2(@swc/core@1.6.13(@swc/helpers@0.5.5))(@types/node@20.14.10)(typescript@5.5.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -24683,6 +24796,19 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 + jest@29.7.0: + dependencies: + '@jest/core': 29.7.0 + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + optional: true + jest@29.7.0(@types/node@20.14.10): dependencies: '@jest/core': 29.7.0 @@ -24720,6 +24846,18 @@ snapshots: - supports-color - ts-node + jest@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)): + dependencies: + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(typescript@5.5.3)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + jiti@1.21.6: {} jmespath@0.16.0: {} @@ -28523,25 +28661,6 @@ snapshots: optionalDependencies: '@swc/core': 1.6.13(@swc/helpers@0.5.5) - ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 20.14.10 - acorn: 8.12.1 - acorn-walk: 8.3.3 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.5.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - optional: true - ts-pnp@1.2.0(typescript@5.5.3): optionalDependencies: typescript: 5.5.3 diff --git a/turbo.json b/turbo.json index 1c27211fe..470becb53 100644 --- a/turbo.json +++ b/turbo.json @@ -53,6 +53,9 @@ "SOURCE_LIB" ] }, + "@hurumap/core": { + "env": ["NEXT_PUBLIC_APP_URL"] + }, "jest": { "inputs": ["src/**/*.js"] }, From bc2e2fc9de8a82217abfab894e175fe238ede8e1 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Tue, 30 Jul 2024 12:15:09 +0300 Subject: [PATCH 03/18] Add download utils Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../HURUmap/IndicatorTitle/Download.js | 34 +++++----------- .../HURUmap/IndicatorTitle/utils.js | 39 +++++++++++++++++++ 2 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js index 6523f5d37..72312bd71 100644 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js +++ b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js @@ -2,13 +2,12 @@ import { ButtonBase, IconButton, Grid, Typography } from "@mui/material"; import { useTheme } from "@mui/material/styles"; import clsx from "clsx"; import Image from "next/image"; -import Papa from "papaparse"; import PropTypes from "prop-types"; import React, { useState, useEffect } from "react"; import * as vega from "vega"; -import * as XLSX from "xlsx"; import useStyles from "./useStyles"; +import { downloadSheetData, downloadJson } from "./utils"; import cfalogo from "@/pesayetu/assets/logos/Group4462.svg"; import projectlogo from "@/pesayetu/assets/logos/Group5002.svg"; @@ -41,8 +40,12 @@ function Download({ const [layout, setLayout] = useState(0); useEffect(() => { - const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); - setView(viewProp); + try { + const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); + setView(viewProp); + } catch (e) { + console.error(e); + } }, [spec]); const setImageLayout = async (e, type) => { @@ -128,31 +131,12 @@ function Download({ const fileType = type.toLowerCase(); const fileName = `${title}.${fileType}`; - let href; if (fileType === "json") { - href = `data:text/json;charset=utf-8,${encodeURIComponent( - JSON.stringify(data), - )}`; - } else if (fileType === "csv") { - href = `data:text/csv;charset=utf-8,${Papa.unparse(data)}`; + downloadJson(data, fileName); } else { - const table = XLSX.utils.json_to_sheet(data); - const wb = XLSX.utils.book_new(); // make Workbook of Excel - // add Worksheet to Workbook - XLSX.utils.book_append_sheet(wb, table, title); - // export Excel file - XLSX.writeFile(wb, fileName); - return; + downloadSheetData(data, fileType, fileName, title); } - /* eslint-env browser */ - const link = document.createElement("a"); - link.href = href; - link.download = fileName; - /* eslint-env browser */ - document.body.appendChild(link); - link.click(); - link.remove(); }; return ( diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js new file mode 100644 index 000000000..570734ab5 --- /dev/null +++ b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js @@ -0,0 +1,39 @@ +import Papa from "papaparse"; +import * as XLSX from "xlsx"; + +export function downloadSheetData(data, type, filename, title) { + if (type === "csv") { + const href = `data:text/csv;charset=utf-8,${Papa.unparse(data)}`; + const link = document.createElement("a"); + link.href = href; + link.download = filename; + /* eslint-env browser */ + document.body.appendChild(link); + link.click(); + link.remove(); + } else { + const table = XLSX.utils.json_to_sheet(data); + const wb = XLSX.utils.book_new(); + // Excel limit sheet title to 31 characters + const maxTitleLength = 31; + const truncatedTitle = + title.length > maxTitleLength + ? title.substring(0, maxTitleLength) + : title; + XLSX.utils.book_append_sheet(wb, table, truncatedTitle); + XLSX.writeFile(wb, filename); + } +} + +export function downloadJson(data, filename) { + const href = `data:text/json;charset=utf-8,${encodeURIComponent( + JSON.stringify(data), + )}`; + const link = document.createElement("a"); + link.href = href; + link.download = filename; + /* eslint-env browser */ + document.body.appendChild(link); + link.click(); + link.remove(); +} From c74bdb684c46efa381f025bb877e0a05ce651d76 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:00:01 +0300 Subject: [PATCH 04/18] download image utils Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../components/HURUmap/IndicatorTitle/Download.js | 12 ++---------- .../src/components/HURUmap/IndicatorTitle/utils.js | 11 +++++++++++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js index 72312bd71..437f4663a 100644 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js +++ b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js @@ -7,7 +7,7 @@ import React, { useState, useEffect } from "react"; import * as vega from "vega"; import useStyles from "./useStyles"; -import { downloadSheetData, downloadJson } from "./utils"; +import { downloadSheetData, downloadJson, downloadImage } from "./utils"; import cfalogo from "@/pesayetu/assets/logos/Group4462.svg"; import projectlogo from "@/pesayetu/assets/logos/Group5002.svg"; @@ -114,15 +114,7 @@ function Download({ const imgType = type.toLowerCase(); const url = await view.toImageURL(imgType, config.images.scaleFactor); - /* eslint-env browser */ - const link = document.createElement("a"); - link.download = `${title}.${imgType}`; - link.href = url; - /* eslint-env browser */ - document.body.appendChild(link); - link.click(); - /* eslint-env browser */ - document.body.removeChild(link); + downloadImage(url, title, imgType); }; const handleDataDownload = async (e, type) => { diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js index 570734ab5..f9b4b3b71 100644 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js +++ b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js @@ -37,3 +37,14 @@ export function downloadJson(data, filename) { link.click(); link.remove(); } + +export function downloadImage(url, title, imgType) { + const link = document.createElement("a"); + link.download = `${title}.${imgType}`; + link.href = url; + /* eslint-env browser */ + document.body.appendChild(link); + link.click(); + /* eslint-env browser */ + document.body.removeChild(link); +} From 0531247435866d118b8d36452989de7a11f4f913 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:28:58 +0300 Subject: [PATCH 05/18] create image util --- .../HURUmap/IndicatorTitle/Download.js | 53 +++++++----------- .../HURUmap/IndicatorTitle/utils.js | 54 +++++++++++++++++++ 2 files changed, 74 insertions(+), 33 deletions(-) diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js index 437f4663a..e208a41ee 100644 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js +++ b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js @@ -7,7 +7,12 @@ import React, { useState, useEffect } from "react"; import * as vega from "vega"; import useStyles from "./useStyles"; -import { downloadSheetData, downloadJson, downloadImage } from "./utils"; +import { + downloadSheetData, + downloadJson, + downloadImage, + createImage, +} from "./utils"; import cfalogo from "@/pesayetu/assets/logos/Group4462.svg"; import projectlogo from "@/pesayetu/assets/logos/Group5002.svg"; @@ -81,39 +86,21 @@ function Download({ e.stopPropagation(); const totalHeight = height + 300; // chartHeight + extra space for legends, logo + title; - view?.signal("totalHeight", totalHeight); - view?.signal("chartTitle", chartTitle); - view?.signal("chartSubtitle", chartSubtitle.toUpperCase()); - view?.signal("chartSource", source ? `Source: ${source}` : ""); - view?.signal("projectLogoUrl", projectlogo); - view?.signal("logoWidth", 60); - view?.signal("logoUrl", cfalogo); - view?.signal("background", palette.common.white); - - if (layout === 0) { - view?.signal("titleY", 20); - view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); - view?.signal("chartY", 50); - view?.signal("titleGroupY", 0); - view?.signal("sourceGroupY", totalHeight - 80); - view?.signal("sourceGroupH", 60); - view?.signal("sourceY", 30); - } else { - view?.signal("titleY", 25); - view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); - view?.signal("chartY", 60); - view?.signal( - "titleGroupY", - totalHeight - 80 + (chartTitle.length - 1) * 15, - ); - view?.signal("sourceGroupY", 1); - view?.signal("sourceGroupH", 60); - view?.signal("sourceY", 30); - } - await view?.runAsync(); - const imgType = type.toLowerCase(); - const url = await view.toImageURL(imgType, config.images.scaleFactor); + + const url = await createImage({ + view, + totalHeight, + chartTitle, + chartSubtitle, + source, + projectlogo, + cfalogo, + backgroundColor: palette.common.white, + layout, + imgType, + scaleFactor: config.images.scaleFactor, + }); downloadImage(url, title, imgType); }; diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js index f9b4b3b71..a1f8a2f4b 100644 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js +++ b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js @@ -48,3 +48,57 @@ export function downloadImage(url, title, imgType) { /* eslint-env browser */ document.body.removeChild(link); } + +export async function createImage({ + view, + totalHeight, + chartTitle, + chartSubtitle, + source = "", + projectlogo, + cfalogo, + backgroundColor, + layout, + imgType, + scaleFactor, +}) { + if (!view) { + return null; + } + + view?.signal("totalHeight", totalHeight); + view?.signal("chartTitle", chartTitle); + view?.signal("chartSubtitle", chartSubtitle.toUpperCase()); + view?.signal("chartSource", source); + view?.signal("projectLogoUrl", projectlogo); + view?.signal("logoWidth", 60); + view?.signal("logoUrl", cfalogo); + view?.signal("background", backgroundColor); + + if (layout === 0) { + view?.signal("titleY", 20); + view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); + view?.signal("chartY", 50); + view?.signal("titleGroupY", 0); + view?.signal("sourceGroupY", totalHeight - 80); + view?.signal("sourceGroupH", 60); + view?.signal("sourceY", 30); + } else { + view?.signal("titleY", 25); + view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); + view?.signal("chartY", 60); + view?.signal( + "titleGroupY", + totalHeight - 80 + (chartTitle.length - 1) * 15, + ); + view?.signal("sourceGroupY", 1); + view?.signal("sourceGroupH", 60); + view?.signal("sourceY", 30); + } + + await view?.runAsync(); + + const url = await view.toImageURL(imgType, scaleFactor); + + return url; +} From 794b0739df2c6fd6c165aa9818c43d298e98ed56 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:08:12 +0300 Subject: [PATCH 06/18] Working download --- .../HURUmap/IndicatorTitle/Download.js | 236 ------------- .../HURUmap/IndicatorTitle/index.js | 74 +++- packages/hurumap-core/package.json | 4 +- .../hurumap-core/src/Download/Download.js | 325 ++++++++++++++++++ packages/hurumap-core/src/Download/index.js | 3 + .../hurumap-core/src/Download}/utils.js | 0 packages/hurumap-core/src/index.js | 1 + pnpm-lock.yaml | 30 +- 8 files changed, 418 insertions(+), 255 deletions(-) delete mode 100644 apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js create mode 100644 packages/hurumap-core/src/Download/Download.js create mode 100644 packages/hurumap-core/src/Download/index.js rename {apps/pesayetu/src/components/HURUmap/IndicatorTitle => packages/hurumap-core/src/Download}/utils.js (100%) diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js deleted file mode 100644 index 0359abb5c..000000000 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/Download.js +++ /dev/null @@ -1,236 +0,0 @@ -import { ButtonBase, IconButton, Grid, Typography } from "@mui/material"; -import { useTheme } from "@mui/material/styles"; -import clsx from "clsx"; -import Image from "next/image"; -import PropTypes from "prop-types"; -import React, { useState, useEffect } from "react"; -import * as vega from "vega"; - -import useStyles from "./useStyles"; -import { - downloadSheetData, - downloadJson, - downloadImage, - createImage, -} from "./utils"; - -import cfalogo from "@/pesayetu/assets/logos/Group4462.svg"; -import projectlogo from "@/pesayetu/assets/logos/Group5002.svg"; -import { idify } from "@/pesayetu/components/HURUmap/Chart/utils"; -import config, { hurumapArgs } from "@/pesayetu/config"; - -function Download({ - title, - chartValue, - handleChartValueChange, - disableToggle, - spec, - source, - height, - data, - currentFilters, - profileNames, - isCompare, - ...props -}) { - const classes = useStyles(props); - const [view, setView] = useState(null); - const { palette } = useTheme(); - - const { - indicatorTitle: { - download: { values, layouts, imageTypes, fileTypes }, - }, - } = hurumapArgs; - const [layout, setLayout] = useState(0); - - useEffect(() => { - try { - const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); - setView(viewProp); - } catch (error) { - console.error("Error creating view", error); - } - }, [spec]); - - const setImageLayout = async (e, type) => { - e.preventDefault(); - e.stopPropagation(); - setLayout(type); - }; - - const splitString = (str) => { - // eslint-disable-next-line prefer-regex-literals - const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); - const chunks = str.match(regex); - return chunks; - }; - - currentFilters?.forEach(({ name, value }) => { - const filterName = idify(name); - view?.signal(`${filterName}Filter`, true); - view?.signal(`${filterName}FilterValue`, value); - }); - - const chartTitle = splitString(title)?.slice(0, 3); - const subtitle = currentFilters?.reduce((acc, cur) => { - return `${acc}${cur.name}: ${cur.value},`; - }, ""); - const secondaryName = isCompare - ? ` vs ${profileNames?.secondary?.split("-")[0]}` - : ""; - const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; - - const handleImageDownload = async (e, type) => { - e.preventDefault(); - e.stopPropagation(); - - const totalHeight = height + 300; // chartHeight + extra space for legends, logo + title; - const imgType = type.toLowerCase(); - - const url = await createImage({ - view, - totalHeight, - chartTitle, - chartSubtitle, - source, - projectlogo, - cfalogo, - backgroundColor: palette.common.white, - layout, - imgType, - scaleFactor: config.images.scaleFactor, - }); - downloadImage(url, title, imgType); - }; - - const handleDataDownload = async (e, type) => { - e.preventDefault(); - e.stopPropagation(); - - const fileType = type.toLowerCase(); - const fileName = `${title}.${fileType}`; - - if (fileType === "json") { - downloadJson(data, fileName); - } else { - downloadSheetData(data, fileType, fileName, title); - } - }; - - return ( - - {!disableToggle && ( - <> - - {values.map((v) => ( - - handleChartValueChange(v)} - > - {v} - - - ))} - - - Download chart as: - - - )} - - {imageTypes.map((p) => ( - - handleImageDownload(e, p)} - > - {p} - - - ))} - - - Layout option: - - - {layouts.map((p, index) => ( - - { - setImageLayout(e, index); - }} - size="large" - > - layout - - - ))} - - - Download data as: - - - {fileTypes.map((f) => ( - - handleDataDownload(e, f)} - > - {f} - - - ))} - - - ); -} - -Download.propTypes = { - title: PropTypes.string, - spec: PropTypes.shape({}), - currentFilters: PropTypes.arrayOf(PropTypes.shape({})), - data: PropTypes.arrayOf(PropTypes.shape({})), - disableToggle: PropTypes.bool, - chartValue: PropTypes.oneOf(["Value", "Percentage"]), - handleChartValueChange: PropTypes.func, - height: PropTypes.number, - source: PropTypes.string, - profileNames: PropTypes.shape({ - primary: PropTypes.string, - secondary: PropTypes.string, - }), - isCompare: PropTypes.bool, -}; - -Download.defaultProps = { - title: undefined, - spec: undefined, - currentFilters: undefined, - data: undefined, - disableToggle: false, - chartValue: undefined, - handleChartValueChange: undefined, - height: 450, - source: undefined, - profileNames: undefined, - isCompare: undefined, -}; - -export default Download; diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/index.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/index.js index 93f48a219..bcbbcc5f8 100644 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/index.js +++ b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/index.js @@ -1,11 +1,10 @@ import { RichTypography } from "@commons-ui/core"; -import { Share, Action } from "@hurumap/core"; -import { Grid } from "@mui/material"; +import { Action, Download, Share } from "@hurumap/core"; +import { Grid, useTheme } from "@mui/material"; import makeStyles from "@mui/styles/makeStyles"; import PropTypes from "prop-types"; -import React from "react"; - -import Download from "./Download"; +import React, { useState, useEffect } from "react"; +import * as vega from "vega"; import { ReactComponent as DownloadIcon } from "@/pesayetu/assets/icons/Component 1.svg"; import { ReactComponent as ShareIcon } from "@/pesayetu/assets/icons/Component 27.svg"; @@ -16,6 +15,10 @@ import { ReactComponent as CopyIcon } from "@/pesayetu/assets/icons/Group 5062.s import { ReactComponent as LinkedInIcon } from "@/pesayetu/assets/icons/LinkedIn.svg"; import { ReactComponent as TwitterIcon } from "@/pesayetu/assets/icons/Twitter.svg"; import { ReactComponent as WhatsAppIcon } from "@/pesayetu/assets/icons/WhatsApp.svg"; +import cfalogo from "@/pesayetu/assets/logos/Group4462.svg"; +import projectlogo from "@/pesayetu/assets/logos/Group5002.svg"; +import { idify } from "@/pesayetu/components/HURUmap/Chart/utils"; +import config, { hurumapArgs } from "@/pesayetu/config"; import site from "@/pesayetu/utils/site"; const useStyles = makeStyles(({ breakpoints, typography, palette }) => ({ @@ -65,9 +68,19 @@ function IndicatorTitle({ view, ...props }) { + const [downloadView, setDownloadView] = useState(null); + const classes = useStyles(props); + const { palette } = useTheme(); - const { geoCode, indicatorId } = props; + const { + currentFilters, + geoCode, + indicatorId, + isCompare, + profileNames, + spec, + } = props; const url = new URL( `/embed/${geoCode.toLowerCase()}/${indicatorId}`, @@ -104,6 +117,34 @@ function IndicatorTitle({ { name: "CopyUrl", icon: CopyIcon, props: { subject: title } }, ]; + const { + indicatorTitle: { + download: { values, layouts, imageTypes, fileTypes }, + }, + } = hurumapArgs; + + const newFilters = currentFilters?.forEach(({ name, value }) => { + const filterName = idify(name); + view?.signal(`${filterName}Filter`, true); + view?.signal(`${filterName}FilterValue`, value); + }); + + const splitString = (str) => { + // eslint-disable-next-line prefer-regex-literals + const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); + const chunks = str.match(regex); + return chunks; + }; + + const chartTitle = splitString(title)?.slice(0, 3); + const subtitle = currentFilters?.reduce((acc, cur) => { + return `${acc}${cur.name}: ${cur.value},`; + }, ""); + const secondaryName = isCompare + ? ` vs ${profileNames?.secondary?.split("-")[0]}` + : ""; + const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; + const actions = [ description && { id: "act-description", @@ -130,6 +171,18 @@ function IndicatorTitle({ ...(view?.data("primary") ?? []), ...(view?.data("secondary") ?? []), ]} + values={values} + imageTypes={imageTypes} + view={downloadView} + chartTitle={chartTitle} + chartSubtitle={chartSubtitle} + cfalogo={cfalogo} + projectlogo={projectlogo} + backgroundColor={palette.common.white} + scaleFactor={config.images.scaleFactor} + layouts={layouts} + fileTypes={fileTypes} + currentFilters={newFilters} /> ), icon: , @@ -151,6 +204,15 @@ function IndicatorTitle({ }, ]; + useEffect(() => { + try { + const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); + setDownloadView(viewProp); + } catch (error) { + console.error("Error creating view", error); + } + }, [spec]); + return (
diff --git a/packages/hurumap-core/package.json b/packages/hurumap-core/package.json index b37b86743..8fa93715e 100644 --- a/packages/hurumap-core/package.json +++ b/packages/hurumap-core/package.json @@ -61,12 +61,14 @@ "@emotion/styled": "^11.11.0", "@mui/material": "^5.14.0", "@mui/utils": "^5.12.3", + "papaparse": "^5.4.1", "leaflet": "^1.9.4", "react": "^18.2.0", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.2.0", "react-leaflet": "^4.2.1", - "react-share": "^5.1.0" + "react-share": "^5.1.0", + "xlsx": "^0.18.5" }, "dependencies": { "prop-types": "^15.8.1" diff --git a/packages/hurumap-core/src/Download/Download.js b/packages/hurumap-core/src/Download/Download.js new file mode 100644 index 000000000..edf1e9f7b --- /dev/null +++ b/packages/hurumap-core/src/Download/Download.js @@ -0,0 +1,325 @@ +import { Grid, ButtonBase, Typography, IconButton } from "@mui/material"; +import React, { useState } from "react"; + +import { + downloadSheetData, + downloadJson, + downloadImage, + createImage, +} from "./utils"; + +const Download = React.forwardRef(function Download( + { + backgroundColor, + cfalogo, + chartSubtitle, + chartTitle, + chartValue, + currentFilters, + data, + disableToggle, + fileTypes, + handleChartValueChange, + height, + imageTypes, + isCompare, + layouts, + projectlogo, + profileNames, + scaleFactor, + spec, + source, + title, + values, + view, + ...props + }, + ref, +) { + const [layout, setLayout] = useState(0); + + const handleImageDownload = async (e, type) => { + e.preventDefault(); + e.stopPropagation(); + + const totalHeight = height + 300; + const imgType = type.toLowerCase(); + + const url = await createImage({ + view, + totalHeight, + chartTitle, + chartSubtitle, + source, + projectlogo, + cfalogo, + backgroundColor, + layout, + imgType, + scaleFactor, + }); + downloadImage(url, title, imgType); + }; + + const handleDataDownload = async (e, type) => { + e.preventDefault(); + e.stopPropagation(); + + const fileType = type.toLowerCase(); + const fileName = `${title}.${fileType}`; + + if (fileType === "json") { + downloadJson(data, fileName); + } else { + downloadSheetData(data, fileType, fileName, title); + } + }; + + const setImageLayout = async (e, type) => { + e.preventDefault(); + e.stopPropagation(); + setLayout(type); + }; + + return ( + + {!disableToggle && ( + <> + ({ + height: theme.typography.pxToRem(36), + })} + > + {values.map((v) => ( + ({ + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRight: `1px solid ${theme.palette.background.paper}`, + "&:last-of-type": { + borderRight: 0, + }, + "&:hover": { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }, + ...(chartValue === v && { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }), + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + onClick={() => handleChartValueChange(v)} + > + {v} + + + ))} + + ({ + height: theme.typography.pxToRem(36), + background: theme.palette.background.paper, + display: "flex", + alignItems: "center", + paddingLeft: theme.typography.pxToRem(16), + justifyContent: "space-between", + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + > + Download chart as: + + + + )} + ({ + height: theme.typography.pxToRem(36), + })} + > + {imageTypes.map((p) => ( + ({ + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRight: `1px solid ${theme.palette.background.paper}`, + "&:last-of-type": { + borderRight: 0, + }, + "&:hover": { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }, + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + onClick={(e) => handleImageDownload(e, p)} + > + {p} + + + ))} + + ({ + height: theme.typography.pxToRem(36), + display: "flex", + alignItems: "center", + paddingLeft: theme.typography.pxToRem(16), + border: `1px solid ${theme.palette.grey.light}`, + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + > + Layout option: + + + ({ + height: theme.typography.pxToRem(36), + })} + > + {layouts.map((p, index) => ( + ({ + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRight: `1px solid ${theme.palette.background.paper}`, + "&:last-of-type": { + borderRight: 0, + }, + "&:hover": { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }, + ...(layout === index && { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }), + })} + > + { + setImageLayout(e, index); + }} + size="large" + > + layout + + + ))} + + ({ + height: theme.typography.pxToRem(36), + background: theme.palette.background.paper, + display: "flex", + alignItems: "center", + paddingLeft: theme.typography.pxToRem(16), + justifyContent: "space-between", + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + > + Download data as: + + + ({ + height: theme.typography.pxToRem(36), + })} + > + {fileTypes.map((f) => ( + ({ + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRight: `1px solid ${theme.palette.background.paper}`, + "&:last-of-type": { + borderRight: 0, + }, + "&:hover": { + background: theme.palette.background.paper, + border: `2px solid ${theme.palette.grey.main}`, + }, + })} + > + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + })} + onClick={(e) => handleDataDownload(e, f)} + > + {f} + + + ))} + + + ); +}); + +export default Download; diff --git a/packages/hurumap-core/src/Download/index.js b/packages/hurumap-core/src/Download/index.js new file mode 100644 index 000000000..c9ba6290e --- /dev/null +++ b/packages/hurumap-core/src/Download/index.js @@ -0,0 +1,3 @@ +import Download from "./Download"; + +export default Download; diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js b/packages/hurumap-core/src/Download/utils.js similarity index 100% rename from apps/pesayetu/src/components/HURUmap/IndicatorTitle/utils.js rename to packages/hurumap-core/src/Download/utils.js diff --git a/packages/hurumap-core/src/index.js b/packages/hurumap-core/src/index.js index 25d86d7b8..9b7b2ffa6 100644 --- a/packages/hurumap-core/src/index.js +++ b/packages/hurumap-core/src/index.js @@ -6,3 +6,4 @@ export { default as Location } from "./Location"; export { default as ShareButton } from "./ShareButton"; export { default as Share } from "./Share"; export { default as Action } from "./Action"; +export { default as Download } from "./Download"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1c6f8c458..78e1a389a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -854,7 +854,7 @@ importers: version: 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@storybook/addon-interactions': specifier: ^8.2.2 - version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) + version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@storybook/addon-links': specifier: ^8.2.2 version: 8.2.2(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) @@ -866,13 +866,13 @@ importers: version: 8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)) '@storybook/nextjs': specifier: ^8.2.2 - version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(babel-plugin-macros@3.1.0)(esbuild@0.21.5)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(next@14.2.5(@babel/core@7.24.8)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(type-fest@4.21.0)(typescript@5.5.3)(webpack-hot-middleware@2.26.1)(webpack@5.93.0(esbuild@0.21.5)) + version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(babel-plugin-macros@3.1.0)(esbuild@0.21.5)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(next@14.2.5(@babel/core@7.24.8)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(type-fest@4.21.0)(typescript@5.5.3)(webpack-hot-middleware@2.26.1)(webpack@5.93.0(esbuild@0.21.5)) '@storybook/react': specifier: ^8.2.2 version: 8.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(typescript@5.5.3) '@storybook/test': specifier: ^8.2.2 - version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) + version: 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@svgr/webpack': specifier: ^8.1.0 version: 8.1.0(typescript@5.5.3) @@ -1634,7 +1634,7 @@ importers: dependencies: '@testing-library/jest-dom': specifier: ^6.4.6 - version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(babel-plugin-macros@3.1.0)) + version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))) '@testing-library/react': specifier: ^14.3.1 version: 14.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1772,6 +1772,9 @@ importers: packages/hurumap-core: dependencies: + papaparse: + specifier: ^5.4.1 + version: 5.4.1 prop-types: specifier: ^15.8.1 version: 15.8.1 @@ -1781,6 +1784,9 @@ importers: react-share: specifier: ^5.1.0 version: 5.1.0(react@18.3.1) + xlsx: + specifier: ^0.18.5 + version: 0.18.5 devDependencies: '@babel/core': specifier: ^7.24.8 @@ -18534,11 +18540,11 @@ snapshots: '@storybook/global': 5.0.0 storybook: 8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)) - '@storybook/addon-interactions@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))': + '@storybook/addon-interactions@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))': dependencies: '@storybook/global': 5.0.0 '@storybook/instrumenter': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) - '@storybook/test': 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) + '@storybook/test': 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) polished: 4.3.1 storybook: 8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)) ts-dedent: 2.2.0 @@ -19004,7 +19010,7 @@ snapshots: '@storybook/mdx2-csf@1.1.0': {} - '@storybook/nextjs@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(babel-plugin-macros@3.1.0)(esbuild@0.21.5)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(next@14.2.5(@babel/core@7.24.8)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(type-fest@4.21.0)(typescript@5.5.3)(webpack-hot-middleware@2.26.1)(webpack@5.93.0(esbuild@0.21.5))': + '@storybook/nextjs@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(babel-plugin-macros@3.1.0)(esbuild@0.21.5)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(next@14.2.5(@babel/core@7.24.8)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(type-fest@4.21.0)(typescript@5.5.3)(webpack-hot-middleware@2.26.1)(webpack@5.93.0(esbuild@0.21.5))': dependencies: '@babel/core': 7.24.8 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.8) @@ -19023,7 +19029,7 @@ snapshots: '@storybook/builder-webpack5': 8.2.2(esbuild@0.21.5)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(typescript@5.5.3) '@storybook/preset-react-webpack': 8.2.2(esbuild@0.21.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(typescript@5.5.3) '@storybook/react': 8.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))(typescript@5.5.3) - '@storybook/test': 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) + '@storybook/test': 8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@types/node': 18.19.39 '@types/semver': 7.5.8 babel-loader: 9.1.3(@babel/core@7.24.8)(webpack@5.93.0(esbuild@0.21.5)) @@ -19349,12 +19355,12 @@ snapshots: memoizerific: 1.11.3 qs: 6.12.3 - '@storybook/test@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))': + '@storybook/test@8.2.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8)))': dependencies: '@storybook/csf': 0.1.11 '@storybook/instrumenter': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.8(@babel/core@7.24.8))) '@testing-library/dom': 10.1.0 - '@testing-library/jest-dom': 6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)) + '@testing-library/jest-dom': 6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))) '@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0) '@vitest/expect': 1.6.0 '@vitest/spy': 1.6.0 @@ -19644,7 +19650,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0))': + '@testing-library/jest-dom@6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.8 @@ -19674,7 +19680,7 @@ snapshots: '@types/jest': 29.5.12 jest: 29.7.0(@types/node@20.14.10) - '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(babel-plugin-macros@3.1.0))': + '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.10)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.8 From 6d33baa3f9427df50d651008654d26b675f17dcd Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:15:04 +0300 Subject: [PATCH 07/18] Climate mapped Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../HURUmap/IndicatorTitle/Download.js | 273 ------------------ .../HURUmap/IndicatorTitle/index.js | 80 ++++- 2 files changed, 71 insertions(+), 282 deletions(-) delete mode 100644 apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/Download.js diff --git a/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/Download.js b/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/Download.js deleted file mode 100644 index 3a1087b65..000000000 --- a/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/Download.js +++ /dev/null @@ -1,273 +0,0 @@ -import { ButtonBase, IconButton, Grid, Typography } from "@mui/material"; -import { useTheme } from "@mui/material/styles"; -import clsx from "clsx"; -import Image from "next/image"; -import Papa from "papaparse"; -import PropTypes from "prop-types"; -import React, { useState, useEffect } from "react"; -import * as vega from "vega"; -import XLSX from "xlsx"; - -import useStyles from "./useStyles"; - -import cfalogo from "@/climatemappedafrica/assets/logos/Group4462.svg"; -import projectlogo from "@/climatemappedafrica/assets/logos/Group5002.svg"; -import { idify } from "@/climatemappedafrica/components/HURUmap/Chart/utils"; -import config, { hurumapArgs } from "@/climatemappedafrica/config"; - -function Download({ - title, - chartValue, - handleChartValueChange, - disableToggle, - spec, - source, - height, - data, - currentFilters, - profileNames, - isCompare, - ...props -}) { - const classes = useStyles(props); - const [view, setView] = useState(null); - const { palette } = useTheme(); - - const { - indicatorTitle: { - download: { values, layouts, imageTypes, fileTypes }, - }, - } = hurumapArgs; - const [layout, setLayout] = useState(0); - - useEffect(() => { - const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); - setView(viewProp); - }, [spec]); - - const setImageLayout = async (e, type) => { - e.preventDefault(); - e.stopPropagation(); - setLayout(type); - }; - - const splitString = (str) => { - // eslint-disable-next-line prefer-regex-literals - const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); - const chunks = str.match(regex); - return chunks; - }; - - currentFilters?.forEach(({ name, value }) => { - const filterName = idify(name); - view?.signal(`${filterName}Filter`, true); - view?.signal(`${filterName}FilterValue`, value); - }); - - const chartTitle = splitString(title)?.slice(0, 3); - const subtitle = currentFilters?.reduce((acc, cur) => { - return `${acc}${cur.name}: ${cur.value},`; - }, ""); - const secondaryName = isCompare - ? ` vs ${profileNames?.secondary?.split("-")[0]}` - : ""; - const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; - - const handleImageDownload = async (e, type) => { - e.preventDefault(); - e.stopPropagation(); - - const totalHeight = height + 300; // chartHeight + extra space for legends, logo + title; - view?.signal("totalHeight", totalHeight); - view?.signal("chartTitle", chartTitle); - view?.signal("chartSubtitle", chartSubtitle.toUpperCase()); - view?.signal("chartSource", source ? `Source: ${source}` : ""); - view?.signal("projectLogoUrl", projectlogo); - view?.signal("logoWidth", 60); - view?.signal("logoUrl", cfalogo); - view?.signal("background", palette.common.white); - - if (layout === 0) { - view?.signal("titleY", 20); - view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); - view?.signal("chartY", 50); - view?.signal("titleGroupY", 0); - view?.signal("sourceGroupY", totalHeight - 80); - view?.signal("sourceGroupH", 60); - view?.signal("sourceY", 30); - } else { - view?.signal("titleY", 25); - view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); - view?.signal("chartY", 60); - view?.signal( - "titleGroupY", - totalHeight - 80 + (chartTitle.length - 1) * 15, - ); - view?.signal("sourceGroupY", 1); - view?.signal("sourceGroupH", 60); - view?.signal("sourceY", 30); - } - await view?.runAsync(); - - const imgType = type.toLowerCase(); - const url = await view.toImageURL(imgType, config.images.scaleFactor); - /* eslint-env browser */ - const link = document.createElement("a"); - link.download = `${title}.${imgType}`; - link.href = url; - /* eslint-env browser */ - document.body.appendChild(link); - link.click(); - /* eslint-env browser */ - document.body.removeChild(link); - }; - - const handleDataDownload = async (e, type) => { - e.preventDefault(); - e.stopPropagation(); - - const fileType = type.toLowerCase(); - const fileName = `${title}.${fileType}`; - let href; - - if (fileType === "json") { - href = `data:text/json;charset=utf-8,${encodeURIComponent( - JSON.stringify(data), - )}`; - } else if (fileType === "csv") { - href = `data:text/csv;charset=utf-8,${Papa.unparse(data)}`; - } else { - const table = XLSX.utils.json_to_sheet(data); - const wb = XLSX.utils.book_new(); // make Workbook of Excel - // add Worksheet to Workbook - XLSX.utils.book_append_sheet(wb, table, title); - // export Excel file - XLSX.writeFile(wb, fileName); - return; - } - /* eslint-env browser */ - const link = document.createElement("a"); - link.href = href; - link.download = fileName; - /* eslint-env browser */ - document.body.appendChild(link); - link.click(); - link.remove(); - }; - - return ( - - {!disableToggle && ( - <> - - {values.map((v) => ( - - handleChartValueChange(v)} - > - {v} - - - ))} - - - Download chart as: - - - )} - - {imageTypes.map((p) => ( - - handleImageDownload(e, p)} - > - {p} - - - ))} - - - Layout option: - - - {layouts.map((p, index) => ( - - { - setImageLayout(e, index); - }} - size="large" - > - layout - - - ))} - - - Download data as: - - - {fileTypes.map((f) => ( - - handleDataDownload(e, f)} - > - {f} - - - ))} - - - ); -} - -Download.propTypes = { - title: PropTypes.string, - spec: PropTypes.shape({}), - currentFilters: PropTypes.arrayOf(PropTypes.shape({})), - data: PropTypes.arrayOf(PropTypes.shape({})), - disableToggle: PropTypes.bool, - chartValue: PropTypes.oneOf(["Value", "Percentage"]), - handleChartValueChange: PropTypes.func, - height: PropTypes.number, - source: PropTypes.string, - profileNames: PropTypes.shape({ - primary: PropTypes.string, - secondary: PropTypes.string, - }), - isCompare: PropTypes.bool, -}; - -Download.defaultProps = { - title: undefined, - spec: undefined, - currentFilters: undefined, - data: undefined, - disableToggle: false, - chartValue: undefined, - handleChartValueChange: undefined, - height: 450, - source: undefined, - profileNames: undefined, - isCompare: undefined, -}; - -export default Download; diff --git a/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/index.js b/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/index.js index 30ed8ef63..4f02d1d2f 100644 --- a/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/index.js +++ b/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/index.js @@ -1,11 +1,10 @@ import { RichTypography } from "@commons-ui/core"; -import { Share, Action } from "@hurumap/core"; -import { Grid } from "@mui/material"; +import { Action, Download, Share } from "@hurumap/core"; +import { Grid, useTheme } from "@mui/material"; import makeStyles from "@mui/styles/makeStyles"; import PropTypes from "prop-types"; -import React from "react"; - -import Download from "./Download"; +import React, { useState, useEffect } from "react"; +import * as vega from "vega"; import { ReactComponent as DownloadIcon } from "@/climatemappedafrica/assets/icons/Component 1.svg"; import { ReactComponent as ShareIcon } from "@/climatemappedafrica/assets/icons/Component 27.svg"; @@ -16,6 +15,10 @@ import { ReactComponent as CopyIcon } from "@/climatemappedafrica/assets/icons/G import { ReactComponent as LinkedInIcon } from "@/climatemappedafrica/assets/icons/LinkedIn.svg"; import { ReactComponent as TwitterIcon } from "@/climatemappedafrica/assets/icons/Twitter.svg"; import { ReactComponent as WhatsAppIcon } from "@/climatemappedafrica/assets/icons/WhatsApp.svg"; +import cfalogo from "@/climatemappedafrica/assets/logos/Group4462.svg"; +import projectlogo from "@/climatemappedafrica/assets/logos/Group5002.svg"; +import { idify } from "@/climatemappedafrica/components/HURUmap/Chart/utils"; +import config, { hurumapArgs } from "@/climatemappedafrica/config"; import site from "@/climatemappedafrica/utils/site"; const useStyles = makeStyles(({ breakpoints, typography, palette }) => ({ @@ -65,9 +68,19 @@ function IndicatorTitle({ view, ...props }) { + const [downloadView, setDownloadView] = useState(null); + const classes = useStyles(props); + const { palette } = useTheme(); - const { geoCode, indicatorId } = props; + const { + currentFilters, + geoCode, + indicatorId, + isCompare, + profileNames, + spec, + } = props; const url = new URL( `/embed/${geoCode.toLowerCase()}/${indicatorId}`, @@ -75,6 +88,11 @@ function IndicatorTitle({ ).toString(); const className = `wrapper-${geoCode}-${indicatorId}`; + const codeData = { + className, + src: `${process.env.NEXT_PUBLIC_APP_URL}/embed/${geoCode.toLowerCase()}/${indicatorId}`, + }; + const shareData = [ { name: "Facebook", @@ -99,11 +117,34 @@ function IndicatorTitle({ { name: "CopyUrl", icon: CopyIcon, props: { subject: title } }, ]; - const codeData = { - className, - src: `${process.env.NEXT_PUBLIC_APP_URL}/embed/${geoCode.toLowerCase()}/${indicatorId}`, + const { + indicatorTitle: { + download: { values, layouts, imageTypes, fileTypes }, + }, + } = hurumapArgs; + + const newFilters = currentFilters?.forEach(({ name, value }) => { + const filterName = idify(name); + view?.signal(`${filterName}Filter`, true); + view?.signal(`${filterName}FilterValue`, value); + }); + + const splitString = (str) => { + // eslint-disable-next-line prefer-regex-literals + const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); + const chunks = str.match(regex); + return chunks; }; + const chartTitle = splitString(title)?.slice(0, 3); + const subtitle = currentFilters?.reduce((acc, cur) => { + return `${acc}${cur.name}: ${cur.value},`; + }, ""); + const secondaryName = isCompare + ? ` vs ${profileNames?.secondary?.split("-")[0]}` + : ""; + const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; + const actions = [ description && { id: "act-description", @@ -130,6 +171,18 @@ function IndicatorTitle({ ...(view?.data("primary") ?? []), ...(view?.data("secondary") ?? []), ]} + values={values} + imageTypes={imageTypes} + view={downloadView} + chartTitle={chartTitle} + chartSubtitle={chartSubtitle} + cfalogo={cfalogo} + projectlogo={projectlogo} + backgroundColor={palette.common.white} + scaleFactor={config.images.scaleFactor} + layouts={layouts} + fileTypes={fileTypes} + currentFilters={newFilters} /> ), icon: , @@ -151,6 +204,15 @@ function IndicatorTitle({ }, ]; + useEffect(() => { + try { + const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); + setDownloadView(viewProp); + } catch (error) { + console.error("Error creating view", error); + } + }, [spec]); + return (
From d6640c9810e43a984be42ce5afcec3ac5e2ad723 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:17:50 +0300 Subject: [PATCH 08/18] Add tests Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../src/Download/Download.snap.js | 49 +++++++++++++++++++ .../src/Download/Download.test.js | 36 ++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 packages/hurumap-core/src/Download/Download.snap.js create mode 100644 packages/hurumap-core/src/Download/Download.test.js diff --git a/packages/hurumap-core/src/Download/Download.snap.js b/packages/hurumap-core/src/Download/Download.snap.js new file mode 100644 index 000000000..d554592a9 --- /dev/null +++ b/packages/hurumap-core/src/Download/Download.snap.js @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Download renders unchanged 1`] = ` +
+
+
+
+

+ Download chart as: +

+
+
+
+

+ Layout option: +

+
+
+
+

+ Download data as: +

+
+
+
+
+`; diff --git a/packages/hurumap-core/src/Download/Download.test.js b/packages/hurumap-core/src/Download/Download.test.js new file mode 100644 index 000000000..f23457ace --- /dev/null +++ b/packages/hurumap-core/src/Download/Download.test.js @@ -0,0 +1,36 @@ +import { render } from "@commons-ui/testing-library"; +import React from "react"; + +import Download from "./Download"; + +const defaultProps = { + backgroundColor: "#fff", + cfalogo: "cfalogo", + chartSubtitle: "chartSubtitle", + chartTitle: "chartTitle", + chartValue: "chartValue", + currentFilters: [], + data: [], + disableToggle: false, + fileTypes: [], + handleChartValueChange: jest.fn(), + height: 100, + imageTypes: [], + isCompare: false, + layouts: [], + projectlogo: "projectlogo", + profileNames: [], + scaleFactor: 1, + spec: {}, + source: "source", + title: "title", + values: [], + view: {}, +}; + +describe("Download", () => { + it("renders unchanged", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); +}); From 1004d164a7bb83be65d5d908a5c8ed9ec052e3c0 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:24:31 +0300 Subject: [PATCH 09/18] Add stories Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../stories/HURUmap/core/Download.stories.js | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 apps/uibook/stories/HURUmap/core/Download.stories.js diff --git a/apps/uibook/stories/HURUmap/core/Download.stories.js b/apps/uibook/stories/HURUmap/core/Download.stories.js new file mode 100644 index 000000000..40c8054fd --- /dev/null +++ b/apps/uibook/stories/HURUmap/core/Download.stories.js @@ -0,0 +1,38 @@ +import { Download } from "@hurumap/core"; +import React from "react"; + +export default { + title: "@hurumap/core/Download", + component: Download, +}; + +function Template(args) { + return ; +} + +export const Default = Template.bind({}); + +Default.args = { + backgroundColor: "white", + cfalogo: null, + chartSubtitle: "Subtitle", + chartTitle: "Title", + chartValue: "Value", + currentFilters: [], + data: [], + disableToggle: false, + fileTypes: ["CSV", "JSON", "XLSX"], + handleChartValueChange: () => {}, + height: 100, + isAction: true, + imageTypes: ["PNG", "JPEG", "SVG"], + layouts: ["Default"], + projectlogo: null, + profileNames: [], + scaleFactor: 2, + spec: {}, + source: "Source", + title: "Download", + values: [], + view: null, +}; From d93237da242ad02ab2d69abec05960f9bba797fa Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:34:33 +0300 Subject: [PATCH 10/18] Fix formating Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- apps/climatemappedafrica/src/lib/hurumap/index.js | 8 ++++---- apps/pesayetu/src/lib/hurumap/index.js | 8 ++++---- apps/promisetracker/src/components/Promises/index.js | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/climatemappedafrica/src/lib/hurumap/index.js b/apps/climatemappedafrica/src/lib/hurumap/index.js index 19527d907..bb03b451a 100644 --- a/apps/climatemappedafrica/src/lib/hurumap/index.js +++ b/apps/climatemappedafrica/src/lib/hurumap/index.js @@ -46,8 +46,8 @@ function formatProfileGeographyData(data, parent) { indicator ], parentData: parent.data - ? parent?.data?.[label]?.subcategories?.[child] - ?.indicators?.[indicator]?.data ?? null + ? (parent?.data?.[label]?.subcategories?.[child] + ?.indicators?.[indicator]?.data ?? null) : null, parentName: parent?.name ?? null, }, @@ -63,9 +63,9 @@ function formatProfileGeographyData(data, parent) { parentMetric: parent.data && parent?.data[label]?.subcategories[child]?.key_metrics - ? parent?.data[label]?.subcategories[child]?.key_metrics[ + ? (parent?.data[label]?.subcategories[child]?.key_metrics[ index - ] ?? null + ] ?? null) : null, }; }), diff --git a/apps/pesayetu/src/lib/hurumap/index.js b/apps/pesayetu/src/lib/hurumap/index.js index d3b3f8390..5495a9d2d 100644 --- a/apps/pesayetu/src/lib/hurumap/index.js +++ b/apps/pesayetu/src/lib/hurumap/index.js @@ -46,8 +46,8 @@ function formatProfileGeographyData(data, parent) { indicator ], parentData: parent.data - ? parent?.data?.[label]?.subcategories?.[child] - ?.indicators?.[indicator]?.data ?? null + ? (parent?.data?.[label]?.subcategories?.[child] + ?.indicators?.[indicator]?.data ?? null) : null, parentName: parent?.name ?? null, }, @@ -63,9 +63,9 @@ function formatProfileGeographyData(data, parent) { parentMetric: parent.data && parent?.data[label]?.subcategories[child]?.key_metrics - ? parent?.data[label]?.subcategories[child]?.key_metrics[ + ? (parent?.data[label]?.subcategories[child]?.key_metrics[ index - ] ?? null + ] ?? null) : null, }; }), diff --git a/apps/promisetracker/src/components/Promises/index.js b/apps/promisetracker/src/components/Promises/index.js index fd404768f..55b68a418 100644 --- a/apps/promisetracker/src/components/Promises/index.js +++ b/apps/promisetracker/src/components/Promises/index.js @@ -94,10 +94,10 @@ function Promises({ sortedItems = items.sort((a, b) => { const aDeadline = a?.promiseDeadline ? new Date(a.promiseDeadline).getTime() - : a.events?.[0]?.year ?? 0; + : (a.events?.[0]?.year ?? 0); const bDeadline = b?.promiseDeadline ? new Date(b.promiseDeadline).getTime() - : b.events?.[0]?.year ?? 0; + : (b.events?.[0]?.year ?? 0); return bDeadline - aDeadline; }); } From c3cf670e1abff0246ec01cb5ec4d6b590319923c Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:46:27 +0300 Subject: [PATCH 11/18] Working indicator title --- .../src/components/HURUmap/Chart/index.js | 160 ++++++- .../hurumap-core/src/IndicatorTitle/Action.js | 96 ---- .../src/IndicatorTitle/Download.js | 426 ------------------ .../src/IndicatorTitle/IndicatorTitle.js | 60 +-- .../hurumap-core/src/IndicatorTitle/Share.js | 234 ---------- .../src/IndicatorTitle/ShareButton.js | 49 -- .../src/ShareButton/ShareButton.js | 4 +- 7 files changed, 161 insertions(+), 868 deletions(-) delete mode 100644 packages/hurumap-core/src/IndicatorTitle/Action.js delete mode 100644 packages/hurumap-core/src/IndicatorTitle/Download.js delete mode 100644 packages/hurumap-core/src/IndicatorTitle/Share.js delete mode 100644 packages/hurumap-core/src/IndicatorTitle/ShareButton.js diff --git a/apps/pesayetu/src/components/HURUmap/Chart/index.js b/apps/pesayetu/src/components/HURUmap/Chart/index.js index e8b23564d..0d72279c9 100644 --- a/apps/pesayetu/src/components/HURUmap/Chart/index.js +++ b/apps/pesayetu/src/components/HURUmap/Chart/index.js @@ -1,15 +1,29 @@ -import { IndicatorTitle, ChartTooltip } from "@hurumap/core"; +import { RichTypography } from "@commons-ui/core"; +import { ChartTooltip, IndicatorTitle, Download, Share } from "@hurumap/core"; import { Source } from "@hurumap/next"; -import { useMediaQuery } from "@mui/material"; +import { useMediaQuery, useTheme } from "@mui/material"; import makeStyles from "@mui/styles/makeStyles"; import React, { useState, useRef, useCallback, useEffect } from "react"; +import * as vega from "vega"; import embed from "vega-embed"; import configureScope from "./configureScope"; import Filters from "./Filters"; import { calculateTooltipPosition, idify } from "./utils"; -// import IndicatorTitle from "@/pesayetu/components/HURUmap/IndicatorTitle"; +import { ReactComponent as DownloadIcon } from "@/pesayetu/assets/icons/Component 1.svg"; +import { ReactComponent as ShareIcon } from "@/pesayetu/assets/icons/Component 27.svg"; +import { ReactComponent as InfoIcon } from "@/pesayetu/assets/icons/Component852.svg"; +import { ReactComponent as EmailIcon } from "@/pesayetu/assets/icons/Email.svg"; +import { ReactComponent as FacebookIcon } from "@/pesayetu/assets/icons/Facebook.svg"; +import { ReactComponent as CopyIcon } from "@/pesayetu/assets/icons/Group 5062.svg"; +import { ReactComponent as LinkedInIcon } from "@/pesayetu/assets/icons/LinkedIn.svg"; +import { ReactComponent as TwitterIcon } from "@/pesayetu/assets/icons/Twitter.svg"; +import { ReactComponent as WhatsAppIcon } from "@/pesayetu/assets/icons/WhatsApp.svg"; +import cfalogo from "@/pesayetu/assets/logos/Group4462.svg"; +import projectlogo from "@/pesayetu/assets/logos/Group5002.svg"; +import config, { hurumapArgs } from "@/pesayetu/config"; +import site from "@/pesayetu/utils/site"; const useStyles = makeStyles(() => ({ root: { @@ -38,6 +52,8 @@ function Chart({ const [cSpec, setCSpec] = useState(null); const isMobile = !useMediaQuery("(min-width:600px)"); const [tooltipData, setTooltipData] = useState(null); + const { palette } = useTheme(); + const [downloadView, setDownloadView] = useState(null); const secondaryIndicator = sI?.indicator; const { @@ -102,6 +118,15 @@ function Chart({ handler, ]); + useEffect(() => { + try { + const viewProp = new vega.View(vega.parse(cSpec), { renderer: "none" }); + setDownloadView(viewProp); + } catch (error) { + console.error("Error creating view", error); + } + }, [cSpec]); + // apply default filter if defined const defaultFilters = filter?.defaults @@ -169,6 +194,134 @@ function Chart({ if (!indicator?.data) { return null; } + const { + indicatorTitle: { + download: { values, layouts, imageTypes, fileTypes }, + }, + } = hurumapArgs; + + const splitString = (str) => { + // eslint-disable-next-line prefer-regex-literals + const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); + const chunks = str.match(regex); + return chunks; + }; + + const chartTitle = splitString(title)?.slice(0, 3); + const subtitle = currentFilters?.reduce((acc, cur) => { + return `${acc}${cur.name}: ${cur.value},`; + }, ""); + const secondaryName = isCompare + ? ` vs ${profileNames?.secondary?.split("-")[0]}` + : ""; + const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; + + const shareData = [ + { + name: "Facebook", + icon: FacebookIcon, + props: { quote: title, hashtag: "#ClimateMapped.Africa" }, + }, + { + name: "Twitter", + icon: TwitterIcon, + props: { title, via: "Code4Africa", related: ["Code4Africa"] }, + }, + { + name: "LinkedIn", + icon: LinkedInIcon, + props: { + summary: title, + source: process.env.NEXT_PUBLIC_APP_URL, + }, + }, + { name: "WhatsApp", icon: WhatsAppIcon, props: { quote: title } }, + { name: "Email", icon: EmailIcon, props: { subject: title } }, + { name: "CopyUrl", icon: CopyIcon, props: { subject: title } }, + ]; + + const shareUrl = new URL( + `/embed/${geoCode.toLowerCase()}/${id}`, + site.environmentUrl, + ).toString(); + + const className = `wrapper-${geoCode}-${id}`; + + const codeData = { + className, + src: `${process.env.NEXT_PUBLIC_APP_URL}/embed/${geoCode.toLowerCase()}/${id}`, + }; + + const actions = [ + description && { + id: "act-description", + title: "Description", + header: "Learn More", + children: ( + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + padding: `${theme.typography.pxToRem(18)} ${theme.typography.pxToRem( + 20, + )} ${theme.typography.pxToRem(31)} ${theme.typography.pxToRem(16)}`, + "& > p > span": { + display: "inline-block", + }, + })} + > + {description} + + ), + icon: , + }, + { + id: "act-download", + title: "Download", + header: disableToggle ? "Download chart as" : "Chart value as:", + children: ( + + ), + icon: , + }, + { + id: "act-share", + title: "Share", + header: "Share chart via:", + children: ( + + ), + icon: , + }, + ]; return (
@@ -187,6 +340,7 @@ function Chart({ isCompare={isCompare} profileNames={profileNames} chartType={chartType?.toLowerCase()} + actions={actions} > {indicatorTitle} diff --git a/packages/hurumap-core/src/IndicatorTitle/Action.js b/packages/hurumap-core/src/IndicatorTitle/Action.js deleted file mode 100644 index 0ee856137..000000000 --- a/packages/hurumap-core/src/IndicatorTitle/Action.js +++ /dev/null @@ -1,96 +0,0 @@ -import CloseIcon from "@mui/icons-material/Close"; -import { - Popper, - Fade, - Paper, - ButtonBase, - Typography, - IconButton, - ClickAwayListener, - Tooltip, - Box, -} from "@mui/material"; -import React, { useState } from "react"; - -function Action({ children, header, icon, title, id, ...props }) { - const [anchorEl, setAnchorEl] = useState(null); - - const handleClick = (event) => { - setAnchorEl(anchorEl ? null : event.currentTarget); - }; - - const handleClose = () => { - setAnchorEl(null); - }; - return ( - - - - {icon} - - - ({ - zIndex: theme.zIndex.drawer, - })} - > - {({ TransitionProps }) => ( - -
- - ({ - background: theme.palette.background.default, - border: `1px solid ${theme.palette.grey.light}`, - width: theme.typography.pxToRem(180), - boxShadow: "0px 3px 6px #00000029", - borderRadius: 0, - marginTop: theme.typography.pxToRem(-40), - })} - > - ({ - background: theme.palette.background.paper, - height: theme.typography.pxToRem(36), - display: "flex", - justifyContent: "space-between", - alignItems: "center", - width: "100%", - paddingLeft: theme.typography.pxToRem(16), - paddingRight: theme.typography.pxToRem(10), - })} - > - ({ - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - })} - > - {header} - - - - {children} - - -
-
- )} -
-
- ); -} - -export default Action; diff --git a/packages/hurumap-core/src/IndicatorTitle/Download.js b/packages/hurumap-core/src/IndicatorTitle/Download.js deleted file mode 100644 index 0c6fcc492..000000000 --- a/packages/hurumap-core/src/IndicatorTitle/Download.js +++ /dev/null @@ -1,426 +0,0 @@ -import { ButtonBase, IconButton, Grid, Typography } from "@mui/material"; -import { useTheme } from "@mui/material/styles"; -// import Image from "next/image"; -import Papa from "papaparse"; -import React, { useState, useEffect } from "react"; -import * as vega from "vega"; -import * as XLSX from "xlsx"; - -import cfalogo from "@/hurumap/core/assets/Group4462.svg"; -import projectlogo from "@/hurumap/core/assets/Group5002.svg"; -import Layout1 from "@/hurumap/core/assets/Group922.svg"; -import Layout2 from "@/hurumap/core/assets/Group923.svg"; -import { idify } from "@/hurumap/core/utils/utils"; -// import config, { hurumapArgs } from "@/pesayetu/config"; - -function Download({ - title, - chartValue, - handleChartValueChange, - disableToggle, - spec, - source, - height, - data, - currentFilters, - profileNames, - isCompare, - ...props -}) { - // const classes = useStyles(props); - const [view, setView] = useState(null); - const { palette } = useTheme(); - - // const { - // indicatorTitle: { - // download: { values, layouts, imageTypes, fileTypes }, - // }, - // } = hurumapArgs; - const values = ["Percentage", "Value"]; - const layouts = [Layout1, Layout2]; - const imageTypes = ["PNG", "SVG"]; - const fileTypes = ["CSV", "XLSX", "JSON"]; - const [layout, setLayout] = useState(0); - - useEffect(() => { - try { - const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); - setView(viewProp); - } catch (error) { - console.error("Error creating view", error); - } - }, [spec]); - - const setImageLayout = async (e, type) => { - e.preventDefault(); - e.stopPropagation(); - setLayout(type); - }; - - const splitString = (str) => { - // eslint-disable-next-line prefer-regex-literals - const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); - const chunks = str.match(regex); - return chunks; - }; - - currentFilters?.forEach(({ name, value }) => { - const filterName = idify(name); - view?.signal(`${filterName}Filter`, true); - view?.signal(`${filterName}FilterValue`, value); - }); - - const chartTitle = splitString(title)?.slice(0, 3); - const subtitle = currentFilters?.reduce((acc, cur) => { - return `${acc}${cur.name}: ${cur.value},`; - }, ""); - const secondaryName = isCompare - ? ` vs ${profileNames?.secondary?.split("-")[0]}` - : ""; - const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; - - const handleImageDownload = async (e, type) => { - e.preventDefault(); - e.stopPropagation(); - - const totalHeight = height + 300; // chartHeight + extra space for legends, logo + title; - view?.signal("totalHeight", totalHeight); - view?.signal("chartTitle", chartTitle); - view?.signal("chartSubtitle", chartSubtitle.toUpperCase()); - view?.signal("chartSource", source ? `Source: ${source}` : ""); - view?.signal("projectLogoUrl", projectlogo); - view?.signal("logoWidth", 60); - view?.signal("logoUrl", cfalogo); - view?.signal("background", palette.common.white); - - if (layout === 0) { - view?.signal("titleY", 20); - view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); - view?.signal("chartY", 50); - view?.signal("titleGroupY", 0); - view?.signal("sourceGroupY", totalHeight - 80); - view?.signal("sourceGroupH", 60); - view?.signal("sourceY", 30); - } else { - view?.signal("titleY", 25); - view?.signal("titleH", 60 + (chartTitle.length - 1) * 15); - view?.signal("chartY", 60); - view?.signal( - "titleGroupY", - totalHeight - 80 + (chartTitle.length - 1) * 15, - ); - view?.signal("sourceGroupY", 1); - view?.signal("sourceGroupH", 60); - view?.signal("sourceY", 30); - } - await view?.runAsync(); - - const imgType = type.toLowerCase(); - // const url = await view.toImageURL(imgType, config.images.scaleFactor); - const url = await view.toImageURL(imgType, 2); - - /* eslint-env browser */ - const link = document.createElement("a"); - link.download = `${title}.${imgType}`; - link.href = url; - /* eslint-env browser */ - document.body.appendChild(link); - link.click(); - /* eslint-env browser */ - document.body.removeChild(link); - }; - - const handleDataDownload = async (e, type) => { - e.preventDefault(); - e.stopPropagation(); - - const fileType = type.toLowerCase(); - const fileName = `${title}.${fileType}`; - let href; - - if (fileType === "json") { - href = `data:text/json;charset=utf-8,${encodeURIComponent( - JSON.stringify(data), - )}`; - } else if (fileType === "csv") { - href = `data:text/csv;charset=utf-8,${Papa.unparse(data)}`; - } else { - const table = XLSX.utils.json_to_sheet(data); - const wb = XLSX.utils.book_new(); // make Workbook of Excel - // add Worksheet to Workbook - XLSX.utils.book_append_sheet(wb, table, title); - // export Excel file - XLSX.writeFile(wb, fileName); - return; - } - /* eslint-env browser */ - const link = document.createElement("a"); - link.href = href; - link.download = fileName; - /* eslint-env browser */ - document.body.appendChild(link); - link.click(); - link.remove(); - }; - - return ( - - {!disableToggle && ( - <> - ({ - height: theme.typography.pxToRem(36), - })} - > - {values.map((v) => ( - ({ - display: "flex", - alignItems: "center", - justifyContent: "center", - borderRight: `1px solid ${theme.palette.background.paper}`, - "&:last-of-type": { - borderRight: 0, - }, - "&:hover": { - background: theme.palette.background.paper, - border: `2px solid ${theme.palette.grey.main}`, - }, - ...(chartValue === v && { - background: theme.palette.background.paper, - border: `2px solid ${theme.palette.grey.main}`, - }), - })} - > - ({ - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - })} - onClick={() => handleChartValueChange(v)} - > - {v} - - - ))} - - ({ - height: theme.typography.pxToRem(36), - background: theme.palette.background.paper, - display: "flex", - alignItems: "center", - paddingLeft: theme.typography.pxToRem(16), - justifyContent: "space-between", - })} - > - ({ - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - })} - > - Download chart as: - - - - )} - ({ - height: theme.typography.pxToRem(36), - })} - > - {imageTypes.map((p) => ( - ({ - display: "flex", - alignItems: "center", - justifyContent: "center", - borderRight: `1px solid ${theme.palette.background.paper}`, - "&:last-of-type": { - borderRight: 0, - }, - "&:hover": { - background: theme.palette.background.paper, - border: `2px solid ${theme.palette.grey.main}`, - }, - })} - > - ({ - fontSize: theme.typography.pxToRem(11), - })} - onClick={(e) => handleImageDownload(e, p)} - > - {p} - - - ))} - - ({ - height: theme.typography.pxToRem(36), - display: "flex", - alignItems: "center", - paddingLeft: theme.typography.pxToRem(16), - border: `1px solid ${theme.palette.grey.light}`, - })} - > - ({ - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - })} - > - Layout option: - - - ({ - height: theme.typography.pxToRem(36), - })} - > - {layouts.map((p, index) => ( - ({ - display: "flex", - alignItems: "center", - justifyContent: "center", - borderRight: `1px solid ${theme.palette.background.paper}`, - "&:last-of-type": { - borderRight: 0, - }, - "&:hover": { - background: theme.palette.background.paper, - border: `2px solid ${theme.palette.grey.main}`, - }, - ...(layout === index && { - background: theme.palette.background.paper, - border: `2px solid ${theme.palette.grey.main}`, - }), - })} - > - { - setImageLayout(e, index); - }} - size="large" - > - layout - - - ))} - - ({ - height: theme.typography.pxToRem(36), - background: theme.palette.background.paper, - display: "flex", - alignItems: "center", - paddingLeft: theme.typography.pxToRem(16), - justifyContent: "space-between", - })} - > - ({ - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - })} - > - Download data as: - - - ({ - height: theme.typography.pxToRem(36), - })} - > - {fileTypes.map((f) => ( - ({ - display: "flex", - alignItems: "center", - justifyContent: "center", - borderRight: `1px solid ${theme.palette.background.paper}`, - "&:last-of-type": { - borderRight: 0, - }, - "&:hover": { - background: theme.palette.background.paper, - border: `2px solid ${theme.palette.grey.main}`, - }, - })} - > - ({ - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - })} - onClick={(e) => handleDataDownload(e, f)} - > - {f} - - - ))} - - - ); -} - -export default Download; diff --git a/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.js b/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.js index 1f57c3302..64d0e2b61 100644 --- a/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.js +++ b/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.js @@ -1,69 +1,13 @@ import { RichTypography } from "@commons-ui/core"; -import DownloadIcon from "@mui/icons-material/Download"; -import InfoIcon from "@mui/icons-material/Info"; -import ShareIcon from "@mui/icons-material/Share"; import { Box, Grid } from "@mui/material"; import React from "react"; -import Action from "./Action"; -import Download from "./Download"; -import Share from "./Share"; +import Action from "@/hurumap/core/Action"; const IndicatorTitle = React.forwardRef(function IndicatorTitle( - { children, description, disableToggle, title, view, ...props }, + { children, actions = [], description, disableToggle, title, view, ...props }, ref, ) { - const actions = [ - description && { - id: "act-description", - title: "Description", - header: "Learn More", - children: ( - ({ - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - padding: `${theme.typography.pxToRem(18)} ${theme.typography.pxToRem( - 20, - )} ${theme.typography.pxToRem(31)} ${theme.typography.pxToRem(16)}`, - "& > p > span": { - display: "inline-block", - }, - })} - > - {description} - - ), - icon: , - }, - { - id: "act-download", - title: "Download", - header: disableToggle ? "Download chart as" : "Chart value as:", - children: ( - - ), - icon: , - }, - { - id: "act-share", - title: "Share", - header: "Share chart via:", - children: , - icon: , - }, - ]; - return ( { - setCopied((prev) => !prev); - }; - - useEffect(() => { - let timer; - if (copied) { - timer = setTimeout(() => { - setCopied(false); - }, 3000); - } - return () => timer && clearTimeout(timer); - }, [copied]); - - // Embed url - const url = new URL( - `/embed/${geoCode.toLowerCase()}/${indicatorId}`, - process.env.NEXT_PUBLIC_APP_URL, - ).toString(); - - const shareData = [ - { name: "Facebook", props: { quote: title, hashtag: "#PesaYetu" } }, - { - name: "Twitter", - props: { title, via: "Code4Africa", related: ["Code4Africa"] }, - }, - { - name: "LinkedIn", - props: { - summary: title, - source: process.env.NEXT_PUBLIC_APP_URL, - }, - }, - { name: "WhatsApp", props: { quote: title } }, - { name: "Email", props: { subject: title } }, - { name: "CopyUrl" }, - ]; - - const className = `wrapper-${geoCode}-${indicatorId}`; - - const code = `
- -
- `; - - return ( - - {shareData.map((social) => ( - - {social.name === "CopyUrl" ? ( - ({ - backgroundColor: `${theme.palette.background.default} !important`, - filter: "opacity(0.6)", - width: "100%", - border: `solid 1px ${theme.palette.background.paper} !important`, - paddingTop: `${theme.typography.pxToRem(5)} !important`, - "&:hover": { - border: "solid 1px #666666 !important", - backgroundColor: `${theme.palette.grey.light} !important`, - }, - })} - > - - ({ - marginLeft: theme.typography.pxToRem(16), - })} - /> - - - ) : ( - - )} - - ))} - - {copied ? ( - ({ - height: theme.typography.pxToRem(36), - display: "flex", - alignItems: "center", - paddingLeft: theme.typography.pxToRem(16), - border: `1px solid ${theme.palette.grey.light}`, - })} - > - ({ - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - })} - > - Copied! - - - ) : null} - - ({ - height: theme.typography.pxToRem(36), - display: "flex", - alignItems: "center", - paddingLeft: theme.typography.pxToRem(16), - border: `1px solid ${theme.palette.grey.light}`, - })} - > - ({ - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - })} - > - Embed on your website: - - - ({ - height: theme.typography.pxToRem(36), - display: "flex", - alignItems: "center", - paddingLeft: theme.typography.pxToRem(16), - border: `1px solid ${theme.palette.grey.light}`, - })} - > - ({ - "& .MuiInputBase-input": { - background: theme.palette.background.paper, - fontSize: theme.typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - }, - })} - /> - - - ); -} - -export default Share; diff --git a/packages/hurumap-core/src/IndicatorTitle/ShareButton.js b/packages/hurumap-core/src/IndicatorTitle/ShareButton.js deleted file mode 100644 index f96ef19e5..000000000 --- a/packages/hurumap-core/src/IndicatorTitle/ShareButton.js +++ /dev/null @@ -1,49 +0,0 @@ -import React from "react"; -import { - TwitterShareButton, - LinkedinShareButton, - FacebookShareButton, - EmailShareButton, - WhatsappShareButton, -} from "react-share"; - -import { ReactComponent as EmailIcon } from "@/hurumap/core/assets/Email.svg"; -import { ReactComponent as FacebookIcon } from "@/hurumap/core/assets/Facebook.svg"; -import { ReactComponent as LinkedInIcon } from "@/hurumap/core/assets/LinkedIn.svg"; -import { ReactComponent as TwitterIcon } from "@/hurumap/core/assets/Twitter.svg"; -import { ReactComponent as WhatsAppIcon } from "@/hurumap/core/assets/WhatsApp.svg"; - -const componentMap = { - Facebook: { icon: FacebookIcon, button: FacebookShareButton }, - Twitter: { icon: TwitterIcon, button: TwitterShareButton }, - LinkedIn: { icon: LinkedInIcon, button: LinkedinShareButton }, - WhatsApp: { icon: WhatsAppIcon, button: WhatsappShareButton }, - Email: { icon: EmailIcon, button: EmailShareButton }, -}; - -function ShareButton({ name, url, ...props }) { - const SocialButtonComponent = componentMap[name].button; - const SocialIcon = componentMap[name].icon; - - return ( - ({ - backgroundColor: `${theme.palette.background.default} !important`, - filter: "opacity(0.6)", - width: "100%", - border: `solid 1px ${theme.palette.background.paper} !important`, - paddingTop: `${theme.typography.pxToRem(5)} !important`, - "&:hover": { - border: "solid 1px #666666 !important", - backgroundColor: `${theme.palette.grey.light} !important`, - }, - })} - > - - - ); -} - -export default ShareButton; diff --git a/packages/hurumap-core/src/ShareButton/ShareButton.js b/packages/hurumap-core/src/ShareButton/ShareButton.js index a99130253..9773811fb 100644 --- a/packages/hurumap-core/src/ShareButton/ShareButton.js +++ b/packages/hurumap-core/src/ShareButton/ShareButton.js @@ -31,11 +31,11 @@ const ShareButton = React.forwardRef(function ShareButton( ) { let SocialButtonComponent = component; - if (name && name !== "CopyUrl") { + if (name) { SocialButtonComponent = componentMap[name]; } - if (!SocialButtonComponent) { + if (!SocialButtonComponent && name !== "CopyUrl") { return null; } From ba86ce7455d308dafcde6f66b98ee6fdf6b9164f Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:59:58 +0300 Subject: [PATCH 12/18] Delete unused indicatorTitle component Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../src/components/HURUmap/Chart/index.js | 176 +++++++++++- .../HURUmap/IndicatorTitle/index.js | 255 ------------------ .../HURUmap/IndicatorTitle/useStyles.js | 80 ------ 3 files changed, 167 insertions(+), 344 deletions(-) delete mode 100644 apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/index.js delete mode 100644 apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/useStyles.js diff --git a/apps/climatemappedafrica/src/components/HURUmap/Chart/index.js b/apps/climatemappedafrica/src/components/HURUmap/Chart/index.js index 29ec03c4f..f8deed06b 100644 --- a/apps/climatemappedafrica/src/components/HURUmap/Chart/index.js +++ b/apps/climatemappedafrica/src/components/HURUmap/Chart/index.js @@ -1,15 +1,29 @@ -import { ChartTooltip } from "@hurumap/core"; +import { RichTypography } from "@commons-ui/core"; +import { ChartTooltip, IndicatorTitle, Download, Share } from "@hurumap/core"; import { Source } from "@hurumap/next"; -import { useMediaQuery } from "@mui/material"; +import { useMediaQuery, useTheme } from "@mui/material"; import makeStyles from "@mui/styles/makeStyles"; import React, { useState, useRef, useCallback, useEffect } from "react"; +import * as vega from "vega"; import embed from "vega-embed"; import configureScope from "./configureScope"; import Filters from "./Filters"; import { calculateTooltipPosition, idify } from "./utils"; -import IndicatorTitle from "@/climatemappedafrica/components/HURUmap/IndicatorTitle"; +import { ReactComponent as DownloadIcon } from "@/climatemappedafrica/assets/icons/Component 1.svg"; +import { ReactComponent as ShareIcon } from "@/climatemappedafrica/assets/icons/Component 27.svg"; +import { ReactComponent as InfoIcon } from "@/climatemappedafrica/assets/icons/Component852.svg"; +import { ReactComponent as EmailIcon } from "@/climatemappedafrica/assets/icons/Email.svg"; +import { ReactComponent as FacebookIcon } from "@/climatemappedafrica/assets/icons/Facebook.svg"; +import { ReactComponent as CopyIcon } from "@/climatemappedafrica/assets/icons/Group 5062.svg"; +import { ReactComponent as LinkedInIcon } from "@/climatemappedafrica/assets/icons/LinkedIn.svg"; +import { ReactComponent as TwitterIcon } from "@/climatemappedafrica/assets/icons/Twitter.svg"; +import { ReactComponent as WhatsAppIcon } from "@/climatemappedafrica/assets/icons/WhatsApp.svg"; +import cfalogo from "@/climatemappedafrica/assets/logos/Group4462.svg"; +import projectlogo from "@/climatemappedafrica/assets/logos/Group5002.svg"; +import config, { hurumapArgs } from "@/climatemappedafrica/config"; +import site from "@/climatemappedafrica/utils/site"; const useStyles = makeStyles(() => ({ root: { @@ -38,6 +52,8 @@ function Chart({ const [cSpec, setCSpec] = useState(null); const isMobile = !useMediaQuery("(min-width:600px)"); const [tooltipData, setTooltipData] = useState(null); + const { palette } = useTheme(); + const [downloadView, setDownloadView] = useState(null); const secondaryIndicator = sI?.indicator; const { @@ -79,13 +95,17 @@ function Chart({ ); setCSpec(spec); if (chartRef?.current) { - const newView = await embed(chartRef.current, spec, { - renderer: "canvas", - actions: false, - tooltip: handler, - }); + try { + const newView = await embed(chartRef.current, spec, { + renderer: "canvas", + actions: false, + tooltip: handler, + }); - setView(newView.view); + setView(newView.view); + } catch (error) { + console.error(error); + } } } renderChart(); @@ -98,6 +118,15 @@ function Chart({ handler, ]); + useEffect(() => { + try { + const viewProp = new vega.View(vega.parse(cSpec), { renderer: "none" }); + setDownloadView(viewProp); + } catch (error) { + console.error("Error creating view", error); + } + }, [cSpec]); + // apply default filter if defined const defaultFilters = filter?.defaults @@ -165,6 +194,134 @@ function Chart({ if (!indicator?.data) { return null; } + const { + indicatorTitle: { + download: { values, layouts, imageTypes, fileTypes }, + }, + } = hurumapArgs; + + const splitString = (str) => { + // eslint-disable-next-line prefer-regex-literals + const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); + const chunks = str.match(regex); + return chunks; + }; + + const chartTitle = splitString(title)?.slice(0, 3); + const subtitle = currentFilters?.reduce((acc, cur) => { + return `${acc}${cur.name}: ${cur.value},`; + }, ""); + const secondaryName = isCompare + ? ` vs ${profileNames?.secondary?.split("-")[0]}` + : ""; + const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; + + const shareData = [ + { + name: "Facebook", + icon: FacebookIcon, + props: { quote: title, hashtag: "#ClimateMapped.Africa" }, + }, + { + name: "Twitter", + icon: TwitterIcon, + props: { title, via: "Code4Africa", related: ["Code4Africa"] }, + }, + { + name: "LinkedIn", + icon: LinkedInIcon, + props: { + summary: title, + source: process.env.NEXT_PUBLIC_APP_URL, + }, + }, + { name: "WhatsApp", icon: WhatsAppIcon, props: { quote: title } }, + { name: "Email", icon: EmailIcon, props: { subject: title } }, + { name: "CopyUrl", icon: CopyIcon, props: { subject: title } }, + ]; + + const shareUrl = new URL( + `/embed/${geoCode.toLowerCase()}/${id}`, + site.environmentUrl, + ).toString(); + + const className = `wrapper-${geoCode}-${id}`; + + const codeData = { + className, + src: `${process.env.NEXT_PUBLIC_APP_URL}/embed/${geoCode.toLowerCase()}/${id}`, + }; + + const actions = [ + description && { + id: "act-description", + title: "Description", + header: "Learn More", + children: ( + ({ + fontSize: theme.typography.pxToRem(11), + lineHeight: 17 / 11, + color: "#666666", + padding: `${theme.typography.pxToRem(18)} ${theme.typography.pxToRem( + 20, + )} ${theme.typography.pxToRem(31)} ${theme.typography.pxToRem(16)}`, + "& > p > span": { + display: "inline-block", + }, + })} + > + {description} + + ), + icon: , + }, + { + id: "act-download", + title: "Download", + header: disableToggle ? "Download chart as" : "Chart value as:", + children: ( + + ), + icon: , + }, + { + id: "act-share", + title: "Share", + header: "Share chart via:", + children: ( + + ), + icon: , + }, + ]; return (
@@ -183,6 +340,7 @@ function Chart({ isCompare={isCompare} profileNames={profileNames} chartType={chartType?.toLowerCase()} + actions={actions} > {indicatorTitle} diff --git a/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/index.js b/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/index.js deleted file mode 100644 index 4f02d1d2f..000000000 --- a/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/index.js +++ /dev/null @@ -1,255 +0,0 @@ -import { RichTypography } from "@commons-ui/core"; -import { Action, Download, Share } from "@hurumap/core"; -import { Grid, useTheme } from "@mui/material"; -import makeStyles from "@mui/styles/makeStyles"; -import PropTypes from "prop-types"; -import React, { useState, useEffect } from "react"; -import * as vega from "vega"; - -import { ReactComponent as DownloadIcon } from "@/climatemappedafrica/assets/icons/Component 1.svg"; -import { ReactComponent as ShareIcon } from "@/climatemappedafrica/assets/icons/Component 27.svg"; -import { ReactComponent as InfoIcon } from "@/climatemappedafrica/assets/icons/Component852.svg"; -import { ReactComponent as EmailIcon } from "@/climatemappedafrica/assets/icons/Email.svg"; -import { ReactComponent as FacebookIcon } from "@/climatemappedafrica/assets/icons/Facebook.svg"; -import { ReactComponent as CopyIcon } from "@/climatemappedafrica/assets/icons/Group 5062.svg"; -import { ReactComponent as LinkedInIcon } from "@/climatemappedafrica/assets/icons/LinkedIn.svg"; -import { ReactComponent as TwitterIcon } from "@/climatemappedafrica/assets/icons/Twitter.svg"; -import { ReactComponent as WhatsAppIcon } from "@/climatemappedafrica/assets/icons/WhatsApp.svg"; -import cfalogo from "@/climatemappedafrica/assets/logos/Group4462.svg"; -import projectlogo from "@/climatemappedafrica/assets/logos/Group5002.svg"; -import { idify } from "@/climatemappedafrica/components/HURUmap/Chart/utils"; -import config, { hurumapArgs } from "@/climatemappedafrica/config"; -import site from "@/climatemappedafrica/utils/site"; - -const useStyles = makeStyles(({ breakpoints, typography, palette }) => ({ - root: { - paddingTop: typography.pxToRem(24), - paddingBottom: typography.pxToRem(25), - }, - description: { - fontSize: typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - padding: `${typography.pxToRem(18)} ${typography.pxToRem( - 20, - )} ${typography.pxToRem(31)} ${typography.pxToRem(16)}`, - "& > p > span": { - display: "inline-block", - }, - }, - link: { - color: palette.text.primary, - fontSize: typography.pxToRem(13), - lineHeight: 20 / 13, - fontFamily: typography.body1.fontFamily, - }, - action: { - marginRight: typography.pxToRem(14), - "&:last-of-type": { - marginRight: 0, - }, - }, - buttons: { - justifyContent: "flex-start", - marginTop: typography.pxToRem(20), - marginBottom: typography.pxToRem(20), - [breakpoints.up("md")]: { - justifyContent: "flex-end", - margin: 0, - }, - }, -})); - -function IndicatorTitle({ - children, - description, - disableToggle, - title, - view, - ...props -}) { - const [downloadView, setDownloadView] = useState(null); - - const classes = useStyles(props); - const { palette } = useTheme(); - - const { - currentFilters, - geoCode, - indicatorId, - isCompare, - profileNames, - spec, - } = props; - - const url = new URL( - `/embed/${geoCode.toLowerCase()}/${indicatorId}`, - site.environmentUrl, - ).toString(); - const className = `wrapper-${geoCode}-${indicatorId}`; - - const codeData = { - className, - src: `${process.env.NEXT_PUBLIC_APP_URL}/embed/${geoCode.toLowerCase()}/${indicatorId}`, - }; - - const shareData = [ - { - name: "Facebook", - icon: FacebookIcon, - props: { quote: title, hashtag: "#ClimateMapped.Africa" }, - }, - { - name: "Twitter", - icon: TwitterIcon, - props: { title, via: "Code4Africa", related: ["Code4Africa"] }, - }, - { - name: "LinkedIn", - icon: LinkedInIcon, - props: { - summary: title, - source: process.env.NEXT_PUBLIC_APP_URL, - }, - }, - { name: "WhatsApp", icon: WhatsAppIcon, props: { quote: title } }, - { name: "Email", icon: EmailIcon, props: { subject: title } }, - { name: "CopyUrl", icon: CopyIcon, props: { subject: title } }, - ]; - - const { - indicatorTitle: { - download: { values, layouts, imageTypes, fileTypes }, - }, - } = hurumapArgs; - - const newFilters = currentFilters?.forEach(({ name, value }) => { - const filterName = idify(name); - view?.signal(`${filterName}Filter`, true); - view?.signal(`${filterName}FilterValue`, value); - }); - - const splitString = (str) => { - // eslint-disable-next-line prefer-regex-literals - const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); - const chunks = str.match(regex); - return chunks; - }; - - const chartTitle = splitString(title)?.slice(0, 3); - const subtitle = currentFilters?.reduce((acc, cur) => { - return `${acc}${cur.name}: ${cur.value},`; - }, ""); - const secondaryName = isCompare - ? ` vs ${profileNames?.secondary?.split("-")[0]}` - : ""; - const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; - - const actions = [ - description && { - id: "act-description", - title: "Description", - header: "Learn More", - children: ( - - {description} - - ), - icon: , - }, - { - id: "act-download", - title: "Download", - header: disableToggle ? "Download chart as" : "Chart value as:", - children: ( - - ), - icon: , - }, - { - id: "act-share", - title: "Share", - header: "Share chart via:", - children: ( - - ), - icon: , - }, - ]; - - useEffect(() => { - try { - const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); - setDownloadView(viewProp); - } catch (error) { - console.error("Error creating view", error); - } - }, [spec]); - - return ( -
- - - {children || title} - - - {actions - .filter((a) => a?.id) - .map((act) => ( - - - - ))} - - -
- ); -} - -IndicatorTitle.propTypes = { - children: PropTypes.node, - description: PropTypes.string, - disableToggle: PropTypes.bool, - title: PropTypes.string, - view: PropTypes.shape({ - height: PropTypes.func, - data: PropTypes.func, - }), -}; - -IndicatorTitle.defaultProps = { - children: undefined, - description: undefined, - disableToggle: false, - title: undefined, - view: undefined, -}; - -export default IndicatorTitle; diff --git a/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/useStyles.js b/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/useStyles.js deleted file mode 100644 index 429ec2f18..000000000 --- a/apps/climatemappedafrica/src/components/HURUmap/IndicatorTitle/useStyles.js +++ /dev/null @@ -1,80 +0,0 @@ -import makeStyles from "@mui/styles/makeStyles"; - -const useStyles = makeStyles(({ palette, typography }) => ({ - root: {}, - header: { - background: palette.background.paper, - display: "flex", - alignItems: "center", - paddingLeft: typography.pxToRem(16), - justifyContent: "space-between", - }, - layout: { - display: "flex", - alignItems: "center", - paddingLeft: typography.pxToRem(16), - border: `1px solid ${palette.grey.light}`, - }, - row: { - height: typography.pxToRem(36), - }, - cell: { - borderRight: `1px solid ${palette.background.paper}`, - "&:last-of-type": { - borderRight: 0, - }, - }, - text: { - fontSize: typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - }, - layoutButton: { - padding: 0, - }, - button: { - display: "flex", - alignItems: "center", - justifyContent: "center", - borderRight: `1px solid ${palette.background.paper}`, - "&:last-of-type": { - borderRight: 0, - }, - "&:hover": { - background: palette.background.paper, - border: `2px solid ${palette.grey.main}`, - }, - }, - activeButton: { - background: palette.background.paper, - border: `2px solid ${palette.grey.main}`, - }, - description: { - fontSize: typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - padding: `${typography.pxToRem(18)} ${typography.pxToRem( - 20, - )} ${typography.pxToRem(31)} ${typography.pxToRem(16)}`, - }, - code: { - background: palette.background.paper, - }, - shareButton: { - backgroundColor: `${palette.background.default} !important`, - filter: "opacity(0.6)", - width: "100%", - border: `solid 1px ${palette.background.paper} !important`, - paddingTop: `${typography.pxToRem(5)} !important`, - "&:hover": { - border: "solid 1px #666666 !important", - backgroundColor: `${palette.grey.light} !important`, - }, - }, - icon: {}, - copyIcon: { - marginLeft: typography.pxToRem(16), - }, -})); - -export default useStyles; From 475b55bdeb1a451414f03b622637518d9b43cf44 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:00:32 +0300 Subject: [PATCH 13/18] delete unused component Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../HURUmap/IndicatorTitle/index.js | 255 ------------------ .../HURUmap/IndicatorTitle/useStyles.js | 80 ------ 2 files changed, 335 deletions(-) delete mode 100644 apps/pesayetu/src/components/HURUmap/IndicatorTitle/index.js delete mode 100644 apps/pesayetu/src/components/HURUmap/IndicatorTitle/useStyles.js diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/index.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/index.js deleted file mode 100644 index bcbbcc5f8..000000000 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/index.js +++ /dev/null @@ -1,255 +0,0 @@ -import { RichTypography } from "@commons-ui/core"; -import { Action, Download, Share } from "@hurumap/core"; -import { Grid, useTheme } from "@mui/material"; -import makeStyles from "@mui/styles/makeStyles"; -import PropTypes from "prop-types"; -import React, { useState, useEffect } from "react"; -import * as vega from "vega"; - -import { ReactComponent as DownloadIcon } from "@/pesayetu/assets/icons/Component 1.svg"; -import { ReactComponent as ShareIcon } from "@/pesayetu/assets/icons/Component 27.svg"; -import { ReactComponent as InfoIcon } from "@/pesayetu/assets/icons/Component852.svg"; -import { ReactComponent as EmailIcon } from "@/pesayetu/assets/icons/Email.svg"; -import { ReactComponent as FacebookIcon } from "@/pesayetu/assets/icons/Facebook.svg"; -import { ReactComponent as CopyIcon } from "@/pesayetu/assets/icons/Group 5062.svg"; -import { ReactComponent as LinkedInIcon } from "@/pesayetu/assets/icons/LinkedIn.svg"; -import { ReactComponent as TwitterIcon } from "@/pesayetu/assets/icons/Twitter.svg"; -import { ReactComponent as WhatsAppIcon } from "@/pesayetu/assets/icons/WhatsApp.svg"; -import cfalogo from "@/pesayetu/assets/logos/Group4462.svg"; -import projectlogo from "@/pesayetu/assets/logos/Group5002.svg"; -import { idify } from "@/pesayetu/components/HURUmap/Chart/utils"; -import config, { hurumapArgs } from "@/pesayetu/config"; -import site from "@/pesayetu/utils/site"; - -const useStyles = makeStyles(({ breakpoints, typography, palette }) => ({ - root: { - paddingTop: typography.pxToRem(24), - paddingBottom: typography.pxToRem(25), - }, - description: { - fontSize: typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - padding: `${typography.pxToRem(18)} ${typography.pxToRem( - 20, - )} ${typography.pxToRem(31)} ${typography.pxToRem(16)}`, - "& > p > span": { - display: "inline-block", - }, - }, - link: { - color: palette.text.primary, - fontSize: typography.pxToRem(13), - lineHeight: 20 / 13, - fontFamily: typography.body1.fontFamily, - }, - action: { - marginRight: typography.pxToRem(14), - "&:last-of-type": { - marginRight: 0, - }, - }, - buttons: { - justifyContent: "flex-start", - marginTop: typography.pxToRem(20), - marginBottom: typography.pxToRem(20), - [breakpoints.up("md")]: { - justifyContent: "flex-end", - margin: 0, - }, - }, -})); - -function IndicatorTitle({ - children, - description, - disableToggle, - title, - view, - ...props -}) { - const [downloadView, setDownloadView] = useState(null); - - const classes = useStyles(props); - const { palette } = useTheme(); - - const { - currentFilters, - geoCode, - indicatorId, - isCompare, - profileNames, - spec, - } = props; - - const url = new URL( - `/embed/${geoCode.toLowerCase()}/${indicatorId}`, - site.environmentUrl, - ).toString(); - const className = `wrapper-${geoCode}-${indicatorId}`; - - const codeData = { - className, - src: `${process.env.NEXT_PUBLIC_APP_URL}/embed/${geoCode.toLowerCase()}/${indicatorId}`, - }; - - const shareData = [ - { - name: "Facebook", - icon: FacebookIcon, - props: { quote: title, hashtag: "#ClimateMapped.Africa" }, - }, - { - name: "Twitter", - icon: TwitterIcon, - props: { title, via: "Code4Africa", related: ["Code4Africa"] }, - }, - { - name: "LinkedIn", - icon: LinkedInIcon, - props: { - summary: title, - source: process.env.NEXT_PUBLIC_APP_URL, - }, - }, - { name: "WhatsApp", icon: WhatsAppIcon, props: { quote: title } }, - { name: "Email", icon: EmailIcon, props: { subject: title } }, - { name: "CopyUrl", icon: CopyIcon, props: { subject: title } }, - ]; - - const { - indicatorTitle: { - download: { values, layouts, imageTypes, fileTypes }, - }, - } = hurumapArgs; - - const newFilters = currentFilters?.forEach(({ name, value }) => { - const filterName = idify(name); - view?.signal(`${filterName}Filter`, true); - view?.signal(`${filterName}FilterValue`, value); - }); - - const splitString = (str) => { - // eslint-disable-next-line prefer-regex-literals - const regex = new RegExp(/\S.{1,42}\S(?= |$)/, "g"); - const chunks = str.match(regex); - return chunks; - }; - - const chartTitle = splitString(title)?.slice(0, 3); - const subtitle = currentFilters?.reduce((acc, cur) => { - return `${acc}${cur.name}: ${cur.value},`; - }, ""); - const secondaryName = isCompare - ? ` vs ${profileNames?.secondary?.split("-")[0]}` - : ""; - const chartSubtitle = `${subtitle} Location: ${profileNames?.primary}${secondaryName}`; - - const actions = [ - description && { - id: "act-description", - title: "Description", - header: "Learn More", - children: ( - - {description} - - ), - icon: , - }, - { - id: "act-download", - title: "Download", - header: disableToggle ? "Download chart as" : "Chart value as:", - children: ( - - ), - icon: , - }, - { - id: "act-share", - title: "Share", - header: "Share chart via:", - children: ( - - ), - icon: , - }, - ]; - - useEffect(() => { - try { - const viewProp = new vega.View(vega.parse(spec), { renderer: "none" }); - setDownloadView(viewProp); - } catch (error) { - console.error("Error creating view", error); - } - }, [spec]); - - return ( -
- - - {children || title} - - - {actions - .filter((a) => a?.id) - .map((act) => ( - - - - ))} - - -
- ); -} - -IndicatorTitle.propTypes = { - children: PropTypes.node, - description: PropTypes.string, - disableToggle: PropTypes.bool, - title: PropTypes.string, - view: PropTypes.shape({ - height: PropTypes.func, - data: PropTypes.func, - }), -}; - -IndicatorTitle.defaultProps = { - children: undefined, - description: undefined, - disableToggle: false, - title: undefined, - view: undefined, -}; - -export default IndicatorTitle; diff --git a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/useStyles.js b/apps/pesayetu/src/components/HURUmap/IndicatorTitle/useStyles.js deleted file mode 100644 index 429ec2f18..000000000 --- a/apps/pesayetu/src/components/HURUmap/IndicatorTitle/useStyles.js +++ /dev/null @@ -1,80 +0,0 @@ -import makeStyles from "@mui/styles/makeStyles"; - -const useStyles = makeStyles(({ palette, typography }) => ({ - root: {}, - header: { - background: palette.background.paper, - display: "flex", - alignItems: "center", - paddingLeft: typography.pxToRem(16), - justifyContent: "space-between", - }, - layout: { - display: "flex", - alignItems: "center", - paddingLeft: typography.pxToRem(16), - border: `1px solid ${palette.grey.light}`, - }, - row: { - height: typography.pxToRem(36), - }, - cell: { - borderRight: `1px solid ${palette.background.paper}`, - "&:last-of-type": { - borderRight: 0, - }, - }, - text: { - fontSize: typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - }, - layoutButton: { - padding: 0, - }, - button: { - display: "flex", - alignItems: "center", - justifyContent: "center", - borderRight: `1px solid ${palette.background.paper}`, - "&:last-of-type": { - borderRight: 0, - }, - "&:hover": { - background: palette.background.paper, - border: `2px solid ${palette.grey.main}`, - }, - }, - activeButton: { - background: palette.background.paper, - border: `2px solid ${palette.grey.main}`, - }, - description: { - fontSize: typography.pxToRem(11), - lineHeight: 17 / 11, - color: "#666666", - padding: `${typography.pxToRem(18)} ${typography.pxToRem( - 20, - )} ${typography.pxToRem(31)} ${typography.pxToRem(16)}`, - }, - code: { - background: palette.background.paper, - }, - shareButton: { - backgroundColor: `${palette.background.default} !important`, - filter: "opacity(0.6)", - width: "100%", - border: `solid 1px ${palette.background.paper} !important`, - paddingTop: `${typography.pxToRem(5)} !important`, - "&:hover": { - border: "solid 1px #666666 !important", - backgroundColor: `${palette.grey.light} !important`, - }, - }, - icon: {}, - copyIcon: { - marginLeft: typography.pxToRem(16), - }, -})); - -export default useStyles; From ca803d6f3b1966e405ee7051c8226c28345b4797 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:18:38 +0300 Subject: [PATCH 14/18] Move button component Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../HURUmap/core/ShareButton.stories.js | 51 ------------------- packages/hurumap-core/src/Share/Share.js | 2 +- .../src/{ShareButton => Share}/ShareButton.js | 0 .../ShareButton.snap.js | 0 .../ShareButton.test.js | 0 .../hurumap-core/src/ShareButton/index.js | 3 -- packages/hurumap-core/src/index.js | 1 - 7 files changed, 1 insertion(+), 56 deletions(-) delete mode 100644 apps/uibook/stories/HURUmap/core/ShareButton.stories.js rename packages/hurumap-core/src/{ShareButton => Share}/ShareButton.js (100%) rename packages/hurumap-core/src/{ShareButton => Share}/ShareButton.snap.js (100%) rename packages/hurumap-core/src/{ShareButton => Share}/ShareButton.test.js (100%) delete mode 100644 packages/hurumap-core/src/ShareButton/index.js diff --git a/apps/uibook/stories/HURUmap/core/ShareButton.stories.js b/apps/uibook/stories/HURUmap/core/ShareButton.stories.js deleted file mode 100644 index 817d6f063..000000000 --- a/apps/uibook/stories/HURUmap/core/ShareButton.stories.js +++ /dev/null @@ -1,51 +0,0 @@ -import { ShareButton } from "@hurumap/core"; -import EmailIcon from "@mui/icons-material/Email"; -import FacebookIcon from "@mui/icons-material/Facebook"; -import LinkedInIcon from "@mui/icons-material/LinkedIn"; -import PinterestIcon from "@mui/icons-material/Pinterest"; -import TelegramIcon from "@mui/icons-material/Telegram"; -import WhatsAppIcon from "@mui/icons-material/WhatsApp"; -import XIcon from "@mui/icons-material/X"; -import React from "react"; - -export default { - title: "@hurumap/core/ShareButton", - argTypes: { - name: { - control: { - type: "select", - }, - options: [ - "Facebook", - "Twitter", - "LinkedIn", - "WhatsApp", - "Email", - "Telegram", - "Pinterest", - ], - }, - }, -}; - -const iconMapping = { - Facebook: FacebookIcon, - Twitter: XIcon, - LinkedIn: LinkedInIcon, - WhatsApp: WhatsAppIcon, - Email: EmailIcon, - Telegram: TelegramIcon, - Pinterest: PinterestIcon, -}; - -function Template({ name, ...args }) { - const IconComponent = iconMapping[name]; - return ; -} - -export const Default = Template.bind({}); - -Default.args = { - url: "https://codeforafrica.org", - name: "Facebook", -}; diff --git a/packages/hurumap-core/src/Share/Share.js b/packages/hurumap-core/src/Share/Share.js index 6aae3dce6..dce5caa2a 100644 --- a/packages/hurumap-core/src/Share/Share.js +++ b/packages/hurumap-core/src/Share/Share.js @@ -1,7 +1,7 @@ import { Grid, TextField, Typography, useTheme } from "@mui/material"; import React, { useState, useEffect } from "react"; -import ShareButton from "@/hurumap/core/ShareButton"; +import ShareButton from "./ShareButton"; const Share = React.forwardRef(function Share( { diff --git a/packages/hurumap-core/src/ShareButton/ShareButton.js b/packages/hurumap-core/src/Share/ShareButton.js similarity index 100% rename from packages/hurumap-core/src/ShareButton/ShareButton.js rename to packages/hurumap-core/src/Share/ShareButton.js diff --git a/packages/hurumap-core/src/ShareButton/ShareButton.snap.js b/packages/hurumap-core/src/Share/ShareButton.snap.js similarity index 100% rename from packages/hurumap-core/src/ShareButton/ShareButton.snap.js rename to packages/hurumap-core/src/Share/ShareButton.snap.js diff --git a/packages/hurumap-core/src/ShareButton/ShareButton.test.js b/packages/hurumap-core/src/Share/ShareButton.test.js similarity index 100% rename from packages/hurumap-core/src/ShareButton/ShareButton.test.js rename to packages/hurumap-core/src/Share/ShareButton.test.js diff --git a/packages/hurumap-core/src/ShareButton/index.js b/packages/hurumap-core/src/ShareButton/index.js deleted file mode 100644 index 0b9ed88f1..000000000 --- a/packages/hurumap-core/src/ShareButton/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import ShareButton from "./ShareButton"; - -export default ShareButton; diff --git a/packages/hurumap-core/src/index.js b/packages/hurumap-core/src/index.js index 3ed6ac8c4..8b4eef3c0 100644 --- a/packages/hurumap-core/src/index.js +++ b/packages/hurumap-core/src/index.js @@ -5,7 +5,6 @@ export { default as LocationHighlight } from "./LocationHighlight"; export { default as Location } from "./Location"; export { default as IndicatorTitle } from "./IndicatorTitle"; export { default as Scope } from "./Scope"; -export { default as ShareButton } from "./ShareButton"; export { default as Share } from "./Share"; export { default as Action } from "./Action"; export { default as Download } from "./Download"; From 09afdc8882895f3a91fe61cf0015630558e3d237 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:25:22 +0300 Subject: [PATCH 15/18] Add tests Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../src/IndicatorTitle/IndicatorTitle.snap.js | 28 +++++++++++++++++++ .../src/IndicatorTitle/IndicatorTitle.test.js | 19 +++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.snap.js create mode 100644 packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.test.js diff --git a/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.snap.js b/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.snap.js new file mode 100644 index 000000000..a81eb3f2b --- /dev/null +++ b/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.snap.js @@ -0,0 +1,28 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IndicatorTitle renders unchanged 1`] = ` +
+
+
+
+
+
+ Children +
+
+
+
+
+
+
+`; diff --git a/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.test.js b/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.test.js new file mode 100644 index 000000000..b4a97ce9c --- /dev/null +++ b/packages/hurumap-core/src/IndicatorTitle/IndicatorTitle.test.js @@ -0,0 +1,19 @@ +import { render } from "@commons-ui/testing-library"; +import React from "react"; + +import IndicatorTitle from "./IndicatorTitle"; + +const defaultProps = { + children:
Children
, + description: "Description", + title: "Title", + view: {}, + actions: [], +}; + +describe("IndicatorTitle", () => { + it("renders unchanged", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); +}); From 92482bbd0bdf55e72d13300253f863c1824200c8 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:14:22 +0300 Subject: [PATCH 16/18] Remove unused assets Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- packages/hurumap-core/src/assets/Email.svg | 1 - packages/hurumap-core/src/assets/Facebook.svg | 1 - .../hurumap-core/src/assets/Group4462.svg | 1 - .../hurumap-core/src/assets/Group5002.svg | 9 --------- packages/hurumap-core/src/assets/Group922.svg | 19 ------------------- packages/hurumap-core/src/assets/Group923.svg | 19 ------------------- packages/hurumap-core/src/assets/LinkedIn.svg | 1 - packages/hurumap-core/src/assets/Twitter.svg | 1 - packages/hurumap-core/src/assets/WhatsApp.svg | 1 - 9 files changed, 53 deletions(-) delete mode 100644 packages/hurumap-core/src/assets/Email.svg delete mode 100644 packages/hurumap-core/src/assets/Facebook.svg delete mode 100644 packages/hurumap-core/src/assets/Group4462.svg delete mode 100644 packages/hurumap-core/src/assets/Group5002.svg delete mode 100644 packages/hurumap-core/src/assets/Group922.svg delete mode 100644 packages/hurumap-core/src/assets/Group923.svg delete mode 100644 packages/hurumap-core/src/assets/LinkedIn.svg delete mode 100644 packages/hurumap-core/src/assets/Twitter.svg delete mode 100644 packages/hurumap-core/src/assets/WhatsApp.svg diff --git a/packages/hurumap-core/src/assets/Email.svg b/packages/hurumap-core/src/assets/Email.svg deleted file mode 100644 index 3e44b8779..000000000 --- a/packages/hurumap-core/src/assets/Email.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/Facebook.svg b/packages/hurumap-core/src/assets/Facebook.svg deleted file mode 100644 index 56c40db42..000000000 --- a/packages/hurumap-core/src/assets/Facebook.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/Group4462.svg b/packages/hurumap-core/src/assets/Group4462.svg deleted file mode 100644 index 277cf32a8..000000000 --- a/packages/hurumap-core/src/assets/Group4462.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/Group5002.svg b/packages/hurumap-core/src/assets/Group5002.svg deleted file mode 100644 index 511d34de6..000000000 --- a/packages/hurumap-core/src/assets/Group5002.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/packages/hurumap-core/src/assets/Group922.svg b/packages/hurumap-core/src/assets/Group922.svg deleted file mode 100644 index d5d131c3b..000000000 --- a/packages/hurumap-core/src/assets/Group922.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/packages/hurumap-core/src/assets/Group923.svg b/packages/hurumap-core/src/assets/Group923.svg deleted file mode 100644 index 82ecb1b26..000000000 --- a/packages/hurumap-core/src/assets/Group923.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/packages/hurumap-core/src/assets/LinkedIn.svg b/packages/hurumap-core/src/assets/LinkedIn.svg deleted file mode 100644 index 744718823..000000000 --- a/packages/hurumap-core/src/assets/LinkedIn.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/Twitter.svg b/packages/hurumap-core/src/assets/Twitter.svg deleted file mode 100644 index ebef26dec..000000000 --- a/packages/hurumap-core/src/assets/Twitter.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/hurumap-core/src/assets/WhatsApp.svg b/packages/hurumap-core/src/assets/WhatsApp.svg deleted file mode 100644 index 85385c727..000000000 --- a/packages/hurumap-core/src/assets/WhatsApp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From b176ac65a41d79ef4a6ce299b7f7828e3c08a0f3 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 1 Aug 2024 17:52:58 +0300 Subject: [PATCH 17/18] Fix stories Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- .../src/components/HURUmap/Chart/index.js | 2 +- .../stories/hurumap/core/Download.stories.js | 7 ++- .../hurumap/core/IndicatorTitle.stories.js | 47 +++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 apps/uibook/stories/hurumap/core/IndicatorTitle.stories.js diff --git a/apps/climatemappedafrica/src/components/HURUmap/Chart/index.js b/apps/climatemappedafrica/src/components/HURUmap/Chart/index.js index f8deed06b..470218447 100644 --- a/apps/climatemappedafrica/src/components/HURUmap/Chart/index.js +++ b/apps/climatemappedafrica/src/components/HURUmap/Chart/index.js @@ -104,7 +104,7 @@ function Chart({ setView(newView.view); } catch (error) { - console.error(error); + console.error("Error rendering chart", error); } } } diff --git a/apps/uibook/stories/hurumap/core/Download.stories.js b/apps/uibook/stories/hurumap/core/Download.stories.js index 40c8054fd..356cb61b2 100644 --- a/apps/uibook/stories/hurumap/core/Download.stories.js +++ b/apps/uibook/stories/hurumap/core/Download.stories.js @@ -25,8 +25,8 @@ Default.args = { handleChartValueChange: () => {}, height: 100, isAction: true, - imageTypes: ["PNG", "JPEG", "SVG"], - layouts: ["Default"], + imageTypes: ["PNG", "SVG"], + layouts: ["Layout 1", "Layout 2"], projectlogo: null, profileNames: [], scaleFactor: 2, @@ -35,4 +35,7 @@ Default.args = { title: "Download", values: [], view: null, + sx: { + width: 200, + }, }; diff --git a/apps/uibook/stories/hurumap/core/IndicatorTitle.stories.js b/apps/uibook/stories/hurumap/core/IndicatorTitle.stories.js new file mode 100644 index 000000000..7a40aac8c --- /dev/null +++ b/apps/uibook/stories/hurumap/core/IndicatorTitle.stories.js @@ -0,0 +1,47 @@ +import { IndicatorTitle } from "@hurumap/core"; +import DownloadIcon from "@mui/icons-material/Download"; +import InfoIcon from "@mui/icons-material/Info"; +import ShareIcon from "@mui/icons-material/Share"; +import React from "react"; + +export default { + title: "@hurumap/core/IndicatorTitle", + component: IndicatorTitle, +}; + +function Template(args) { + return ; +} + +export const Default = Template.bind({}); + +Default.args = { + children: Area of agricultural land in hectares, + description: "Area of agricultural land by main purpose is in Hectares.", + disableToggle: false, + title: "Area of agricultural land in hectares", + view: {}, + actions: [ + { + id: "act-description", + title: "Description", + header: "Learn More", + children: Learn More, + icon: , + }, + { + id: "act-download", + title: "Download", + header: "Download", + children: Download, + icon: , + }, + { + id: "act-share", + title: "Share", + header: "Share", + children: Share, + icon: , + }, + ], +}; From 2901835a4e211d09b217236080aa4b50e8a49f46 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Mon, 5 Aug 2024 10:54:53 +0300 Subject: [PATCH 18/18] Remove unused file Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> --- packages/hurumap-core/src/utils/utils.js | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 packages/hurumap-core/src/utils/utils.js diff --git a/packages/hurumap-core/src/utils/utils.js b/packages/hurumap-core/src/utils/utils.js deleted file mode 100644 index be0107532..000000000 --- a/packages/hurumap-core/src/utils/utils.js +++ /dev/null @@ -1,8 +0,0 @@ -/* eslint-disable import/prefer-default-export */ -export function idify(string) { - return string - .replace(/^\s+|\s+$/g, "") - .replace(/[^a-z0-9]/g, "") - .replace(/\s+/g, "_") - .replace(/_+/g, "_"); -}