Nivo Pie Chart Not Rendering - javascript

I'm using the nivo charting library and am struggling to get my pie charts to render. I really don't understand why the pie chart isn't showing up.
Here is my core component code for the dashboard:
import React, { useState, useEffect } from "react";
import Amplify, { Storage } from "aws-amplify";
import Paper from "#material-ui/core/Paper";
import Box from "#material-ui/core/Box";
import Grid from "#material-ui/core/Grid";
import awsmobile from "./aws-exports";
import * as d3 from "d3";
import CircularProgress from "#material-ui/core/CircularProgress";
import MyResponsivePie from "./pieConfig";
import useStyles from "./useStyles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import IconButton from "#material-ui/core/IconButton";
import CloudDownloadIcon from "#material-ui/icons/CloudDownload";
import Typography from "#material-ui/core/Typography";
Amplify.configure(awsmobile);
Storage.configure({ level: "private" });
export default function Dashboard() {
useEffect(() => {
getFile();
}, []);
const classes = useStyles();
const [dashboard, showDashboard] = useState(false);
const [dashboardfile, setFile] = useState();
const getFile = async () => {
const url = await get_url().catch(err => getFile());
const file = await d3.csv(url);
if (file) {
console.log(file);
setFile(file);
showDashboard(true);
}
};
const get_url = () => {
var url = Storage.get("output.csv", { level: "private" }, { expires: 60 });
console.log(url);
return url;
};
const countColumnValues = (file, column) => {
var data_count = d3
.nest()
.key(function(d) {
return d[column];
})
.rollup(function(leaves) {
return leaves.length;
})
.entries(file);
console.log(data_count);
return data_count;
};
const generatePie = (file, column) => {
var data = countColumnValues(file, column);
return data;
};
return (
<Box className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
>
<CloudDownloadIcon onClick={get_url}></CloudDownloadIcon>
</IconButton>
<Typography variant="h6" className={classes.title}>
Atreides Controls NLP Dashboard
</Typography>
</Toolbar>
</AppBar>
{dashboard === false && (
<div className={classes.circle}>
<CircularProgress />
</div>
)}
{dashboard && (
<div className={classes.root}>
<Grid container direction="row" space={3}>
<Grid item xs>
<Paper className={classes.paper}>
<div className={classes.pie}>
<MyResponsivePie
id="contains_who_pie"
data={generatePie(dashboardfile, "contains_whos")}
/>{" "}
</div>
</Paper>
</Grid>
<Grid item xs>
<Paper className={classes.paper}>
<div className={classes.pie}>
<MyResponsivePie
id="contains_what_pie"
data={generatePie(dashboardfile, "contains_whats")}
/>
</div>
</Paper>
</Grid>
<Grid item xs>
<Paper className={classes.paper}>
<div className={classes.pie}>
<MyResponsivePie
id="contains_how_pie"
data={generatePie(dashboardfile, "contains_hows")}
/>
</div>
</Paper>
</Grid>
</Grid>
<Grid container direction="row" space={3}>
<Grid item xs>
<Paper className={classes.paper}>
<div className={classes.pie}>
<MyResponsivePie
id="multiple_who_pie"
data={generatePie(dashboardfile, "multiple_whos")}
/>
</div>
</Paper>
</Grid>
<Grid item xs>
<Paper className={classes.paper}>
<div className={classes.pie}>
<MyResponsivePie
id="multiple_what_pie"
data={generatePie(dashboardfile, "multiple_whats")}
/>{" "}
</div>
</Paper>
</Grid>
<Grid item xs>
<Paper className={classes.paper}>
<div className={classes.pie}>
<MyResponsivePie
id="multiple_how_pie"
data={generatePie(dashboardfile, "multiple_hows")}
/>
</div>
</Paper>
</Grid>
</Grid>
<Grid container direction="row" space={3}>
<Grid item xs>
<Paper className={classes.paper}>
<div className={classes.pie}>
<MyResponsivePie
id="risk_relevance_pie"
data={generatePie(
dashboardfile,
"control_relevance_to_risk"
)}
/>
</div>
</Paper>
</Grid>
<Grid item xs>
<Paper className={classes.paper}>
<div className={classes.pie}>
<MyResponsivePie
id="automated_manual_pie"
data={generatePie(dashboardfile, "")}
/>
</div>
</Paper>
</Grid>
<Grid item xs>
<Paper className={classes.paper}>
<div className={classes.pie}>
<MyResponsivePie
id="preventative_detective_pie"
data={generatePie(dashboardfile, "")}
/>
</div>
</Paper>
</Grid>
</Grid>
</div>
)}
</Box>
);
}
The pie chart component is configured using this component that I am importing:
import React from "react";
import { ResponsivePie } from "#nivo/pie";
const MyResponsivePie = ({ data }) => (
<ResponsivePie
data={data}
margin={{ top: 40, right: 80, bottom: 80, left: 80 }}
startAngle={-180}
innerRadius={0.5}
padAngle={0.7}
cornerRadius={3}
colors={{ scheme: "nivo" }}
borderWidth={1}
borderColor={{ theme: "grid.line.stroke" }}
radialLabelsSkipAngle={10}
radialLabelsTextXOffset={6}
radialLabelsTextColor="#333333"
radialLabelsLinkOffset={0}
radialLabelsLinkDiagonalLength={16}
radialLabelsLinkHorizontalLength={24}
radialLabelsLinkStrokeWidth={3}
radialLabelsLinkColor={{ from: "color", modifiers: [] }}
slicesLabelsSkipAngle={10}
slicesLabelsTextColor="#333333"
animate={true}
motionStiffness={90}
motionDamping={15}
legends={[
{
anchor: "bottom",
direction: "row",
translateY: 56,
itemWidth: 100,
itemHeight: 18,
itemTextColor: "#999",
symbolSize: 18,
symbolShape: "circle",
effects: [
{
on: "hover",
style: {
itemTextColor: "#000"
}
}
]
}
]}
/>
);
export default MyResponsivePie;
and my styles file looks like this
import { green } from "#material-ui/core/colors";
import { makeStyles } from "#material-ui/core/styles";
import { forceCenter } from "d3";
const useStyles = makeStyles(theme => ({
root: {
height: "100vh"
},
success: {
backgroundColor: green[600]
},
error: {
backgroundColor: theme.palette.error.dark
},
icon: {
fontSize: 20
},
iconVariant: {
opacity: 0.9,
marginRight: theme.spacing(1)
},
message: {
display: "flex",
alignItems: "center"
},
image: {
backgroundImage: "url(https://source.unsplash.com/8WFnEehJWso)",
backgroundRepeat: "no-repeat",
backgroundColor:
theme.palette.type === "dark"
? theme.palette.grey[900]
: theme.palette.grey[50],
backgroundSize: "cover",
backgroundPosition: "center"
},
paper: {
margin: theme.spacing(1.5, 3),
display: "flex",
flexDirection: "column",
alignItems: "center"
},
form: {
width: "100%", // Fix IE 11 issue.
marginTop: theme.spacing(1)
},
submit: {
margin: theme.spacing(3, 0, 2)
},
card: {
maxWidth: 600
},
media: {
height: 500
},
circle: {
display: "flex",
"& > * + *": {
marginLeft: theme.spacing(2)
}
},
menuButton: {
marginRight: theme.spacing(2)
},
title: {
flexGrow: 1,
alignContent: "center"
},
pie: {
height: 250
}
}));
export default useStyles;
Lastly an example of my data that is coming back from the generate pie function is like this:
[
{key: "True", value: 7981},
{key: "False", value: 950}
]

The issue I had was rather daft, the container object did not have a specified size.

Related

How to create new components on every button click in "React"

So I want when the user clicks on the button, be able to create new CatagoryField Component that I made. When I place the component in a function and call it it will only create the component once. I will appreciate some help. I'm confused about how should I implement this?
App components
import React, { useState } from "react";
import {
Accordion,
AccordionSummary,
Chip,
Button,
IconButton,
Autocomplete,
TextField,
} from "#mui/material";
import { Grid } from "#mui/material";
import SearchBar from "material-ui-search-bar";
import DeleteIcon from "#mui/icons-material/Delete";
import ExpandMoreOutlinedIcon from "#mui/icons-material/ExpandMoreOutlined";
import AddCircleOutlineOutlinedIcon from "#mui/icons-material/AddCircleOutlineOutlined";
import HelpIcon from "#mui/icons-material/Help";
import HistoryToggleOffIcon from "#mui/icons-material/HistoryToggleOff";
import AllMembers from "./components/common/main/allMembers";
import CatagoryField from "./components/common/main/catagoryField";
const autoCompleteOptions = [
{ title: "A", year: 1994 },
{ title: "B", year: 1972 },
{ title: "C", year: 1974 },
{ title: "D", year: 2008 },
{ title: "E", year: 1957 },
{ title: "F", year: 1993 },
{ title: "G", year: 1994 },
];
const App = () => {
const [value, setValue] = useState();
const [element, setElement] = useState(0);
const doSomethingWith = () => {
return null;
};
let i = 0;
const creator = () => {
while (i < element) {
i++;
return (
<CatagoryField
catagoryName="خدماتی"
react="از آنها چیزی میخریم"
createdBy="سیستم"
disable={false}
/>
);
}
};
console.log(element);
return (
<>
<div style={{ margin: "4rem 1rem" }}>
<Accordion>
<AccordionSummary
sx={{ height: "65px" }}
aria-controls="panel1a-content"
>
<Grid
container
direction="row"
justifyContent="space-between"
alignItems="center"
>
<Grid item>
<IconButton className="chevron__icon">
<ExpandMoreOutlinedIcon />
</IconButton>
<span className="users__catagory"> دسته بندی کاربران</span>
</Grid>
<Grid item>
<IconButton>
<HistoryToggleOffIcon />
</IconButton>
<IconButton>
<HelpIcon className="help" />
</IconButton>
<span className="version">4.3.2</span>
</Grid>
</Grid>
</AccordionSummary>
<AccordionSummary
sx={{
height: "65px",
padding: "30px",
background: "#E6E6E6",
cursor: "default !important",
}}
aria-controls="panel1a-content"
>
<Grid
container
direction="row"
alignItems="center"
sx={{ display: "relative" }}
>
<Grid item>
<Button
variant="outlined"
sx={{ height: "50px" }}
size="medium"
onClick={() => setElement(element + 1)}
endIcon={
<AddCircleOutlineOutlinedIcon
sx={{ marginRight: "10px" }}
/>
}
>
افزودن دسته جدید
</Button>
</Grid>
<Grid sx={{ width: "207px" }} item>
<SearchBar
className="search__holder"
placeholder="جستجو..."
value={value}
style={{ width: "207px", height: "45px" }}
onChange={(newValue) => setValue(newValue)}
onRequestSearch={() => doSomethingWith()}
/>
</Grid>
<Grid className="sort__field" item>
<Autocomplete
sx={{
width: "207px !important",
padding: "0 !important",
backgroundColor: "white !important",
}}
options={autoCompleteOptions}
getOptionLabel={(option) => option.title}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
variant="outlined"
label={option.title}
{...getTagProps({ index })}
/>
))
}
renderInput={(params) => (
<TextField
{...params}
variant="filled"
sx={{
width: "207px !important",
padding: "0 !important",
background: "white !important",
}}
placeholder="مرتب سازی..."
/>
)}
/>
</Grid>
<Grid item>
<IconButton sx={{ margin: "0 5px" }}>
<DeleteIcon />
</IconButton>
</Grid>
<Grid item className="last__edit">
<Grid item>
<span>
آخرین ویرایش:
<a className="last_Modified" href="#">
سیستم
</a>
</span>
<span>1405/12/24 23:59 </span>
</Grid>
</Grid>
</Grid>
</AccordionSummary>
<AllMembers />
<CatagoryField
catagoryName="اپراتور سیستم"
react="اپراتور سیستم"
createdBy="سیستم"
/>
<CatagoryField
catagoryName="مشتریان"
react="به آنها چیزی فروخته ایم"
createdBy="سیستم"
/>
<CatagoryField
catagoryName="خدماتی"
react="از آنها چیزی میخریم"
createdBy="سیستم"
disable={false}
/>
{creator()}
</Accordion>
</div>
</>
);
};
export default App;
The best way in order to achieve the solution is to use a state with useMemo.and the problem with your code is that the creator acts as a function and it will only execute once try this.
import {useMemo} from 'react';
const App = () => {
const [elements , setElements] = useState(0);
const creator = useMemo(() => {
return (
<>
{Array(elements).fill(elements).map((item , index) => (
<CategoryField
key={`cat-${index}`} // key is need when mapping! it is not props
catagoryName="خدماتی"
react="از آنها چیزی میخریم"
createdBy="سیستم"
disable={false}
/>
))}
</>
)
},[elements]);//render when elements change
return (
<>
<div style={{ margin: "4rem 1rem" }}>
<Accordion>
<AccordionSummary
sx={{ height: "65px" }}
aria-controls="panel1a-content"
>
<Grid
container
direction="row"
justifyContent="space-between"
alignItems="center"
>
<Grid item>
<IconButton className="chevron__icon">
<ExpandMoreOutlinedIcon />
</IconButton>
<span className="users__catagory"> دسته بندی کاربران</span>
</Grid>
<Grid item>
<IconButton>
<HistoryToggleOffIcon />
</IconButton>
<IconButton>
<HelpIcon className="help" />
</IconButton>
<span className="version">4.3.2</span>
</Grid>
</Grid>
</AccordionSummary>
<AccordionSummary
sx={{
height: "65px",
padding: "30px",
background: "#E6E6E6",
cursor: "default !important",
}}
aria-controls="panel1a-content"
>
<Grid
container
direction="row"
alignItems="center"
sx={{ display: "relative" }}
>
<Grid item>
<Button
variant="outlined"
sx={{ height: "50px" }}
size="medium"
onClick={() => setElements(elements + 1)}
endIcon={
<AddCircleOutlineOutlinedIcon
sx={{ marginRight: "10px" }}
/>
}
>
افزودن دسته جدید
</Button>
</Grid>
<Grid sx={{ width: "207px" }} item>
<SearchBar
className="search__holder"
placeholder="جستجو..."
value={value}
style={{ width: "207px", height: "45px" }}
onChange={(newValue) => setValue(newValue)}
onRequestSearch={() => doSomethingWith()}
/>
</Grid>
<Grid className="sort__field" item>
<Autocomplete
sx={{
width: "207px !important",
padding: "0 !important",
backgroundColor: "white !important",
}}
options={autoCompleteOptions}
getOptionLabel={(option) => option.title}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
key={`chip-${index}`}
variant="outlined"
label={option.title}
{...getTagProps({ index })}
/>
))
}
renderInput={(params) => (
<TextField
{...params}
variant="filled"
sx={{
width: "207px !important",
padding: "0 !important",
background: "white !important",
}}
placeholder="مرتب سازی..."
/>
)}
/>
</Grid>
<Grid item>
<IconButton sx={{ margin: "0 5px" }}>
<DeleteIcon />
</IconButton>
</Grid>
<Grid item className="last__edit">
<Grid item>
<span>
آخرین ویرایش:
<a className="last_Modified" href="#">
سیستم
</a>
</span>
<span>1405/12/24 23:59 </span>
</Grid>
</Grid>
</Grid>
</AccordionSummary>
<AllMembers />
<CatagoryField
catagoryName="اپراتور سیستم"
react="اپراتور سیستم"
createdBy="سیستم"
/>
<CatagoryField
catagoryName="مشتریان"
react="به آنها چیزی فروخته ایم"
createdBy="سیستم"
/>
<CatagoryField
catagoryName="خدماتی"
react="از آنها چیزی میخریم"
createdBy="سیستم"
disable={false}
/>
{creator}
</Accordion>
</div>
</>
);
}
export default App;

How to change the position of a grid item left and right in a map() function

I have a page containing a "Timeline" element from Material Ui, with an "alternate" alignment. So I have a "TimeLineContent" containing several elements: Paper, Typography (For title and description) and an image.
I want to make the text always towards the center of the timeline. That is to say, one time the text is to the left, another to the right ...
Here an example of my problem :
The first TimelineContent is good (Text is to the left)
The second one is not good (Text is not to the right)
I could have used a flex-direction : reverse-row but I have several TimelineContent like this which are created with a .map()
Here the code I have right now :
<Timeline align="alternate">
{result.map((index) => {
return (
<TimelineItem className={classes.timelineStyle}>
<TimelineOppositeContent>
<Typography variant="body2" color="textSecondary">
{index.sif_date}
</Typography>
</TimelineOppositeContent>
<TimelineSeparator>
<TimelineDot className={classes.dot}>
<LaptopMacIcon/>
</TimelineDot>
<TimelineConnector />
</TimelineSeparator>
<TimelineContent>
<Paper elevation={3} className={classes.paper}>
<Grid style={{display: 'flex', flexWrap: 'nowrap'}}>
<Grid item>
<Typography variant="h6" component="h1">
{index.sif_titre}
</Typography>
<Typography style={{fontSize: 'smaller'}}>
{index.sif_msg}
</Typography>
</Grid>
<Grid item>
<Zoom overlayBgColorStart='rgba(73, 80, 87, 67)' overlayBgColorEnd='rgba(73, 80, 87, 67)' zoomMargin={100}>
<img src={index.sif_image} alt={index.sif_image} className={classes.img} style={{maxWidth: 200, maxHeight: 200}}/>
</Zoom>
</Grid>
</Grid>
</Paper>
</TimelineContent>
</TimelineItem>
)
})
}
</Timeline>
const useStyles = makeStyles((theme) => ({
paper: {
padding: '6px 16px',
textAlign: 'center',
backgroundColor: 'white !important',
display: 'flex'
},
secondaryTail: {
backgroundColor: theme.palette.secondary.main,
},
img : {
flex: 1,
resizeMode: 'contain',
},
dot : {
backgroundColor: '#ef9700'
},
timelineStyle: {
padding: '0px 300px !important'
}
}));
EDIT :
Full code of my page :
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Timeline from '#material-ui/lab/Timeline';
import TimelineItem from '#material-ui/lab/TimelineItem';
import TimelineSeparator from '#material-ui/lab/TimelineSeparator';
import TimelineConnector from '#material-ui/lab/TimelineConnector';
import TimelineContent from '#material-ui/lab/TimelineContent';
import TimelineOppositeContent from '#material-ui/lab/TimelineOppositeContent';
import TimelineDot from '#material-ui/lab/TimelineDot';
import {Grid} from "#material-ui/core";
import LaptopMacIcon from '#material-ui/icons/LaptopMac';
import Paper from '#material-ui/core/Paper';
import Typography from '#material-ui/core/Typography';
import {useEffect, useState} from "react";
import {data} from './data.json';
import axios from 'axios';
import Zoom from 'react-medium-image-zoom';
import 'react-medium-image-zoom/dist/styles.css';
const useStyles = makeStyles((theme) => ({
paper: {
padding: '6px 16px',
textAlign: 'center',
backgroundColor: 'white !important',
display: 'flex'
},
secondaryTail: {
backgroundColor: theme.palette.secondary.main,
},
img : {
flex: 1,
resizeMode: 'contain',
},
dot : {
backgroundColor: '#ef9700'
},
timelineStyle: {
padding: '0px 300px !important'
},
Grid: {
display: 'flex',
flexWrap: 'nowrap',
flexDirection: 'row',
'&:nth-child(2n+1)': {
flexDirection: 'row-reverse',
}
}
}));
const index = () =>{
const [result, setResult] = useState([]);
useEffect(()=>{
axios.get('/api/timeLine_siinfra').then((response) => {
setResult(response.data)
});
}, []);
const classes = useStyles();
return (
<Timeline align="alternate">
{result.map((index) => {
return (
<TimelineItem className={classes.timelineStyle}>
<TimelineOppositeContent>
<Typography variant="body2" color="textSecondary">
{index.sif_date}
</Typography>
</TimelineOppositeContent>
<TimelineSeparator>
<TimelineDot className={classes.dot}>
<LaptopMacIcon/>
</TimelineDot>
<TimelineConnector />
</TimelineSeparator>
<TimelineContent>
<Paper elevation={3} className={classes.paper}>
<Grid container className={classes.Grid}>
<Grid item>
<Typography variant="h6" component="h1">
{index.sif_titre}
</Typography>
<Typography style={{fontSize: 'smaller'}}>
{index.sif_msg}
</Typography>
</Grid>
<Grid item>
<Zoom overlayBgColorStart='rgba(73, 80, 87, 67)' overlayBgColorEnd='rgba(73, 80, 87, 67)' zoomMargin={100}>
<img src={index.sif_image} alt={index.sif_image} className={classes.img} style={{maxWidth: 200, maxHeight: 200}}/>
</Zoom>
</Grid>
</Grid>
</Paper>
</TimelineContent>
</TimelineItem>
)
})
}
</Timeline>
)}
export default index;
You can do that with an nth-child selector in CSS and then toggle between your styles / flex direction.
Docs for the nth-child selector: https://developer.mozilla.org/de/docs/Web/CSS/:nth-child
.parent{
display: flex;
flex-directrion: row;
}
.parent:nth-child(2n+1){ /* or: :nth-child(odd) */
flex-direction: row-reverse;
}
<div class="parent">
<div class="img">IMG</div>
<div class="txt">txt</div>
</div>
<div class="parent">
<div class="img">IMG</div>
<div class="txt">txt</div>
</div>
<div class="parent">
<div class="img">IMG</div>
<div class="txt">txt</div>
</div>
<div class="parent">
<div class="img">IMG</div>
<div class="txt">txt</div>
</div>
I would use a modulo to determine if we're on an even or odd iteration, and adjust accordingly. I've also set the title component as a variable so we don't have to duplicate it:
{result.map((index, i) => {
let isEven = i % 2 === 0,
titleComponent = (
<Grid item>
<Typography variant="h6" component="h1">
{index.sif_titre}
</Typography>
<Typography style={{fontSize: 'smaller'}}>
{index.sif_msg}
</Typography>
</Grid>
);
return (
<TimelineItem className={classes.timelineStyle}>
<TimelineOppositeContent>
<Typography variant="body2" color="textSecondary">
{index.sif_date}
</Typography>
</TimelineOppositeContent>
<TimelineSeparator>
<TimelineDot className={classes.dot}>
<LaptopMacIcon/>
</TimelineDot>
<TimelineConnector />
</TimelineSeparator>
<TimelineContent>
<Paper elevation={3} className={classes.paper}>
<Grid style={{display: 'flex', flexWrap: 'nowrap'}}>
{isEven && titleComponent}
<Grid item>
<Zoom overlayBgColorStart='rgba(73, 80, 87, 67)' overlayBgColorEnd='rgba(73, 80, 87, 67)' zoomMargin={100}>
<img src={index.sif_image} alt={index.sif_image} className={classes.img} style={{maxWidth: 200, maxHeight: 200}}/>
</Zoom>
</Grid>
{!isEven && titleComponent}
</Grid>
</Paper>
</TimelineContent>
</TimelineItem>
)
})}
Modulo example:
https://jsfiddle.net/q12yah85/
const MuiTimelineItem = withStyles({
alignAlternate: {
"&:nth-child(even) .MuiTimelineItem-content": {
direction: "rtl"
}
}
})(TimelineItem);

I can't placse new grid in the new line

I am trying to create a page that contains a list of cards. I designed the Header of the page but as a beginner, but I created it in my own way.
Problem is that when I am trying to display the card in the new Grid container its will not showing the desired result.
Here the Image with the head I created
Here the I the problem picture when I try to put Grid container
My Style and Code :
import { AppBar, Avatar, Button, Card, CardActionArea, CardActions, CardContent, CardMedia, Grid, IconButton, makeStyles, Toolbar, Typography } from '#material-ui/core';
import React from 'react';
import MenuIcon from '#material-ui/icons/Menu';
import { Link } from 'react-router-dom';
const useStyles = makeStyles((theme) => ({
blackBox: {
backgroundColor: 'black',
height: '350px'
},
AppBar: {
'&.MuiAppBar-positionFixed': {
top: '60px',
right: '126px',
'#media (max-width: 576px)': {
right: '42px'
}
},
width: '85%',
},
large: {
width: theme.spacing(10),
height: theme.spacing(10),
},
link: {
color: 'white',
textDecoration: 'none',
marginLeft: '30px',
fontFamily: 'Times new roman'
},
headText: {
marginTop: '130px',
'#media (max-width: 576px)': {
marginTop: '170px',
}
},
title: {
color: 'white',
'#media (max-width: 576px)': {
fontSize: '30px'
}
},
titleDesc: {
color: 'white',
'#media (max-width: 576px)': {
width: '235px'
}
}
}))
export default function CoursesView() {
const classes = useStyles();
return (
<>
<Grid container
direction="column"
// justify="space-evenly"
alignItems="center"
className={classes.blackBox}
>
<Grid item >
<AppBar className={classes.AppBar} color='transparent'>
<Toolbar>
{/* <IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
<MenuIcon />
</IconButton> */}
<div style={{ flexGrow: '1' }}>
<Avatar alt="Remy Sharp" src="https://seeklogo.com/images/F/forex-logo-6B4D0AB43E-seeklogo.com.png" className={classes.large} />
</div>
<Link to='/play' className={classes.link}>Home</Link>
<Link to='/play' className={classes.link}>Courses</Link>
<Link to='/play' className={classes.link}>The Trade Signal</Link>
<Link to='/play' className={classes.link}>About</Link>
<Link to='/play' className={classes.link}>My Account</Link>
<Link to='/play' className={classes.link}>My Crat</Link>
</Toolbar>
</AppBar>
</Grid>
<Grid item container className={classes.headText} direction="column"
justify="center"
alignItems="center">
<Typography variant="h2" className={classes.title}>
Courses
</Typography>
<Typography variant="p" className={classes.titleDesc}>
our uniqly designed courses will help you in your specific areas of needs
</Typography>
</Grid>
</Grid>
<Grid container>
<h1>The cards wil display Here</h1>
</Grid>
</>
)
}
enter code here
The main app file that renders this app
import React from "react";
import CourseListView from "./components/pages/CourseListView";
import VideoPlayView from "./components/pages/VideoPlayView";
import { Route, Switch } from "react-router-dom";
import { makeStyles, ThemeProvider } from "#material-ui/core/styles";
import { createMuiTheme } from '#material-ui/core';
import CoursesView from "./components/pages/CoursesView";
const useStyles = makeStyles({
container: {
display: "flex"
}
});
const theme = createMuiTheme({
palette: {
primary: {
main: "#333996",
light: "#3c44b126"
},
secondary: {
main: "#f83245",
light: "#f8324526"
},
background: {
default: "#f4f5fd"
},
},
overrides: {
MuiAppBar: {
root: {
transform: 'translateZ(0)',
}
}
}
})
export default function App() {
const classes = useStyles();
return (
<ThemeProvider theme={theme}>
<div className={classes.container}>
<Switch>
<Route exact from="/" render={props => <CourseListView {...props} />} />
<Route exact from="/play" render={props => <VideoPlayView {...props} />} />
<Route exact from="/Home" render={props => <CoursesView {...props} />} />
</Switch>
</div>
</ThemeProvider>
);
}
try this :
container: {
display: "flex",
flexDirection: column
}

Server Error ReferenceError: window is not defined This error happened while generating the page

I want to add Microsoft Login Button in Next Js using material Ui but
when I add package from NPM and refresh the page I got the above
error.
When I Assign ClientId="a973536f-eb3e-4fd9-9394-9f4194d69153" to Microsoft component as shown below I got the above error. How to cope with this error.
import React from "react";
import { Grid, Container, Checkbox, IconButton, FormControlLabel, TextField, Button, Link } from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
import Icon from "#material-ui/core/Icon";
import { loadCSS } from "fg-loadcss";
import FacebookLogin from "react-facebook-login/dist/facebook-login-render-props";
import { GoogleLogin } from "react-google-login";
import MicrosoftLogin from "react-microsoft-login";
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(0),
display: "flex",
flexDirection: "column",
alignItems: "center",
height: '60vh',
},
background: {
backgroundColor: "#220E1A",
borderRadius: "5px",
color: "white",import React from "react";
import { Grid, Container, Checkbox, IconButton, FormControlLabel, TextField, Button, Link } from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
import Icon from "#material-ui/core/Icon";
import { loadCSS } from "fg-loadcss";
import FacebookLogin from "react-facebook-login/dist/facebook-login-render-props";
import { GoogleLogin } from "react-google-login";
import MicrosoftLogin from "react-microsoft-login";
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(0),
display: "flex",
flexDirection: "column",
alignItems: "center",
height: '60vh',
},
background: {
backgroundColor: "#220E1A",
borderRadius: "5px",
color: "white",
},
form: {
width: "70%", // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
input1: {
background: "white",
borderRadius: "25px",
color: "white",
},
submit: {
margin: theme.spacing(1, 0, 1),
borderRadius: "25px",
},
buttonGroup: {
borderRadius: "50px",
margin: theme.spacing(2, 0, 2, 0),
},
winIcon: {
padding: '0px',
margin: '0px',
width: '10px'
}
}));
export default function SignIn() {
const classes = useStyles();
//Load Fonts awesome icons
React.useEffect(() => {
const node = loadCSS(
"https://use.fontawesome.com/releases/v5.12.0/css/all.css",
document.querySelector("#font-awesome-css")
);
return () => {
node.parentNode.removeChild(node);
};
}, []);
//google facebook,Microsoft Login response
const responseFacebook = (response) => {
console.log(response);
};
const responseGoogle = (response) => {
console.log(response);
};
const authHandler = (err, data) => {
console.log(err, data);
};
return (
<Container maxWidth="xm" className={classes.background}>
<div className={classes.paper}>
<form className={classes.form} noValidate>
<TextField
className={classes.input1}
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoFocus
variant="filled"
/>
<TextField
className={classes.input1}
variant="filled"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<Grid
container
direction="column"
justify="center"
alignItems="center"
>
<Grid item >
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Stay signed in"
/>
</Grid>
<Grid item>
<Button
type="submit"
medium
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
</Grid>
<Grid item>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<h3 align="center">Or Via</h3>{" "}
<FacebookLogin
appId="225241158739281"
autoLoad
callback={responseFacebook}
render={(renderProps) => (
<IconButton color="primary" onClick={renderProps.onClick}>
<Icon className="fab fa-facebook" />
</IconButton>
)}
/>
<GoogleLogin
clientId="500452257814-peb71oi9612hv04svvfpvfrtch6pc5br.apps.googleusercontent.com"
render={(renderProps) => (
<IconButton
onClick={renderProps.onClick}
>
{" "}
<Icon className="fab fa-google" color="primary" />
</IconButton>
)}
buttonText="Login"
onSuccess={responseGoogle}
onFailure={responseGoogle}
cookiePolicy={"single_host_origin"}
/>
//**Problem is here IN MicrosoftLogin when i assign Id it creates the above error.**
<MicrosoftLogin
// clientId="a973536f-eb3e-4fd9-9394-9f4194d69153"
authCallback={authHandler}
redirectUri="https://localhost:3000/"
className={classes.winIcon}
children={
<IconButton>
<Icon className="fab fa-windows" color="primary" />
</IconButton>}
/>
</Grid>
</Grid>
</form>
</div>
</Container>
);
}
},
form: {
width: "70%", // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
input1: {
background: "white",
borderRadius: "25px",
color: "white",
},
submit: {
margin: theme.spacing(1, 0, 1),
borderRadius: "25px",
},
buttonGroup: {
borderRadius: "50px",
margin: theme.spacing(2, 0, 2, 0),
},
winIcon: {
padding: '0px',
margin: '0px',
width: '10px'
}
}));
export default function SignIn() {
const classes = useStyles();
//Load Fonts awesome icons
React.useEffect(() => {
const node = loadCSS(
"https://use.fontawesome.com/releases/v5.12.0/css/all.css",
document.querySelector("#font-awesome-css")
);
return () => {
node.parentNode.removeChild(node);
};
}, []);
//google facebook,Microsoft Login response
const responseFacebook = (response) => {
console.log(response);
};
const responseGoogle = (response) => {
console.log(response);
};
const authHandler = (err, data) => {
console.log(err, data);
};
return (
<Container maxWidth="xm" className={classes.background}>
<div className={classes.paper}>
<form className={classes.form} noValidate>
<TextField
className={classes.input1}
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoFocus
variant="filled"
/>
<TextField
className={classes.input1}
variant="filled"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<Grid
container
direction="column"
justify="center"
alignItems="center"
>
<Grid item >
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Stay signed in"
/>
</Grid>
<Grid item>
<Button
type="submit"
medium
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
</Grid>
<Grid item>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<h3 align="center">Or Via</h3>{" "}
<FacebookLogin
appId="225241158739281"
autoLoad
callback={responseFacebook}
render={(renderProps) => (
<IconButton color="primary" onClick={renderProps.onClick}>
<Icon className="fab fa-facebook" />
</IconButton>
)}
/>
<GoogleLogin
clientId="500452257814-peb71oi9612hv04svvfpvfrtch6pc5br.apps.googleusercontent.com"
render={(renderProps) => (
<IconButton
onClick={renderProps.onClick}
>
{" "}
<Icon className="fab fa-google" color="primary" />
</IconButton>
)}
buttonText="Login"
onSuccess={responseGoogle}
onFailure={responseGoogle}
cookiePolicy={"single_host_origin"}
/>
//**Problem is here IN MicrosoftLogin when i assign Id it creates the above error.**
<MicrosoftLogin
// clientId="a973536f-eb3e-4fd9-9394-9f4194d69153"
authCallback={authHandler}
redirectUri="https://localhost:3000/"
className={classes.winIcon}
children={
<IconButton>
<Icon className="fab fa-windows" color="primary" />
</IconButton>}
/>
</Grid>
</Grid>
</form>
</div>
</Container>
);
}
It's related to server side rendering and client side rendering.
As Next.js provides SSR, you need to consider using objects like window, localStorage and so on. While compiling client side, those objects are fine but when Nextjs compiles server side, it shows error like you shared.
It seems like GoogleLogin uses window object if you assign the client id. You need to check that first. And lemme know the result.
Hey the easy way for Material UI Components, to rendered it on Next js framework.Just use component to render it on client side only.
(If any component use Window object on server side it will show this error)
solution:
import NoSsr from '#material-ui/core/NoSsr';
<NoSsr>
<MicrosoftLogin
clientId="a973536f-eb3e-4fd9-9394-9f4194d69153"
authCallback={authHandler}
redirectUri="https://localhost:3000/"
className={classes.winIcon}
children={
<IconButton>
<Icon className="fab fa-windows" color="primary" />
</IconButton>
}
/>
</NoSsr>

Is there a way to show a Material-UI Drawer nested inside a Grid component?

I'm creating a web application using Material-UI. The main page is divided in 3 grids, each with a height of 500px. I wanted to display a drawer with some options of actions inside the middle grid. Is that possible? The way I have it so far I can only display it in relation to the whole screen.
Here's my main component with the grid elements:
import React, { Fragment } from 'react';
import Grid from '#material-ui/core/Grid';
import Paper from '#material-ui/core/Paper';
const style = {
Paper: {
padding: 10,
marginTop: 5,
marginBottom: 5,
height: 500,
overflowY: 'auto',
position: 'relative',
},
Fab: {
position: 'absolute',
top: 5,
left: 5
},
}
export default () => {
return (
<Fragment>
<Grid container spacing={1}>
<Grid item xs={12} sm={4} md={4} lg={2}>
<Paper style={style.Paper}>
</Paper>
</Grid>
<Grid item xs={12} sm={8} md={8} lg={4}>
<Paper style={style.Paper}>
<ToolbarDrawer />
</Paper>
</Grid>
<Grid item xs={12} sm={12} md={12} lg={6}>
<Paper style={style.Paper}>
</Paper>
</Grid>
</Grid>
</Fragment>
);
}
Here's my drawer component which I would like to be displayed nested inside the middle grid:
javascript
import React, { Fragment } from 'react';
import IconButton from '#material-ui/core/IconButton';
import ChevronRightIcon from '#material-ui/icons/ChevronRight';
import ChevronLeftIcon from '#material-ui/icons/ChevronLeft';
import InboxIcon from '#material-ui/icons/MoveToInbox';
import MailIcon from '#material-ui/icons/Mail';
import { makeStyles } from '#material-ui/core/styles';
import clsx from 'clsx';
import Drawer from '#material-ui/core/Drawer';
import Divider from '#material-ui/core/Divider';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import List from '#material-ui/core/List';
import CssBaseline from '#material-ui/core/CssBaseline';
const drawerWidth = 240;
const useStyles = makeStyles(theme => ({
drawer: {
width: drawerWidth,
flexShrink: 0,
whiteSpace: 'nowrap',
},
drawerOpen: {
width: drawerWidth,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
drawerClose: {
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: 'hidden',
width: theme.spacing(6) + 1,
[theme.breakpoints.up('sm')]: {
width: theme.spacing(7) + 1,
},
},
toolbar: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: theme.spacing(0, 1),
...theme.mixins.toolbar,
}
}));
export default () => {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
function handleToolbarClose() {
setOpen(!open);
}
return (
<Fragment>
<CssBaseline />
<Drawer
anchor="right"
variant="permanent"
className={clsx(classes.drawer, {
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
})}
classes={{
paper: clsx({
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
}),
}}
open={open}
>
<div className={classes.toolbar}>
<IconButton onClick={handleToolbarClose}>
{(open) ? <ChevronRightIcon /> : <ChevronLeftIcon />}
</IconButton>
</div>
<Divider />
<List>
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
<List>
{['All mail', 'Trash', 'Spam'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</Drawer>
</Fragment>
)
}
It looks like you're going to have to build a makeshift drawer component for this. Here is an example you could use to get started:
Live demo can be found here
MakeshiftDrawer using List component and Slide transition component:
export default function MakeshiftDrawer({ open }) {
const classes = useStyles();
const [selectedIndex, setSelectedIndex] = React.useState(1);
function handleListItemClick(event, index) {
setSelectedIndex(index);
}
return (
<Slide direction="right" in={open} mountOnEnter unmountOnExit>
<div className={classes.root}>
<List component="nav" aria-label="main mailbox folders">
<ListItem
button
selected={selectedIndex === 0}
onClick={event => handleListItemClick(event, 0)}
>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Inbox" />
</ListItem>
<ListItem
button
selected={selectedIndex === 1}
onClick={event => handleListItemClick(event, 1)}
>
<ListItemIcon>
<DraftsIcon />
</ListItemIcon>
<ListItemText primary="Drafts" />
</ListItem>
</List>
<Divider />
<List component="nav" aria-label="secondary mailbox folder">
<ListItem
button
selected={selectedIndex === 2}
onClick={event => handleListItemClick(event, 2)}
>
<ListItemText primary="Trash" />
</ListItem>
<ListItem
button
selected={selectedIndex === 3}
onClick={event => handleListItemClick(event, 3)}
>
<ListItemText primary="Spam" />
</ListItem>
</List>
</div>
</Slide>
);
}
MakeshiftDrawer in use:
function App() {
const [isOpen, setIsOpen] = useState(true);
const toggle = () => {
setIsOpen(!isOpen);
}
return (
<div>
<Grid container direction="row" style={topGridStyle}>
</Grid>
<Grid container direction="row" style={midGridStyle}>
<Grid item>
<Button variant="contained" color="primary" onClick={toggle}>Toggle</Button>
<MakeshiftDrawer open={isOpen} />
</Grid>
</Grid>
<Grid container direction="row" style={botGridStyle}>
</Grid>
</div>
);
}
Rendered:

Categories