Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: resize events #382

Closed
pnkflydgr opened this issue May 7, 2017 · 14 comments
Closed

Feature request: resize events #382

pnkflydgr opened this issue May 7, 2017 · 14 comments

Comments

@pnkflydgr
Copy link

When will the ability to resize events be added?

I don't mind attempting to write it if someone could point me in the right direction. I've been coding for a long time but I'm fairly new to react.

@jquense
Copy link
Owner

jquense commented May 7, 2017

No plans right now to add it but it would make a good add-on like drag and drop if you want to give it a shot

@pnkflydgr
Copy link
Author

pnkflydgr commented May 7, 2017

Can you just tell me which component I would need to override to control events? Is there already something there like for customView.js.

I would love to write it so it could be used like this (the mouse resize cursor would occur if(onResize()):

<DragAndDropCalendar
   events={this.props.events}
    style={{height: 800}}
    selectable='ignoreEvents'
    defaultView='week'
    scrollToTime={new Date(1970, 1, 1, 8)}
    onResize={event => { //stuff }}
/>

@AgamlaRage
Copy link

AgamlaRage commented May 8, 2017

+1 for this feature !
I didn't dig too much in the core yet, but if I will start somewhere, it will be in the selection system.
Maybe it can be use to acheive that.

screen

@gazab
Copy link

gazab commented May 8, 2017

Or should it be implemented as part of the drag and drop addon? Resizing and moving are rather similar..

Either way, I would also love this feature!

@jnmandal
Copy link

This is something I currently need so I'm taking a stab at it now. My plan is to add it as part of the dnd addon, taking advantage of the components prop to pass in a gcal-like resize anchor.

@pnkflydgr
Copy link
Author

Thanks @jnmandal for picking this up. I had got to the point where I had decided to just make another component for dnd. Don't have a lot of time right now.

@AgamlaRage
Copy link

AgamlaRage commented May 22, 2017

I quickly did something about that. That is working but there is a too heavy render lifecycle in my project to be fully usable. (Sorry, I worked on the compiled files, because I need to live test it on my app, then I didn't do a PR for now).
See .gif at the bottom.

  • This can also be use, to render a drag preview, when you are dragging an event.
  • You can still use onEventDrop callback at the end of the resizing (for ajx request by example)

react-big-calendar modifications

lib/addons/dragAndDrop/index.js

1 - Create and pass through props the new onEventResize callback (following the same road as onEventDrop) callback

lib/addons/dragAndDrop/backgroundWrapper.js

1 - receive onEventResize. line95

2 - add hover() react-dnd dropTarget spec. line111

hover: function hover(_, monitor, _ref) {

      var props = _ref.props,
          context = _ref.context;

      var item = monitor.getItem();
      var itemType = monitor.getItemType();
      var value = props.value;
      var onEventResize = context.onEventResize;

      if ((!window.reactBigCalendarResizerValue || window.reactBigCalendarResizerValue.toString() !== value.toString())) {
        window.reactBigCalendarResizerValue = value; // store value to not trigger event each time

        onEventResize(itemType, item, value); // calback
      }
    }

IMPORTANT: Here i used a global var window.reactBigCalendarResizerValue to store the current hovered cel datel, and not trigger the custom callback several time on the same cell.
Need to use a special component var, but don't really know where to put it

3 - add a new target event-resize to the DropTarget, to be able to make the difference between moving and resizing an event. line126

// return DropTarget(['event'], dropTarget, collectTarget)(DraggableBackgroundWrapper);
return DropTarget(['event', 'event-resize'], dropTarget, collectTarget)(DraggableBackgroundWrapper);

API modification

1 - The onEventResize(itemType, event, value) callback is now available on bigcalendar.
And will be triggered when you drag a react-dnd dragSource onto it;

  • itemType: oneOf(['event, 'event-resize'])
  • event: your event
  • value: the current hovered cell date
    // CUSTOM CALLBACK
    this.onEventResize = (itemType, event, value) => {
      console.log('onEventResize', event, value);

      // make date calculation and update bigcalendar events
      // I don't provied this section of code because it's your API, 
      // and I think my problem of speed is from here
    };

    // RENDER CALENDAR
    <BigCalendar
      onEventResize={this.onEventResize}
    />

2 - Create the event-resize dragSource. That will wrap your resizer

import React from 'react';
import PropTypes from 'prop-types';
import { DragSource } from 'react-dnd';
import { getEmptyImage } from 'react-dnd-html5-backend';


class BigCalendarResizerDraggableBox extends React.Component {

  componentDidMount() {
    // Use empty image as a drag preview so browsers don't draw it
    // and we can draw whatever we want on the custom drag layer instead.
    this.props.connectDragPreview(getEmptyImage(), {
      // IE fallback: specify that we'd rather screenshot the node
      // when it already knows it's being dragged so we can hide it with CSS.
      captureDraggingState: true,
    });
  }

  render() {
    const { children, connectDragSource } = this.props;
    return connectDragSource(children);
  }

  static propTypes = {
    children: PropTypes.node.isRequired,
    connectDragSource: PropTypes.func.isRequired,
  };
}

export default DragSource(
  'event-resize',
  {
    beginDrag(props) { // pass props to DragLayer, getting with monitor.getItem()
      console.log('beginDrag');
      return props.event;
    },
    endDrag(props) { // pass props to DragLayer, getting with monitor.getItem()
      console.log('endDrag');
      return { endDrag: true };
    },
  },
  (connect, monitor) => ({
    connectDragSource: connect.dragSource(),
    // isDragging: monitor.isDragging(),
    // item: monitor.getItem(),
    // itemType: monitor.getItemType(),
    // dropResult: monitor.getDropResult(),
    // didDrop: monitor.didDrop(),
    // differenceFromInitialOffset: monitor.getDifferenceFromInitialOffset(),
    connectDragPreview: connect.dragPreview(), // prevent from displaying ghost image
  })
)(BigCalendarResizerDraggableBox);

3 - Wrap a Resizer component into it. And render it at the end of your custom EventComponent

<BigCalendarResizerDraggableBox event={event}>
     <div className="rbc-resizer"></div>
</BigCalendarResizerDraggableBox>
.rbc-resizer {
     position: absolute;
     left: 0;
     right: 0;
     bottom: 0;
     height: 8px;
     overflow: hidden;
     line-height: 8px;
     font-size: 11px;
     font-family: monospace;
     text-align: center;
     cursor: s-resize;
     user-drag: none;

      &::after {
        content: '=';
      }
    }

Result.

I did it slowly, then maybe you don't see that is raming.
Maybe the lifecycle problem I have is due to my system to live update the event on the calendar. (Taking too much time to find event and calculate date ... etc)

screen

@AgamlaRage
Copy link

Someone tried the code I provied ?

I realised that I only made test in development mode, when I tested it in production it was really better, still not as fast as GoogleCalendar or FullCalendar, but way more viable.

If my code if working for someone else, I will make a PR.

@dtmunir
Copy link

dtmunir commented Sep 27, 2017

@AgamlaRage this looks really good. Would love to take this for a spin @andela-koni

@arecvlohe
Copy link
Collaborator

@AgamlaRage I wasn't not able to get my implementation to work as smoothly as yours. Are you handling the update on drop and hover?

@AgamlaRage
Copy link

AgamlaRage commented Oct 5, 2017

Hey everyone, sorry to be late !
I'll do this PR today. The code is still working fine.

@arecvlohe Maybe you have some components that you use in your Calendar that you have to control the update. As I say before, the render lifecycles of the DnD component are HUGE.

In my code I have a fine control using shoulComponentUpdate() almost in each components, and I use a global var window.reactBigCalendarResizerValue to not trigger the render if you hover the same cell too long.

@dtmunir
Copy link

dtmunir commented Oct 5, 2017 via email

@arecvlohe
Copy link
Collaborator

arecvlohe commented Oct 5, 2017

@AgamlaRage I see now, that's a good idea using sCU on each component! Before you get too far take a look at my branch that implements this with help from @jnmandal and his commits. This is being worked on over at #406. It would be good to get your feedback or to tidy this up with your ideas/improvements.

feature/events-resize

@AgamlaRage
Copy link

@arecvlohe Too late ! :o

I just make it, I will have a look at this #406 tomorrow I think.

The PR #577 is not perfect yet, I still have some improvments to make, but it's working.
I add an example page so you can try it.

Or see in action

alt text

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants