I am trying to hide the canvas element in this MyRecorder component:
The element is visible when inspecting the page in browser.
import React, {Component} from 'react';
import { render } from 'react-dom';
import start from '../img/start.svg';
import stop from '../img/stop.svg';
import pause from '../img/pause.svg';
import { ReactMic } from 'react-mic';
class MyRecorder extends Component {
constructor(props){
super(props);
this.state = {
blobObject: null,
isRecording: false,
isPaused: false
}
}
startOrPauseRecording= () => {
const { isPaused, isRecording } = this.state
if(isPaused) {
this.setState({ isPaused: false })
} else if(isRecording) {
this.setState({ isPaused: true })
} else {
this.setState({ isRecording: true })
}
}
stopRecording= () => {
this.setState({ isRecording: false });
}
onStop= (blobObject) => {
this.setState({ blobURL : blobObject.blobURL });
}
render() {
const { blobURL, isRecording, isPaused } = this.state;
const getImage = () => {
if(isRecording && !isPaused) {
return (`url(${pause})`)
}
else {
return (`url(${start})`)
}
}
return(
<div
style={{marginLeft: 15,}}
>
<ReactMic
record={isRecording}
pause={isPaused}
visualSetting="none"
audioBitsPerSecond= {128000}
onStop={this.onStop}
onStart={this.onStart}
onSave={this.onSave}
strokeColor="#000000" />
<audio ref="" controls="controls" src={blobURL}></audio>
<br />
<br />
<button
className="btn btn-light recButton"
style={{
backgroundImage: `url(${isRecording && !isPaused? pause : start})`,
width:40,
height:40,
}}
onClick={this.startOrPauseRecording}>
</button>
<button
className="btn btn-light recButton"
disabled={!isRecording}
style={{
backgroundImage: `url(${stop})`,
width:40,
height:40,
}}
onClick={this.stopRecording}>
</button>
<br />
</div>
);
}
}
export default MyRecorder;
When the visualSetting is:
visualSetting="sinewave"
Sinewaves are shown in the canvas, after changing it to:
visualSetting="none"
The waves go away but the canvas element is still there. Any idea how to get rid of the element?
I was able to find a workaround. In the file node_modules/react-mic/es/components/ReactMic.js
Change line 130 from:
return React.createElement('canvas', { ref: 'visualizer', height: height, width: width, className: this.props.className });
To:
return React.createElement('canvas', { ref: 'visualizer', height: 0, width: 0, className: this.props.className });
Related
I have the stake component that is rendered 4 times in the parent class component. I am trying to pass valueNewStake as prop to its parent component and group all the inputs in one common array (see allStakes). For a reason I am not able to change the state and also the dom does not render the button next to the component. Can anyone explain me why it is happening as I am new in react. Thanks
import React, { Component } from 'react';
import Stake from './stake';
class FetchRandomBet extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
bet: null,
value: this.props.value,
allStakes: ['']
};
}
async componentDidMount() {
const url = "http://localhost:4000/";
const response = await fetch(url);
const data = await response.json();
this.setState({
loading: false,
bet: data.bets,
});
}
render() {
const { valueProp: value } = this.props;
const { bet, loading } = this.state;
if (loading) {
return <div>loading..</div>;
}
if (!bet) {
return <div>did not get data</div>;
}
return (
< div >
{
loading || !bet ? (
<div>loading..</div>
) : value === 0 ? (
<div className="bet-list">
<ol>
<p>NAME</p>
{
bet.map(post => (
<li key={post.id}>
{post.name}
</li>
))
}
</ol>
<ul>
<p>ODDS</p>
{
bet.map(post => (
<li key={post.id}>
{post.odds[4].oddsDecimal}
<div className="stake-margin">
<Stake
allStakes={this.props.valueNewStake}
onChange={() => { this.setState({ allStakes: [...this.props.valueNewStake] }) }}
>
<button>ok</button>
</Stake>
</div>
</li>
))
}
</ul>
</div>
import React, { useState } from 'react';
import CurrencyInput from 'react-currency-input-field';
function Stake() {
const [newStake, setStake] = useState(['']);
const changeStake = (e) => {
setStake(e.target.value)
}
return (
<>
<CurrencyInput
onChange={changeStake}
valueNewStake={newStake}
style={{
marginLeft: "40px",
width: "50px"
}}
placeholder="Stake"
decimalScale={2}
prefix="£"
/>
{newStake}
</>
);
}
export default Stake;
You're not passing your props to your Stake component
function Stake({ allStakes, onChange }) {
// do something with your props here
const [newStake, setStake] = useState(['']);
const changeStake = (e) => {
onChange()
setStake(e.target.value)
}
return (
<>
<CurrencyInput
onChange={changeStake}
valueNewStake={newStake}
style={{
marginLeft: "40px",
width: "50px"
}}
placeholder="Stake"
decimalScale={2}
prefix="£"
/>
{newStake}
</>
);
}
I am using react-google-maps. I have created map and displayed 3 types of markers in it.
I can now draw polygons on map but not able to get the details of markers covered under the drawn shape.
Any help would be appreciated.
This is my code of map jsx.
I am creating 3 different markers with different icons to identify on map.
When i draw a shape on map, i want to get the details of every sort of marker which comes under the drawn shape.
import React from "react";
import DrawingManager from "react-google-maps/lib/components/drawing/DrawingManager";
import {GoogleMap, InfoWindow, Marker, withGoogleMap, withScriptjs} from "react-google-maps";
import UploadApis from "../../service/rest/upload";
import "./index.scss";
let selectedShape;
function clearSelection() {
if (selectedShape) {
if (selectedShape.type !== 'marker') {
selectedShape.setEditable(false);
}
selectedShape = null;
}
}
function setSelection(shape) {
if (shape.type !== 'marker') {
clearSelection();
shape.setEditable(true);
}
selectedShape = shape;
}
class Map extends React.Component {
constructor(props) {
super(props);
this.shapes = [];
this.state = {
fiberData: [],
subscriberData: [],
sitesData: [],
fetchData: false,
selected: null
};
this.handleOverlayComplete = this.handleOverlayComplete.bind(this);
this.data();
}
handleOverlayComplete(e) {
console.log("overlay",e);
const newShape = e.overlay;
newShape.type = e.type;
if (e.type !== window.google.maps.drawing.OverlayType.MARKER) {
window.google.maps.event.addListener(newShape, 'click', function (e) {
if (e.vertex !== undefined) {
if (newShape.type === window.google.maps.drawing.OverlayType.POLYGON) {
let path = newShape.getPaths().getAt(e.path);
path.removeAt(e.vertex);
if (path.length < 3) {
newShape.setMap(null);
}
}
if (newShape.type === window.google.maps.drawing.OverlayType.POLYLINE) {
let path = newShape.getPath();
path.removeAt(e.vertex);
if (path.length < 2) {
newShape.setMap(null);
}
}
}
setSelection(newShape);
});
setSelection(newShape);
} else {
window.google.maps.event.addListener(newShape, 'click', function (e) {
setSelection(newShape);
});
setSelection(newShape);
}
this.shapes.push(newShape);
}
data = async () => {
let fiberData = await UploadApis.getMetaDataById("fiber",this.props.projectId);
let sitesData = await UploadApis.getMetaDataById("sites",this.props.projectId);
let subscriberData = await UploadApis.getMetaDataById("subscriber",this.props.projectId);
this.setState({fiberData: fiberData, sitesData: sitesData, subscriberData: subscriberData, fetchData: true})
};
deleteSelectedShape = () => {
if (selectedShape) {
selectedShape.setMap(null);
}
};
setSelected(selected) {
this.setState({selected: selected})
}
render() {
return (
<div>
<button className="btn-container" onClick={this.deleteSelectedShape}>Delete Shape
</button>
{this.state.fetchData ?
<div>
<GoogleMap
defaultZoom={6}
defaultCenter={{lat: 22.5106879, lng: 79.9189213}}
>
<DrawingManager
defaultDrawingMode={null}
defaultOptions={{
drawingControl: true,
drawingControlOptions: {
position: window.google.maps.ControlPosition.TOP_CENTER,
drawingModes: [ 'circle', 'polygon', 'polyline', 'rectangle']
},
polygonOptions: {editable: true},
circleOptions: {editable: true},
rectangleOptions: {editable: true},
markerOptions: {editable: true},
polylineOptions: {editable: true}
}}
onOverlayComplete={this.handleOverlayComplete}
/>
{this.state.fiberData.map((fiber) => (
<Marker
key={fiber.id}
position={{lat: fiber.latitude, lng: fiber.longitude}}
onClick={() => {
this.setSelected(fiber);
}}
icon={{
url: "../assets/svg/fiber.png",
scaledSize: new window.google.maps.Size(25, 25)
}}
/>
))}
{this.state.sitesData.map((site) => (
<Marker
key={site.id}
position={{lat: site.latitude, lng: site.longitude}}
onClick={() => {
this.setSelected(site);
}}
icon={{
url: "../assets/svg/tower.png",
scaledSize: new window.google.maps.Size(25, 25)
}}
/>
))}
{this.state.subscriberData.map((subscriber) => (
<Marker
key={subscriber.id}
position={{lat: subscriber.latitude, lng: subscriber.longitude}}
onClick={() => {
this.setSelected(subscriber);
}}
icon={{
url: "../assets/svg/subscriber.svg",
scaledSize: new window.google.maps.Size(25, 25)
}}
/>
))}
{this.state.selected && (
<InfoWindow
position={{lat: this.state.selected.latitude, lng: this.state.selected.longitude}}
onCloseClick={() => {
this.setSelected(null);
}}>
<div>
<h4>{this.state.selected.name}</h4>
<p>{this.state.selected.description}</p>
</div>
</InfoWindow>
)}
</GoogleMap>
</div> : null
}
</div>
);
}
}
export default withScriptjs(withGoogleMap(Map));
This is the first file which i have called. Index file which renders the map is -
import React from "react";
import Map from './map.jsx';
export default class MapContainer extends React.Component {
_projectId="";
constructor(props) {
super(props);
console.log(props);
if(props.location.state.project){
this._projectId = props.location.state.project.id;
}
}
render() {
return (
<div>
<Map
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=API_KEY`}
loadingElement={<div style={{height: `100%`}}/>}
containerElement={<div style={{height: `480px`}}/>}
mapElement={<div style={{height: `100%`}}/>}
projectId ={this._projectId}
/>
</div>
);
}
}```
I am trying to test a component with #react-google-maps/api package. I am getting error: TypeError: Cannot read property 'maps' of undefined.
My component:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchPersonId, updatePersonSettings, pushPersonMessage } from '../../actions/person';
import TemplatePage from '../templates/TemplatePage';
import Card from '../partials/Card';
import Msg from '../partials/Msg';
import { GoogleMap, Marker } from '#react-google-maps/api';
import markerPosition from'../../img/marker-position.png';
import PlacesAutocomplete, { geocodeByAddress, getLatLng } from 'react-places-autocomplete';
import PropTypes from 'prop-types';
import { DEFAULT_LAT, DEFAULT_LNG, DEFAULT_ZOOM } from '../../config/';
export class Settings extends Component {
state = {
lat: DEFAULT_LAT,
lng: DEFAULT_LNG,
zoom: DEFAULT_ZOOM,
address: '',
formSubmitted: false
}
componentDidMount () {
const { lat, lng, zoom } = this.props.auth;
this.setState({
lat: lat !== undefined && lat !== null ? lat : DEFAULT_LAT,
lng: lng !== undefined && lng !== null ? lng : DEFAULT_LNG,
zoom: zoom !== undefined && zoom !== null ? zoom : DEFAULT_ZOOM
});
this.drawMarker();
}
handleOnSubmit = e => {
e.preventDefault();
const settings = {
zoom: this.state.zoom,
lat: this.state.lat,
lng: this.state.lng
}
this.props.updatePersonSettings({ id: this.props.auth.person_id, settings })
}
handleChangeZoom = event => {
this.setState({ zoom: parseInt(event.target.value )});
}
handleChangeAddress = (address) => {
this.setState({ address });
}
handleSelect = (address) => {
geocodeByAddress(address)
.then(results =>
getLatLng(results[0])
.then(function(result) {
this.setState({
lat: result.lat,
lng: result.lng,
})
this.drawMarker()
}.bind(this))
)
.catch(error => console.error('Error', error));
};
handleMapClick = e => {
this.setState({
lat: e.latLng.lat(),
lng: e.latLng.lng(),
});
this.drawMarker();
}
handleMapZoom = (zoom) => {
console.log(zoom)
}
drawMarker = () => {
return <Marker
position={{
lat: parseFloat(this.state.lat),
lng: parseFloat(this.state.lng)
}}
icon={
new window.google.maps.MarkerImage(
markerPosition,
null, /* size is determined at runtime */
null, /* origin is 0,0 */
null, /* anchor is bottom center of the scaled image */
new window.google.maps.Size(48, 48)
)
}
>
</Marker>
}
get msg() {
if(this.props.person !== '') {
return <Msg msg={this.props.person} />
}
return null;
}
render() {
const { status } = this.props.person;
const { lat, lng, zoom, address, formSubmitted } = this.state;
return (
<TemplatePage>
{ this.msg }
<Card title='Settings' padding='large'>
<form className="form" onSubmit={this.handleOnSubmit}>
<div className="form-group">
<label htmlFor="position">Default map position</label>
<div className="google-map google-map__settings">
<GoogleMap
center={{ lat, lng }}
zoom={ zoom }
onClick={ e => this.handleMapClick(e) }
onZoomChanged={(e) => {
console.log('zoom changed')
}}
>
{this.drawMarker()}
<div className="map-constraints-container" />
</GoogleMap>
</div>
</div>
<div className="form-group">
<div className="map-constraints-slider">
<label htmlFor="range">Default map zoom: {zoom}</label>
<input
type="range"
id="zoom"
value={ zoom }
name="zoom"
min="1"
max="18"
onChange={ this.handleChangeZoom }
/>
</div>
</div>
<div className="form-group">
<PlacesAutocomplete
value={address}
onChange={ this.handleChangeAddress }
onSelect={ this.handleSelect }
>
{({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
<div>
<input
{...getInputProps({
placeholder: 'Search places...',
className: 'location-search-input',
})}
/>
<div className="autocomplete-dropdown-container">
{loading && <div>Loading...</div>}
{suggestions.map(suggestion => {
const className = suggestion.active
? 'suggestion-item--active'
: 'suggestion-item';
// inline style for demonstration purpose
const style = suggestion.active
? { backgroundColor: '#fafafa', cursor: 'pointer' }
: { backgroundColor: '#ffffff', cursor: 'pointer' };
return (
<div
{...getSuggestionItemProps(suggestion, {
className,
style,
})}
>
<span>{suggestion.description}</span>
</div>
);
})}
</div>
</div>
)}
</PlacesAutocomplete>
</div>
<div className="form-group">
<input
type="submit"
value="Update settings"
className="btn btn--primary card__footer--btn-left"
disabled={ formSubmitted && status === 'fetching' ? 'disabled' : null }
/>
</div>
</form>
</Card>
</TemplatePage>
)
}
}
Settings.defaultProps = {
auth: {},
person: {},
fetchPersonId: () => Promise.resolve(),
updatePersonsettings: () => Promise.resolve(),
pushPersonMessage: () => Promise.resolve()
}
Settings.propTypes = {
auth: PropTypes.object,
person: PropTypes.object,
fetchPersonId: PropTypes.func,
updatePersonsettings: PropTypes.func,
pushPersonMessage: PropTypes.func
};
export default connect(
({ auth, person }) => ({ auth, person }),
{ fetchPersonId, updatePersonSettings, pushPersonMessage }
)(Settings);
My test:
import React from 'react';
import { shallow } from 'enzyme';
import { Settings } from '../../../components/pages/Settings';
test('should render settings page', () => {
const wrapper = shallow(<Settings />);
expect(wrapper).toMatchSnapshot();
});
I read that in order to resolve such issues it is best to mock up the package. In some other component I am using `` package, which I managed to mock like so:
const zxcvbn = require.requireActual('zxcvbn');
export default (password = 'test') => {
return zxcvbn(password);
}
How would I mock up the #react-google-maps/api package and get rid of the error? Is this a good approach (mocking the package)? Or can this be resolved any other way? How would I test if the map or marker rendered at all?
I know this is an old question.
But the way I manage this is by mocking the google object. This is only mocks what I'm calling so you'd need to add any google constants and methods you call.
As for testing if it gets rendered, that's all buried in the google maps javascript api blob. You could add spys to ensure the appropriate functions are called.
I don't think it'd be possible to verify google maps is actually rendering anything though.
import ReactDOM from 'react-dom';
//ReactDOM.createPortal = jest.fn(node => node);
jest.mock('#react-google-maps/api', () => {
const React = require('React');
return {
withGoogleMap: (Component) => Component,
withScriptjs: (Component) => Component,
Polyline: (props) => <div />,
Marker: (props) => <div />,
GoogleMap: (props) => (<div><div className="mock-google-maps" />{props.children}</div>),
};
});
global.google = {
maps: {
LatLngBounds: () => ({
extend: () => { },
}),
MapTypeId: {
ROADMAP: 'rdmap',
SATELLITE: 'stllte'
},
ControlPosition: {
BOTTOM_CENTER: 'BC',
BOTTOM_LEFT: 'BL',
BOTTOM_RIGHT: 'BR',
LEFT_BOTTOM: 'LB',
LEFT_CENTER: 'LC',
LEFT_TOP: 'LT',
RIGHT_BOTTOM: 'RB',
RIGHT_CENTER: 'RC',
RIGHT_TOP: 'RT',
TOP_CENTER: 'TC',
TOP_LEFT: 'TL',
TOP_RIGHT: 'TR',
},
Size: function (w, h) {},
Data: class {
setStyle() {}
addListener() {}
setMap() {}
}
}
};
I know several topics exist about this subject but i don't find the "real" answer....
First of all, i work on React JS and i'm a beginner ;)
With the YouTube API, i mapped the items in the JSON object to display video thumbnails in cards. On desktop mode, when i click on thumbnail, it trigger a modal with the video.
But on mobile, i have 2 issues.....
I want, in the same time, replace (maybe replaceWith and data-video can be helpfull...) the thumbnail by the video who match with, and i want to trigger autoplay and fullscreen.....i don't know if the second part is possible....Despite my research, i still don't if i can get around this mobile block....
Thanks a lot for the answers and the advices :)
Here is my code below :
import React, { Component } from 'react'
import axios from 'axios';
import posed from 'react-pose';
import ReactPlayer from 'react-player';
import { Card, CardImg, Col, Row, CardTitle, Modal, ModalBody, ModalHeader, Pagination, PaginationItem, PaginationLink } from 'reactstrap';
import './videos.css'
const Box = posed.div({
hidden: { opacity: 0 },
visible: { opacity: 1 }
});
class Videos extends Component {
constructor () {
super();
this.state = {
isVisible : true,
videos: [],
resultsDatas: "",
nextPage: "",
previousPage: "",
videoId: "",
search: "",
playing: false,
modal : false,
clickedVideoId: "",
clickedVideoTitle: ""
}
}
componentDidMount() {
axios.get('https://www.googleapis.com/youtube/v3/playlistItems?key=......API KEY........&playlistId=PL3-4jitn5YqtnR_mrYoz_Qb0z7frXZcW6&type=video&showinfo=0&iv_load_policy=3&part=snippet,id&order=date&maxResults=24')
.then((result) => {
this.setState({
videos: result.data.items,
resultsDatas: result.data,
nextPage: result.data.nextPageToken});
console.log(this.state.videos);
}
)
setTimeout(() => {this.setState({ isVisible: !this.state.isVisible });
}, 400);
}
nextPage = () => {
axios.get(`https://www.googleapis.com/youtube/v3/playlistItems?key=......API KEY........&playlistId=PL3-4jitn5YqtnR_mrYoz_Qb0z7frXZcW6&type=video&part=snippet,id&order=date&maxResults=24&pageToken=${this.state.nextPage}`)
.then((result) => {
this.setState({
nextPage: result.data.nextPageToken,
previousPage: result.data.prevPageToken,
videos: result.data.items,
resultsDatas: result.data
});
})
}
previousPage = () => {
axios.get(`https://www.googleapis.com/youtube/v3/playlistItems?key=......API KEY........&playlistId=PL3-4jitn5YqtnR_mrYoz_Qb0z7frXZcW6&type=video&part=snippet,id&order=date&maxResults=24&pageToken=${this.state.previousPage}`)
.then((result) => {
this.setState({
nextPage: result.data.nextPageToken,
previousPage: result.data.prevPageToken,
videos: result.data.items,
resultsDatas: result.data});
})
}
//For search function
inputChange = (event) => {
this.setState({search: event.target.value })
}
playPause = (index) => {
let element = document.getElementById(`play-pause${index}`);
if (element.requestFullscreen) {
this.setState({playing: !this.state.playing})
}
}
toggleModal = () => {
this.setState({
modal: !this.state.modal
});
}
onThumbnailClick = (index) => {
this.setState({
clickedVideoId: this.state.videos[index].snippet.resourceId.videoId,
clickedVideoTitle: this.state.videos[index].snippet.title
})
var windowWidth = window.innerWidth;
if(windowWidth > 768){
this.toggleModal()
}
}
render() {
let mapedVideos = this.state.videos.filter(
(item) => {
return item.snippet.title.toLowerCase().indexOf(this.state.search) !==-1;
}
);
return (
<div>
{/* <Row className="search-pages-bar pt-3 d-flex justify-content-center">
<Pagination>
<PaginationItem onClick={this.previousPage}>
<PaginationLink previous href="#"/>
</PaginationItem>
<PaginationItem onClick={this.nextPage}>
<PaginationLink next href="#"/>
</PaginationItem>
</Pagination>
</Row> */}
<Box pose={this.state.isVisible ? 'hidden' : 'visible'}>
<Row className="custom-videos-row mb-5">
{mapedVideos.map((item, index) => {
this.state.videos.map((item) => {
if(item.snippet.title.length > 38) {
return (item.snippet.title=`${item.snippet.title.slice(0,37)}... `);
}
})
return (
<Col className="custom-videos-col" lg="3" md="4" sm="6" key={index}>
<Card className="card-wrapper" onClick={() => {this.onThumbnailClick(index)}}>
<CardImg className="video-thumbnail" src={item.snippet.thumbnails.medium.url} alt="thumb"></CardImg>
<CardTitle className="video-card-title pl-2"><img className="play-picto" src={process.env.PUBLIC_URL + '/images/play_L.png'} alt="play-picto"/>{item.snippet.title}
</CardTitle>
</Card>
</Col>
);
})}
<Modal className="video-modal" role="dialog" isOpen={this.state.modal} toggle={this.toggleModal}>
<ModalHeader className="custom-modal-header" toggle={this.toggleModal}>
<img src={process.env.PUBLIC_URL + './images/logo.png'} alt="La Baule TV logo" className="LBTV-logo"></img>
<span className="ml-2">{this.state.clickedVideoTitle}</span></ModalHeader>
<ModalBody>
<ReactPlayer className="video-player"
url={`https://www.youtube.com/watch?v=${this.state.clickedVideoId}`}
playing= {true}
config={{
youtube: {
playerVars: {
modestbranding: 1,
controls: 1,
rel: 0
}
}}}
/>
</ModalBody>
</Modal>
</Row>
</Box>
</div>
)
}
}
export default Videos;
<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>
I'm using ReactJS and I'm trying to do a delete confirm popover and it works but when I click on "delete" doesn't work at all!
I'm using a button and inside I have an Icon and when click should popover its data-content, and it does! but the onClick inside doesn't work, maybe it's the way that I'm writing it? Have no idea what's going on
What I'm doing wrong?
Thank you, hope you can help me!
import React, { Component } from 'react';
import moment from 'moment';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faTrashAlt, faEdit, faTimes } from '#fortawesome/free-solid-svg-icons'
import NewTask from '../NewTask/NewTask';
import './Tasks.css';
class Tasks extends Component {
constructor(props) {
super(props);
this.state = {
projectId: props._id,
project: props.project,
tasks: []
};
}
componentDidMount() {
fetch(`/dashboard/project/${this.props.projectId}/tasks`)
.then(response => {
return response.json()
}).then(task => {
this.setState({
tasks: task.tasks
})
}).catch(error => console.error('Error:', error));
}
appendTask = task => {
let tasks = this.state.tasks;
tasks.push(task);
this.setState({tasks});
}
removeTask = taskId => {
let tasks = this.state.tasks;
let taskToDel = tasks.find(function(element){
if(element._id === taskId) {
return element;
}
});
if(taskToDel) {
// Find index of task to remove
const index = tasks.indexOf(taskToDel);
// If task index is found remove task from array
if(index != -1)
tasks.splice(index, 1);
this.setState({tasks});
}
}
deleteTaskOnDb = task => {
let data = {taskId: task._id};
fetch(`/dashboard/project/${this.props.projectId}/tasks/delete`, {
method: 'delete',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}).then(response => {
//if(response.status === 200)
return response.json()
}).then(taskId => {
this.removeTask(taskId);
}).catch(error => console.error('Error:', error));
}
render() {
//POPOVER FUNCTION HERE
$(function () {
$('[data-toggle="popover"]').popover()
})
//POPOVER FUNCTION HERE
const fontawesomeiconStyle = {
fontSize: '1em',
color: '#bd822a',
textAlign: 'center'
}
const listStyle = {
display:'flex',
flexFlow: 'row wrap',
justifyContent: 'space-between'
}
const { tasks } = this.state;
return (
<div>
<ul className="task-list">
{tasks.map(task =>
<li key={task._id} style={listStyle}> <div>
{task.tasktitle}
<br/>
<p style={{fontSize: '10px', color: '#a2a2a2'}}>{moment(task.created).format('MMM DD YY, h:mm A')} </p>
</div>
<div>
<p style={{fontSize: '12px', color: '#a2a2a2'}}>{task.taskcomment}</p>
</div>
<div>
//BUTTON HERE
<button type="button" className="example-popover btn--delete button--tasks" data-html="true" data-container="body" data-toggle="popover" data-placement="right" data-content="Are you sure? <button type='button' className='btn--delete button--tasks' onClick='{() => this.deleteTaskOnDb(task)}'> Delete</button>">
<FontAwesomeIcon style={fontawesomeiconStyle} icon={faTimes} />
</button>
//BUTTON HERE
</div>
</li>
)}
</ul>
{this.props.project &&
this.props.project._id &&
<NewTask projectId={this.props.project._id} appendTask={this.appendTask}/>
}
</div>
);
}
}
export default Tasks;