Set timeout on material UI drawer when open - javascript

I would like to close the drawer after a specific time however I dont think material UI drawer has that kind of props. Is there a way to use transitionDuration to close the drawer or maybe add a setTimeout in my function ? When adding a timeout in my toggleDrawer function, it won't notice the timeout.
<Drawer
className="draww"
anchor={anchor}
open={state[anchor]}
transitionDuration={2000}
onClose={toggleDrawer(anchor, false)}
>
<div className="drawer-title">
<Link to="/">
<h2>NOW NOW</h2>
</Link>
</div>
<a className="cl" onClick={toggleDrawer(anchor, false)}>
×
</a>
{/* {list(anchor)} */}
<br />
<div className="cart-drawer">
<h4>YOUR SELECTION</h4>
<div className="border-cart"></div>
{cartItems.map((data) => (
<div className="row thiss">
<Link
to={{ pathname: `/product/${data._id}` }}
onClick={toggleDrawer(anchor, false)}
>
{data.product_image && (
<img
className="drawer-pic"
src={data.product_image.secure_url}
alt=""
/>
)}
</Link>
<div className="col info-vart">
<Link
to={{ pathname: `/product/${data._id}` }}
onClick={toggleDrawer(anchor, false)}
>
<h2>{data.product_name.slice(0, 12)}</h2>
<h5>Ref:{data.product_details[1].TAILLE}</h5>
<button
onClick={() => removeProduct(data)}
className="remove"
>
DELETE
</button>
</Link>
</div>
<h3>€{data.product_price}</h3>
</div>
))}
<div className="border-cart"></div>
<div className="draw-down">
<div className="row ">
<p className="sub">TOTAL</p>
<p className="sub total">{formatNumber(total)}</p>
</div>
<div className="centerthis">
<button
type="button"
onClick={someFunc}
className="checkoutt"
role="link"
>
CHECKOUT
</button>
<PayPalScriptProvider
options={{
"client-id":
"",
currency: "EUR",
}}
>
<div
className="paypalll"
style={{
minWidth: "280px",
maxWidth: "280px",
}}
>
<PayPalButtons
style={{
layout: "horizontal",
height: 45,
}}
createOrder={(data, actions) => {
return actions.order.create({
purchase_units: [
{
amount: {
value: total,
},
},
],
});
}}
/>
</div>
</PayPalScriptProvider>
</div>
</div>
<br />
</div>
<br />
</Drawer>
Toggle drawer function
const toggleDrawer = (anchor, open, data) => (event) => {
if (
event.type === "keydown" &&
(event.key === "Tab" || event.key === "Shift")
) {
return addProduct(data);
}
setState({ ...state, [anchor]: open });
};

You can use a useEffect hook to close drawer after a timeout.
const allAnchors = ['left', 'right', 'top', 'bottom'];
for(let anchor of allAnchors) {
useEffect(() => {
if (state[anchor]) {
setTimeout(() => {
toggleDrawer(anchor, false)()
}, 2000); // close after 2000ms
}
}, [state[anchor]]);
}
I saw you're using anchor variable, hinting that you might have multiple directions for drawer.
If that's not the case, you can modify code and remove the for-loop entirely.
Here's a working example
const { useState, useEffect } = React;
const { Drawer, Button } = MaterialUI;
const App = (props) => {
const [ state, setState ] = useState({});
const allAnchors = [ 'left', 'right', 'top', 'bottom' ];
for(let anchor of allAnchors) {
useEffect(() => {
if (state[anchor]) {
setTimeout(() => {
toggleDrawer(anchor, false)()
}, 2000); // close after 2000ms
}
}, [state[anchor]]);
}
const toggleDrawer = (anchor, open, data) => (event) => {
if (
// check if event is not undefined
event &&
event.type === "keydown" &&
(event.key === "Tab" || event.key === "Shift")
) {
return addProduct(data);
}
if( typeof open === 'undefined') open = !state[anchor]
setState(s => ({ ...s, [anchor]: open }));
};
return (
<div>
{ allAnchors.map(anchor =>
(
<React.Fragment>
<Button onClick={toggleDrawer(anchor)} >
{anchor}
</Button>
<Drawer
anchor={anchor}
open={state[anchor]}
onClose={toggleDrawer(anchor, false)}
>
This is Drawer
</Drawer>
</React.Fragment>
))
}
</div>
)
}
ReactDOM.render(<App />, document.querySelector('#root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/#material-ui/core#4.12.1/umd/material-ui.development.js"></script>
<div id="root" />

Related

How to map components and ensure the component has the same attribute individually

Currently I have a map function that render a serial of image, and I realized that they share the same hover state, which means they will perform the same action when hovered. Is there are any standard practice to map duplicate components while assigning them unique/individual properies?
{itemData.map((item) => (
<ImageListItem key={item.img}>
<img
src={item.img}
alt={item.title}
loading="lazy"
onMouseOver={() => {setHover(true)}}
onMouseOut={() => {setHover(false)}}
style={{ transform: hover ? 'scale(1.5, 1.5)' : null }}
/>
<ImageListItemBar
title={item.title}
subtitle={item.author}
actionIcon={
<IconButton
sx={{ color: 'rgba(255, 255, 255, 0.54)' }}
aria-label={`info about ${item.title}`}
>
<InfoIcon />
</IconButton>
}
/>
You should use a component, which create a unique state for each element, i wrote an easy to understand example.
import React, { useState } from "react"
const items = [
{
title: 'Card1',
price: 100
},
{
title: 'Card2',
price: 50
},
{
title: 'Card3',
price: 200
},
]
export default function App() {
return (
<>
{
items.map(element => {
return(
<Card {...element}/>
)
})
}
</>
)
}
function Card({title, price, key}) {
const [isHovered, setHover] = useState(false)
return (
<>
<div
key={key}
onMouseOver={() => {setHover(true)}}
onMouseOut={() => {setHover(false)}}
>
<div>
{title}
</div>
<h3>
{
isHovered && price
}
</h3>
</div>
</>
);
}
I made the card price to show if hovered so you can see it works on each individual component.
Code sandbox if you want to check it out.
To provide unique properties, you need to have something that uniquely identifies your image component and use it to manage your state. In your case, your state hover should be an array or an object, not a boolean. Since you are using item.img as a key, I assume it is unique and hence it can help in your state management like this:
const [hover, setHover] = useState({});
{itemData.map((item) => (
<ImageListItem key={item.img}>
<img
src={item.img}
alt={item.title}
loading="lazy"
onMouseOver={() => setHover({...hover, [item.img]: true})}
onMouseOut={() => setHover({...hover, [item.img]: false})}
style={{ transform: hover ? 'scale(1.5, 1.5)' : null }}
/>
<ImageListItemBar
title={item.title}
subtitle={item.author}
actionIcon={
<IconButton
sx={{ color: 'rgba(255, 255, 255, 0.54)' }}
aria-label={`info about ${item.title}`}
>
<InfoIcon />
</IconButton>
}
/>
))
}
If you want the state to be in the parent without going all the way to an array or object, you can use a number instead. If only one item at a time is going to be active, you can just use the index of the active item as the state:
const { useState } = React;
const things = ["foo", "bar", "baz"];
function Component() {
const [active, setActive] = useState(-1);
const updateActivity = (index) => setActive(index === active ? -1 : index);
return (
<ul>
{things.map((thing, index) => (
<li>
<button key={index} onClick={() => updateActivity(index)}>
{index === active
? <strong>{thing}</strong>
: thing}
</button>
</li>
))}
<li>Value: {active}</li>
</ul>
);
}
ReactDOM.render(
<Component />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Alternatively, in cases where you want multiple items to be simultaneously active, you can use a "bit flag" approach where each bit of the value represents whether or not the corresponding index is active:
const { useState } = React;
const things = ["foo", "bar", "baz"];
function Component() {
const [active, setActive] = useState(0);
const updateActivity = (index) => setActive(active ^ Math.pow(2, index));
return (
<ul>
{things.map((thing, index) => (
<li>
<button key={index} onClick={() => updateActivity(index)}>
{active & Math.pow(2, index)
? <strong>{thing}</strong>
: thing}
</button>
</li>
))}
<li>Value: {active} ({active.toString(2).padStart(3, "0")})</li>
</ul>
);
}
ReactDOM.render(
<Component />,
document.getElementById("react2")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="react2"></div>

Toasty does not autoclose or manual close after hook list

I modified the code to generate a toast stack into a ToastContainer dynamically as a notification system. Now the toast do not autoclose even in close button click.
The code can be reproduced by copy and past inside of dimiss area in https://react-bootstrap.github.io/components/toasts/
const Tsty = (props) =>
<>
<Toast show={ props.show } delay={ 3000 } autohide>
<Toast.Header>
<img src="holder.js/20x20?text=%20" className="rounded me-2" alt="" />
<strong className="me-auto">{props.title}</strong>
<small className="text-muted">{props.time}</small>
</Toast.Header>
<Toast.Body>{props.body}</Toast.Body>
</Toast>
</>
render(<Tsty />);
function Example() {
const [listNtfy, setNtfy] = useState([]);
const style = { position: 'fixed', bottom: '60px', right: '10px', zIndex: '1000'}
return (
<>
<Button onClick={() => {setNtfy([...listNtfy, {title: 'title #', time: 'now', body: new Date().toString(), show : true }])}}>Add Ntfy</Button>
<ToastContainer style={style}>
{ listNtfy.map( (x,i) => <Tsty show={ x.show } title={x.title + i} time={x.time} body={x.body} key={i} /> ) }
</ToastContainer>
</>
);
}
render(<Example />);
where is the error?
This doesn't close cause Tosty hook to show property that is not present in the hook. To solve it, you can define the show property and create a function to hide it. When all ntfys are closed, the list is cleaned.
const Tsty = (props) =>
<>
<Toast show={ props.show } onClose={ () => {props.fcn(props.idx) } } delay={ 5000 } autohide>
<Toast.Header>
<img src="holder.js/20x20?text=Q" className="rounded me-2" alt="" />
<strong className="me-auto">{props.title}</strong>
<small className="text-muted">{props.time}</small>
</Toast.Header>
<Toast.Body>{props.body}</Toast.Body>
</Toast>
</>
render(<Tsty />);
function Example() {
const [listNtfy, setNtfy] = useState([]);
// Function to autohide the ntfys
const autoHide = (key) => {
// Set visibility of Ntfy to hidden
listNtfy.filter((x,i) => i === key)[0].show = false;
// Apply the change
setNtfy([...listNtfy]);
// Check all notifications is hide (if yes, reset the list)
if (listNtfy.every(v => v.show === false))
setNtfy([]);
};
const style = { position: 'fixed', bottom: '60px', right: '10px', zIndex: '1000'}
return (
<>
<Button onClick={() => {setNtfy([...listNtfy, { title: 'title #' + listNtfy.length, time: 'now', body: new Date().toString(), show : true }])}}>Add Ntfy</Button>
<ToastContainer style={style}>
{ listNtfy.map( (x,i) => <Tsty show={ x.show } title={x.title} time={x.time} body={ x.body } key={i} idx={i} fcn={ autoHide } /> )}
</ToastContainer>
</>
);
}
render(<Example />);

Multiple fields appearing under a parent in ReactJs

class CriteriaSetValue extends Component {
state = {
count: 0,
tableName: "",
fieldName:"",
tables: [],
fields: [],
addLine: [],
addField: []
};
onSubmit = e => {
e.preventDefault();
const addField = this.state.addField;
const size = addField.length + 1;
addField.push(size);
this.setState({
addField
});
addNewLine = event => {
event.preventDefault();
const addLine = this.state.addLine;
const size = addLine.length + 1;
const nextLine = this.state.count + 1;
addLine.push(size);
this.setState({
count: nextLine,
addLine
});
};
render() {
const {showForm, tableName, fieldName } = this.state;
const { props, state } = this;
return (
<React.Fragment>
<div className="form-wrapper">
<div className="row">
<div className="col-10 container">
<form onSubmit={this.submit} className="card">
<div className="card-header">
<h3 className="card-title">
Criteria Set
{/* <Locale value="std.formupload" /> */}
</h3>
</div>
<div className="card-body">
<div className="row">
<div className="col-md-7 col-lg-8">
<div className="add-line">
<Button
icon
labelPosition="left"
onClick={this.addNewLine}
>
Add Line
<Icon name="plus" />
</Button>
{this.state.addLine.map(index => {
return (
<div
className="field-line"
style={{ marginTop: "30px" }}
key={index}
id={index}
>
<h4 className="field-button">Line {index}</h4>
<Button
className="field-button"
icon
onClick={this.toggleForm}
>
<Icon name="box" />
</Button>
</div>
);
})
}
{
this.state.addField.map(index => {
return (
<React.Fragment>
<div
className="field-button"
style={{
marginTop: "20px",
paddingLeft: "20px"
}}
key={index}
id={index}
>
<h4
className="field-button"
onclick={this.addCriteriaValue}
>
<span>
table.field
</span>
</h4>
<Button
className="field-button"
icon
onClick={this.toggleDelete}
>
<Icon name="delete calendar" />
</Button>
</div>
<br></br>
</React.Fragment>
);
})
}
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</React.Fragment>
);
}
};
This is kind of related to what I am trying to achieve:
https://codesandbox.io/s/3vqyo8xlx5
But I want the child to appear under the preference of where the "Add child" button is clicked, not on the last one.
I am working on making multiple fields to appear under each line when a button beside line1, line2 and so on is clicked, but currently, the field jump to last lines when a button is clicked, it is not appearing on the appropriate line.
I have been able to show lines when the "Add Line" button is clicked and I have also been able to show the field when the button beside "Line #1" is clicked.
I want the fields for "Line #1" to show under the line1 when the field button is clicked, the field for "Line #2" to show under the line2 when the field button beside it is clicked and so on
You can try something like this:
const AddButton = ({ label, onClick }) => (
<button onClick={onClick}>
{label} [+]
</button>
)
const FieldData = ({ label, criterias, onAdd, onDelete }) => (
<React.Fragment>
<div
className='field-button'
style={{
marginTop: '20px',
paddingLeft: '20px'
}}
>
<h4 className='field-button'>
<AddButton
label='Add criteria'
onClick={onAdd}
/>
<span>
{label}
</span>
</h4>
{criterias.map((item, idx) => (
<p key={idx}>{item.id}</p>
))}
<button
className='field-button'
onClick={onDelete}
>
Del [-]
</button>
</div>
<br />
</React.Fragment>
)
class App extends React.PureComponent {
state = {
lines: []
}
handleSubmit = e => {
e.preventDefault()
console.log('DATA TO SAVE ' + JSON.stringify(this.state.lines))
}
handleAddLine = event => {
event.preventDefault()
this.setState(prevState => ({
...prevState,
lines: [
...prevState.lines,
{
id: (prevState.lines.length + 1),
fields: []
}
]
}))
}
handleAddField = lineId => e => {
e.preventDefault()
this.setState(prevState => {
const newLines = [ ...prevState.lines ]
const curLine = newLines[newLines.findIndex(({ id }) => id === lineId)]
curLine.fields.push({
id: curLine.fields.length + 1,
criterias: []
})
return {
...prevState,
lines: newLines
}
})
}
handleAddCriteria = (lineId, fieldId) => event => {
event.preventDefault()
this.setState(prevState => {
const newLines = [ ...prevState.lines ]
const curLine = newLines[newLines.findIndex(({ id }) => id === lineId)]
const curField = curLine.fields[curLine.fields.findIndex(({ id }) => id === fieldId)]
curField.criterias.push({
id: curField.criterias.length + 1
})
return {
...prevState,
lines: newLines
}
})
}
handleDeleteField = (lineId, fieldId) => event => {
event.preventDefault()
this.setState(prevState => {
const newLines = [ ...prevState.lines ]
const curLine = newLines[newLines.findIndex(({ id }) => id === lineId)]
curLine.fields = curLine.fields.filter(item => item.id !== fieldId)
return {
...prevState,
lines: newLines
}
})
}
render() {
const { lines } = this.state
return (
<React.Fragment>
<div className='form-wrapper'>
<div className='row'>
<div className='col-10 container'>
<form
onSubmit={this.handleSubmit}
className='card'
>
<div className='card-header'>
<h3 className='card-title'>
Criteria Set
</h3>
</div>
<div className='card-body'>
<div className='row'>
<div className='col-md-7 col-lg-8'>
<div className='add-line'>
<AddButton
label='Add Line'
onClick={this.handleAddLine}
/>
{lines.map((line, idx) => {
return (
<React.Fragment key={idx}>
<div
className='field-line'
style={{ marginTop: '30px' }}
>
<h4 className='field-button'>
Line {idx+1}
</h4>
<AddButton
label='Add field'
onClick={this.handleAddField(line.id)}
/>
</div>
{line.fields.map((lField, idx) => (
<FieldData
label={idx+1}
criterias={lField.criterias}
onAdd={this.handleAddCriteria(line.id, lField.id)}
onDelete={this.handleDeleteField(line.id, lField.id)}
/>
))}
</React.Fragment>
)
})}
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</React.Fragment>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
I defined a new data structure for the state, so It is better to think about nested data, and I refactored the code a little.

How to implement drag and drop behaviour in React

I'm trying to implement drag and drop behaviour using React and react-beautiful-dnd library.
I want to chose some images using react-dropzone library and after choosing images I show thumbnails on the right side of the screen and after that I want to be able to drag one of those thumbnails to the left side and drop it to one of those containers.
My code is as follows:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import Dropzone from "react-dropzone";
import { Animated } from "react-animated-css";
import { orderBy } from "lodash";
import UUID from "uuid";
import "./styles.css";
const animationIn = "fadeInDown";
const animationOut = "fadeOutUp";
const animationDuration = 400; // in ms
const pictureTypes = [
{
title: "3/4 front left",
imageOverlay: "https://via.placeholder.com/100",
item: "front-left",
mandatory: true,
image: null,
priority: 1
},
{
title: "3/4 rear right",
imageOverlay: "https://via.placeholder.com/100",
item: "rear-right",
mandatory: true,
image: null,
priority: 2
},
{
title: "Inside door right",
imageOverlay: "https://via.placeholder.com/100",
item: "front-door-right-i",
mandatory: true,
image: null,
priority: 3
}
];
class App extends Component {
constructor(props) {
super(props);
this.state = {
files: [],
pictureTypes: pictureTypes
};
this.onDragEnd = this.onDragEnd.bind(this);
}
onDragEnd(result) {
debugger;
// dropped outside the list
if (!result.destination) {
return;
}
}
addFilesToState(files) {
let files_with_preview = [];
files.map(file => {
file["preview"] = URL.createObjectURL(file);
files_with_preview.push(file);
this.setState({ [`visibleAnimate${file.path}`]: true });
});
const new_files = [...this.state.files, ...files_with_preview];
this.setState({ files: new_files });
}
renderPreviews(files) {
if (files.length < 1)
return <div>Drag and drop some files to see them here.</div>;
return (
<div style={{ display: "flex", flexDirection: "column" }}>
<div>Chosen pictures</div>
<div style={{ display: "flex", flexDirection: "row" }}>
{files.map((file, index) => {
return (
<Draggable key={UUID.v4()} draggableId={UUID.v4()} index={index}>
{provided => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<img
src={file.preview}
alt={file.path}
style={{ width: 80 }}
/>
</div>
)}
</Draggable>
);
})}
</div>
</div>
);
}
handlePictureTypesDrop(file, pictureType) {
const file_blob = URL.createObjectURL(file);
const updated_picture_type = {
...this.state.pictureTypes.find(pt => pt.item === pictureType.item),
image: file_blob
};
const updated_picture_types = [
...this.state.pictureTypes.filter(pt => pt.item !== pictureType.item),
updated_picture_type
];
let new_picture_types = [...updated_picture_types];
this.setState({ pictureTypes: new_picture_types });
}
renderPictureTypes() {
const { allowed_types } = this.props;
const { pictureTypes } = this.state;
const self = this;
return orderBy(pictureTypes, "priority").map(pt => {
return (
<div style={{ width: "25%", marginRight: 5 }}>
<Dropzone
onDrop={files => self.handlePictureTypesDrop(files[0], pt)}
accept={allowed_types}
multiple={false}
>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()}>
<input {...getInputProps()} />
<div className="picture-types-wrapper">
<div>
<img
src={pt.image !== null ? pt.image : pt.imageOverlay}
alt={pt.title}
/>
</div>
<div style={{ fontSize: "0.65rem" }}>{pt.title}</div>
</div>
</div>
)}
</Dropzone>
</div>
);
});
}
// Normally you would want to split things out into separate components.
// But in this example everything is just done in one place for simplicity
render() {
const { files } = this.state;
const self = this;
return (
<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId="droppable">
{provided => (
<div
key="droppable"
{...provided.droppableProps}
ref={provided.innerRef}
>
<Dropzone
onDrop={files => self.addFilesToState(files)}
accept="image/jpeg, image/png"
>
{({ getRootProps, getInputProps }) => (
<section className="drag-drop-section">
<div {...getRootProps()}>
<input {...getInputProps()} />
<p className="drag-drop-text">
Drag 'n' drop some files here, or click to select files
</p>
</div>
</section>
)}
</Dropzone>
<div
style={{ display: "flex", flexDirection: "row", marginTop: 10 }}
>
<div style={{ display: "flex", flexDirection: "row" }}>
{self.renderPictureTypes()}
</div>
<div className="flex w-1/2 pl-2">
{self.renderPreviews(files)}
</div>
</div>
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}
}
// Put the thing into the DOM!
ReactDOM.render(<App />, document.getElementById("root"));
Here is the example code on codesandbox.
The photo's are successfully added to the right side where I render the thumbnails but I cant drag one of them then to the left side.
Any idea how to solve it?
<Draggable> should be inside <Droppable>
<Draggable /> components can be dragged around and dropped onto <Droppable />s. A <Draggable /> must always be contained within a <Droppable />. It is possible to reorder a <Draggable /> within its home <Droppable /> or move to another <Droppable />. It is possible because a <Droppable /> is free to control what it allows to be dropped on it.
see here

togglebutton failing in reactjs

I am trying to show different html body on same tab having two toggle buttons. I have two toggle buttons with one as pre-configured. I want to show different html on two different buttons, for doing this I have added one functions named getBody for rendering html.
But I'm not getting how to call this function with certain condition in toggle button. For doing this I have added one variable flag. And I am not getting how to use toggle button . It should be something like EbLog will be by default pre-configured and after that one can use CloudLog.
export default class ResourceLog extends React.Component {
constructor(props) {
super(props);
this.state = {
streamData: {},
streamMessage: "",
interval: 5000,
showDatePicker: false,
selectionConfigs: [
{
name: "1 Hr",
cssClass: "btn btn-info btn-sm",
duration: 300,
startTime: -1,
endTime: -1,
diff: 3600
},
{
name: "3 Hr",
cssClass: "btn btn-info btn-sm",
duration: 300,
startTime: -1,
endTime: -1,
diff: 10800
}
],
params: {},
show: "EbLog",
value: 1
};
}
streamLogs = () => {
if (this.props.resource.status === "ACTIVE") {
this.setState({ streamMessage: "loading logs.." });
axios.instance
.get("api/resources/" + this.props.resource.id + "/log/stream")
.then(resp => {
this.setState({ streamData: resp.data, streamMessage: "" });
})
.catch(err => {
this.setState({ streamMessage: "" });
NotificationManager.error("unable to fetch logs");
});
} else {
this.setState({
streamMessage: "Resource is not Active cannot fetch/stream logs..."
});
}
};
onCloud = () => {
let endTime = this.state.params.endTime;
if (endTime === -1) {
endTime = new Date().getTime();
}
let startTime = this.state.params.startTime;
if (startTime === -1) {
startTime = endTime - this.state.params.diff * 1000;
}
let filter = this.state.params.duration;
if (filter === -1) {
filter = "";
}
let params = Object.assign(
{},
{ startTime: startTime, endTime: endTime, filter: period }
);
this.setState({ streamMessage: "loading stats.." });
axios.instance
.get("api/resources/" + this.props.resource.id + "/cloud/log", {
params: params
})
.then(resp => {
this.setState({ data: resp.data, streamMessage: "" });
})
.catch(error => {
NotificationManager.error(`Failed to fetch stats-`, "Error");
});
};
render() {
return (
<div>
//<button style={edit} onClick={this.streamLogs}>
EbLog
</button>
//<button style={edit} onClick={this.onCloud}>
CloudLog
</button>
<ButtonToolbar>
<ToggleButtonGroup type="checkbox" defaultValue={[1]}>
<ToggleButton value={1}>EBLog</ToggleButton>
{}
<ToggleButton value={2}>CloudLog</ToggleButton>
</ToggleButtonGroup>
</ButtonToolbar>
{this.getBody()}
</div>
);
}
getBody = () => {
if (this.state.show == "EbLog") {
return (
<div className="row" style={{ margin: "15px" }}>
<div className="col-md-12">
<h3 style={{ display: "inline" }}>
Logs
<span
style={{ marginLeft: "10px", cursor: "pointer" }}
title={"Download"}
>
<a
target="_blank"
href={`api/resources/${this.props.resource.id}/log`}
>
<i className="fa fa-download" />
</a>
</span>
<span
style={{ marginLeft: "10px", cursor: "pointer" }}
title={"Refresh"}
>
<i onClick={this.streamLogs} className="fa fa-refresh" />
</span>
</h3>
</div>
<div className="clearfix" />
<br />
<div className="col-md-12">
<div>{this.state.streamMessage}</div>
{mapObject(this.state.streamData, (k, v) => (
<div>
<pre>{v.join("\n")}</pre>
</div>
))}
</div>
</div>
);
} else if (this.state.show == "CloudLog") {
return (
<div className="row" style={{ margin: "20px", textAlign: "center" }}>
<div>
<span
className={this.state.selectionConfigs[0].cssClass}
onClick={() =>
this.updateStatsConf(this.state.selectionConfigs[0])
}
>
{this.state.selectionConfigs[0].name}
</span>
<span
style={{ marginLeft: "10px" }}
className={this.state.selectionConfigs[1].cssClass}
onClick={() =>
this.updateStatsConf(this.state.selectionConfigs[1])
}
>
{this.state.selectionConfigs[1].name}
</span>
<span
style={{ marginLeft: "10px" }}
className={this.state.selectionConfigs[2].cssClass}
onClick={() =>
this.updateStatsConf(this.state.selectionConfigs[2])
}
>
{this.state.selectionConfigs[2].name}
</span>
</div>
<div className="row" style={{ margin: "20px" }}>
<div className="col-md-12">
<div>{this.state.streamMessage}</div>
{mapObject(this.state.streamData, (k, v) => (
<div>
<pre>{v.join("\n")}</pre>
</div>
))}
</div>
</div>
</div>
);
} else {
<h1> please click a Button </h1>;
}
};
}
Please refer this link. I have used this link as reference for creating ToggleButton under section Controlled
From what I understand, you need to create a simple method to change state on click. Say something like;
toggleButton = (text) => {
this.setState({show: text});
}
And then use onClick attribute in your ToggleButton element;
<ToggleButtonGroup type="checkbox" defaultValue={[1]}>
<ToggleButton value={1} onClick={this.toggleButton.bind(this, "EbLog")}>EBLog</ToggleButton>
{}
<ToggleButton value={2} onClick={this.toggleButton.bind(this, "CloudLog")}>CloudLog</ToggleButton>
</ToggleButtonGroup>
From what i understood from the problem, please refer the following example to render different views according to toggle button click.
The toggle button should be as follows
<ToggleButton onClick = {this.toggleButton}/>
The method should update the state
toggleButton(value){
value ? this.setState(show:'CloudLog') : this.setState(show:'EbLog')
}
The render method can be as
render() {
return(
this.state.show ==='CloudLog' ? <div>View 1</div> : <div>View 2</div>
)
}

Categories

Resources