StephenChou1017 / react-big-scheduler

A scheduler and resource planning component built for React and made for modern browsers (IE10+)
https://stephenchou1017.github.io/scheduler/#/
MIT License
760 stars 414 forks source link

NEW MAINTAINED FORK #260

Open hbatalhaStch opened 1 year ago

hbatalhaStch commented 1 year ago

I am using this for a project so it has become part of my requirement, so I plan on keep on maintaining this project in this fork. I have already made improvement and fix the performance issues.

wbern commented 1 year ago

Thanks for maintaining this fork.

Do you have any examples that are up-to-date with the changes you made? I noticed a couple of things:

Less important things:

hbatalhaStch commented 1 year ago

...but how do I make sure the styling is still applied properly for the basic example?

In the example the css is imported directly in index.html file After the build the css will be added by the build script.

How did you implement the drag and drop context?

withDnDContext.js

How did you get typings to work for this package?

The build script copies the typings file into dist folder which in this case is going to be the lib folder. This is how the lib folder going to look like: image

From where do I import this package? I am using the src directory now and transpiling from there, but curious if there's a better way.

I plan on publishing the fork tomorrow, the package is going to be named react-big-scheduler-stch

Edit:

Since the fork is not published yet, I have been using the transpiled js in my next.js project using typescript: image

and this is a component I created to use it:

import DemoData from '@/mock/DemoData';
import dayjs, { Dayjs } from 'dayjs';
import React, { Component } from 'react'
import Scheduler, {
    SchedulerData,
    ViewType,
    View,
    EventItem,
    SchedulerDataConfig,
    Resource,
    SchedulerDataBehaviors,
} from './rcbigsch'

interface State {
    viewModel: SchedulerData
}

interface IProps {
    date?: string | Dayjs;
    viewType?: ViewType;
    showAgenda?: boolean;
    isEventPerspective?: boolean;
    newConfig?: SchedulerDataConfig;
    newBehaviours?: SchedulerDataBehaviors;
    schedulerDataConfig?: SchedulerDataConfig;
    resources: Resource[];
    events: EventItem[];
    responsiveByParentWidth?: number;
    responsiveByParentRef?: React.RefObject<HTMLDivElement>;
}

export default class BigScheduler extends Component<IProps, State> {
    constructor(props: IProps) {
        super(props);
        let schedulerData = new SchedulerData(props.date ?? dayjs(),
            props.viewType ?? ViewType.Month,
            props.showAgenda ?? false,
            props.isEventPerspective ?? false,
           props.schedulerDataConfig);
        schedulerData.setSchedulerLocale('pt-br');
        schedulerData.setCalendarPopoverLocale('pt_BR');
        schedulerData.setResources(props.resources);
        schedulerData.setEvents(props.events);
        this.state = {
            viewModel: schedulerData
        }
    }

    render() {
        const { viewModel } = this.state;
        return (
            <div>
                <div>
                    <Scheduler schedulerData={viewModel}
                        responsiveByParentRef={this.props.responsiveByParentRef}
                        responsiveByParentWidth={this.props.responsiveByParentWidth}
                        prevClick={this.prevClick}
                        nextClick={this.nextClick}
                        onSelectDate={this.onSelectDate}
                        onViewChange={this.onViewChange}

                        toggleExpandFunc={this.toggleExpandFunc}
                    />
                </div>
            </div>
        )
    }

    prevClick = (schedulerData: SchedulerData) => {
        schedulerData.prev();
        schedulerData.setEvents(this.props.events);
        this.setState({
            viewModel: schedulerData
        })
    }

    nextClick = (schedulerData: SchedulerData) => {
        schedulerData.next();
        schedulerData.setEvents(this.props.events);
        this.setState({
            viewModel: schedulerData
        })
    }

    onViewChange = (schedulerData: SchedulerData, view: View) => {
        const start = new Date();
        schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective);
        schedulerData.setEvents(this.props.events);
        this.setState({
            viewModel: schedulerData
        })
        function secondsBetween(date1: Date, date2: Date) {
            var diff = Math.abs(date1.getTime() - date2.getTime());
            return diff / 1000;
        }

        console.log("Elapsed seconds: " + secondsBetween(start, new Date()))
    }

    onSelectDate = (schedulerData: SchedulerData, date: string) => {
        schedulerData.setDate(date);
        schedulerData.setEvents(this.props.events);
        this.setState({
            viewModel: schedulerData
        })
    }

    eventClicked = (schedulerData: SchedulerData, event: EventItem) => {
        alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`);
    };

    ops1 = (schedulerData: SchedulerData, event: EventItem) => {
        alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`);
    };

    ops2 = (schedulerData: SchedulerData, event: EventItem) => {
        alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`);
    };

    toggleExpandFunc = (schedulerData: SchedulerData, slotId: string) => {
        schedulerData.toggleExpandStatus(slotId);
        this.setState({
            viewModel: schedulerData
        });
    }
}

beware that I had to dynamically import it.

wbern commented 1 year ago

Thank you so much, will have a look at this and let you know how it went.

wbern commented 1 year ago

I used your examples and got CSS and other things to work. Great job!

My only challenge now is that I want a responsive table based on my grid content, and responsiveByParentWidth does not seem to work at all as advertised.

I am using mui and Grid containers, and I just want the table to adjust to the size of the parent grid, but it seems to be always taking up too much space on the sides.

Do you have any approach there that you'd like to share?

hbatalhaStch commented 1 year ago

I have removed responsiveByParentWidth as it was not ideal. Instead I have added:

image

I also have published the fork: https://www.npmjs.com/package/react-big-scheduler-stch

Could you test it and give me a feedback?

wbern commented 1 year ago

I'm working on incorporating this scheduler off and on, I will publish my complete example when done.

It would be nice if there were examples of how to use it with hooks but hopefully I'll figure it out anyway.

hbatalhaStch commented 1 year ago

I tried once to get it to work with hooks but I wasn't successful and as I was need it immediately I just switch to class component for the time being, so examples are not available at the moment. When you figure it out please share with us.

hbatalhaStch commented 1 year ago

@wbern here is a quick working TS example (I did some basic tests only), it should be a good starting point hopefully:

import dayjs, { Dayjs } from 'dayjs';
import React, { useEffect, useState } from 'react';
import Scheduler, {
    EventItem, Resource, SchedulerData, SchedulerDataBehaviors, SchedulerDataConfig, View, ViewType
} from 'react-big-scheduler-stch';

interface IProps {
    date?: string | Dayjs;
    viewType?: ViewType;
    showAgenda?: boolean;
    isEventPerspective?: boolean;
    newConfig?: SchedulerDataConfig;
    newBehaviours?: SchedulerDataBehaviors;
    schedulerDataConfig?: SchedulerDataConfig;
    resources: Resource[];
    events: EventItem[];
    parentRef?: React.RefObject<any>;
}

function BigScheduler(props: IProps) {
    const [schedulerData, setSchedulerData] = useState(new SchedulerData(props.date ?? dayjs(),
        props.viewType ?? ViewType.Month,
        props.showAgenda ?? false,
        props.isEventPerspective ?? false,
        props.schedulerDataConfig,
    ))

    useEffect(() => {
        schedulerData.setResources(props.resources);
        schedulerData.setEvents(props.events);
    })

    const prevClick = (schedulerData: SchedulerData) => {
        schedulerData.prev();
        schedulerData.setEvents(props.events);
        setSchedulerData(schedulerData)
    }

    const nextClick = (schedulerData: SchedulerData) => {
        schedulerData.next();
        schedulerData.setEvents(props.events);
        setSchedulerData(schedulerData)
    }

    const onViewChange = (schedulerData: SchedulerData, view: View) => {
        schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective);
        schedulerData.setEvents(props.events);
        setSchedulerData(schedulerData)
    }

    const onSelectDate = (schedulerData: SchedulerData, date: string) => {
        schedulerData.setDate(date);
        onDateChange(schedulerData)
        schedulerData.setEvents(props.events);
        setSchedulerData(schedulerData)

    }

    const eventClicked = (schedulerData: SchedulerData, event: EventItem) => {

    };

    const toggleExpandFunc = (schedulerData: SchedulerData, slotId: string) => {
        schedulerData.toggleExpandStatus(slotId);
        setSchedulerData(schedulerData)
    }

    return (
        <Scheduler
            parentRef={props.parentRef}
            prevClick={prevClick}
            nextClick={nextClick}
            onSelectDate={onSelectDate}
            onViewChange={onViewChange}
            toggleExpandFunc={toggleExpandFunc}
            eventItemClick={eventClicked}
            schedulerData={schedulerData}
        />
    )
}

export default BigScheduler