W ostatnim wpisie związanym z projektem dodałem do aplikacji Reduxa. Jednak samo dodanie go nie spowoduje, że w aplikacji zacznie się coś dziać. Czas na trochę akcji.

Światła, kamera, akcja

Na początek krótkie przypomnienie z ostatniego wpisu. Akcja jest to jedyny sposób by zmienić stan naszej aplikacji. Są więc jej koniecznym elementem. Póki co zdefiniowałem jedną akcję, która będzie najczęściej wykonywana czyli zaznaczanie godzin pracy w kalendarzu. Zacząłem od stworzenia następującej funkcji:

export const addEvent = (newEvent) => {

  return {

    type: 'ADD_EVENT',

    description: Math.abs(newEvent.end -newEvent.start) / 36e5,

    start_date: newEvent.start.toUTCString(),

    end_date: newEvent.end.toUTCString()

  }

}

Jej zadaniem jest przygotowanie odpowiednich danych dla reducera. Zwraca ona tylko to co jest potrzebne do obsłużenia wywołanej akcji. Obiekt przygotowany przez tę funkcje ląduje w reducerze gdzie jest obsługiwany. Plik reducera wygląda następująco:

const calendar = (state =[], action) => {

    switch (action.type) {

        case 'ADD_EVENT': {

            return [

                ...state,

                {

                    'title': action.description,

                    'start': new Date(action.start_date),

                    'end':new Date(action.end_date)

                }

            ]

        }

        default:

            return state;

    }

}

Nasz obiekt jest dostępny pod zmienną action skąd mamy dostęp do wszystkich pól zdefiniowanych w akcji. Sama funkcja reducera jest bardzo prosta i jej głównym elementem jest switch, którym decydujemy co zrobić w zależności od typu akcji. Elementem, który zasługuje na chwilę uwagi jest sposób zwracania nowego stanu. Jako, że głównym założeniem reduxa jest brak mutowania jakichkolwiek elementów to nie możemy bezpośrednio zmienić naszego stanu tylko musimy zwrócić zupełnie nowy obiekt, który zawiera elementy poprzednie oraz ten nowo dodany.

Akcja w widoku

Teraz wystarczy połączyć to wszystko z kalendarzem. Zacząłem od pliku calendar.container. Musiałem w nim zdefiniować funkcję za pomocą której będę wywoływał moją akcje:

const mapDispatchToProps = (dispatch) => {

  return {

    onAddEvent: (newEvent) => { dispatch(addEvent(newEvent)) },

  }

}

Zapis, którego użyłem znaczy, że w momencie wywołania funkcji onAddEvent zostanie wywołana akcja addEvent z parametrem, który przekazaliśmy. Pierwsze co musiałem zrobić w pliku calendar.component to dodać następującą linijkę:

const { calendar, onAddEvent } = this.props;

Dzięki temu mogę korzystać ze zmiennej calendar, która jest obiektem stanu dla mojego komponentu oraz onAddEvent, która jest wyżej zdefiniowaną funkcją.Teraz wystarczy wykorzystać to co daje nam react-big-calendar. Aktualnie wygląda on tak:

return (

            <div className="calendar">

                <BigCalendar

                    ref='calendar'

                    selectable={this.state.selectable}

                    defaultView='week'

                    onView={this.onViewChange}

                    events={calendar}

                    onSelectSlot={(event) => onAddEvent(event)}

                />

            </div>

        )

Pierwszym krokiem było dodanie opcji selectable do komponentu. Pozwala to na zaznaczanie pól na kalendarzu. Jako, że chciałem zaznaczać pola tylko w widoku tygodniowym to wykorzystałem opcję onView która wywołuje przekazaną funkcję za każdym razem gdy zmieni się typ widoku.

onViewChange = (event) => {

        if (event === 'week') {

           this.setState({selectable:true})

        } else {

            this.setState({selectable:false})

        }

    

    };

No i najważniejsza opcja onSelectSlot, która powoduje wywołanie przekazanej funkcji za każdym razem gdy coś się zaznaczy na kalendarzu.

Jak widać tworzenie akcji nie jest takie ciężkie. Teraz za każdym razem gdy będę chciał dodać nową akcję to będę postępował w identyczny sposób. Najwięcej problemów tutaj sprawiło mi nie tworzenie akcji a połączenie tego z kalendarzem i dostosowanie widoku do swoich wyobrażeń. Efekt moich prac jest dostępny tutaj. Teraz  chciałbym się trochę pobawić pythonem i stworzyć na jego podstawie serwer api. Tak więc do zobaczenia wkrótce we wpisie dotyczącym podstaw pythona.