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

[MM-595] Add feature to view shared calendars while creating an event #86

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion gcal/calendar.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,25 @@ func (c *client) DeleteCalendar(remoteUserID string, calID string) error {

// GetCalendars returns a list of calendars
func (c *client) GetCalendars(remoteUserID string) ([]*remote.Calendar, error) {
return nil, errors.New("gcal GetCalendars not implemented")
service, err := calendar.NewService(context.Background(), option.WithHTTPClient(c.httpClient))
if err != nil {
return nil, errors.Wrap(err, "gcal GetCalendars, error creating service")
}

res, err := service.CalendarList.List().Do()
if err != nil {
return nil, errors.Wrap(err, "gcal GetCalendars, error getting list of calendars")
}

calendarList := []*remote.Calendar{}
for _, calendar := range res.Items {
calendarList = append(calendarList, &remote.Calendar{
ID: calendar.Id,
Name: calendar.Summary,
})
}

return calendarList, nil
}

// GetDefaultCalendar returns the default calendar for the user
Expand Down
9 changes: 6 additions & 3 deletions gcal/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@ func (c *client) GetEvent(remoteUserID, eventID string) (*remote.Event, error) {
}

// CreateEvent creates a calendar event
func (c *client) CreateEvent(_ string, in *remote.Event) (*remote.Event, error) {
func (c *client) CreateEvent(calendarID, _ string, in *remote.Event) (*remote.Event, error) {
service, err := calendar.NewService(context.Background(), option.WithHTTPClient(c.httpClient))
if err != nil {
return nil, errors.Wrap(err, "gcal CreateEvent, error creating service")
}

evt := convertRemoteEventToGcalEvent(in)

calendar := defaultCalendarName
if calendarID != "" {
calendar = calendarID
}
resultEvent, err := service.Events.
Insert(defaultCalendarName, evt).
Insert(calendar, evt).
SendUpdates("all"). // Send notifications to all attendees.
Do()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/mattermost/mattermost-plugin-google-calendar
go 1.21

require (
github.com/mattermost/mattermost-plugin-mscalendar v1.3.0
github.com/mattermost/mattermost-plugin-mscalendar v1.2.2-0.20240717132440-5de872875282

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have we updated this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was needed to link with the mscalendar changes for the API. We will update this once we merge the PR mattermost/mattermost-plugin-mscalendar#379

github.com/mattermost/mattermost/server/public v0.1.1
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.9.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956 h1:Y1Tu/swM31pVwwb
github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956/go.mod h1:SRl30Lb7/QoYyohYeVBuqYvvmXSZJxZgiV3Zf6VbxjI=
github.com/mattermost/logr/v2 v2.0.21 h1:CMHsP+nrbRlEC4g7BwOk1GAnMtHkniFhlSQPXy52be4=
github.com/mattermost/logr/v2 v2.0.21/go.mod h1:kZkB/zqKL9e+RY5gB3vGpsyenC+TpuiOenjMkvJJbzc=
github.com/mattermost/mattermost-plugin-mscalendar v1.3.0 h1:5X/J7O956A0uqENvDTrNVgLqWNuBKKXDE5jqlrbOCCY=
github.com/mattermost/mattermost-plugin-mscalendar v1.3.0/go.mod h1:aIO3y2VNX7VRmI2wvos8MFywGoqFp3zKH6QgyAJMEMQ=
github.com/mattermost/mattermost-plugin-mscalendar v1.2.2-0.20240717132440-5de872875282 h1:8vFteChSYt654Ae+EUrRz/l+bIroAB3pyq4q8V34CsQ=
github.com/mattermost/mattermost-plugin-mscalendar v1.2.2-0.20240717132440-5de872875282/go.mod h1:0QMN1lB9ChMWlJzUvC4JPvuAQ882hhwIWwT2kW7GAvo=
github.com/mattermost/mattermost/server/public v0.1.1 h1:T5UtZ0SB3rZvhiKFUxkPn4fNrEQTXAcmCHVkRct1dpk=
github.com/mattermost/mattermost/server/public v0.1.1/go.mod h1:WeqCPudYLqk4HjjGvCMJwhtHMVvcNUTHIbrLmLjAD+4=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
Expand Down
21 changes: 21 additions & 0 deletions webapp/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,27 @@ export const autocompleteUserChannels = (input: string, teamId: string) => async
}
};

type Calendar = {
id: string;
name: string;
}

export type CalendarListResponse = {data?: Calendar[]; error?: string};

export const fetchCalendarList = () => async (dispatch, getState): Promise<CalendarListResponse> => {
const state = getState();
const pluginServerRoute = getPluginServerRoute(state);

return doFetchWithResponse(`${pluginServerRoute}/api/v1/calendar/list`).
then((response) => {
return {data: response.data};
}).
catch((response) => {
const error = response.message?.error || 'An error occurred while fetching calendars list.';
return {data: [], error};
});
};

export type CreateCalendarEventResponse = {data?: any; error?: string};

export const createCalendarEvent = (payload: CreateEventPayload) => async (dispatch, getState): Promise<CreateCalendarEventResponse> => {
Expand Down
65 changes: 65 additions & 0 deletions webapp/src/components/calendar_selector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React, {useCallback, useState} from 'react';
import {useSelector, useDispatch} from 'react-redux';

import AsyncSelect from 'react-select/async';

import {getTheme} from 'mattermost-redux/selectors/entities/preferences';

import {getStyleForReactSelect} from '@/utils/styles';
import {CalendarListResponse, fetchCalendarList} from '@/actions';

type SelectOption = {
label: string;
value: string;
}

type Props = {
onChange: (selected: string) => void;
value: string[];
};

export default function CalendarSelector(props: Props) {
const [storedError, setStoredError] = useState('');

const theme = useSelector(getTheme);

const dispatch = useDispatch();

const loadOptions = useCallback(async (): Promise<SelectOption[]> => {
const response = (await dispatch(fetchCalendarList()) as unknown as CalendarListResponse);

if (response.error) {
setStoredError(response.error);
return [];
}

setStoredError('');

return response.data.map((c) => ({
label: c.name,
value: c.id,
}));
}, []);

const handleChange = (selected: SelectOption) => {
props.onChange(selected.value);
};

return (
<>
<AsyncSelect
value={props.value}
loadOptions={loadOptions}
defaultOptions={true}
menuPortalTarget={document.body}
menuPlacement='auto'
onChange={handleChange}
styles={getStyleForReactSelect(theme)}
isMulti={false}
/>
{storedError && (
<span className='error-text'>{storedError}</span>
)}
</>
);
}
10 changes: 10 additions & 0 deletions webapp/src/components/modals/create_event_form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {CreateCalendarEventResponse, createCalendarEvent} from '@/actions';
import {getTodayString} from '@/utils/datetime';

import './create_event_form.scss';
import CalendarSelector from '../calendar_selector';

type Props = {
close: (e?: Event) => void;
Expand All @@ -46,6 +47,7 @@ export default function CreateEventForm(props: Props) {
description: '',
channel_id: '',
location: '',
calendar_id: '',
});

const setFormValue = <Key extends keyof CreateEventPayload>(name: Key, value: CreateEventPayload[Key]) => {
Expand Down Expand Up @@ -167,6 +169,14 @@ const ActualForm = (props: ActualFormProps) => {
const theme = useSelector(getTheme);

const components = [
{
label: 'Calendar (optional)',
component: (
<CalendarSelector
onChange={(selected) => setFormValue('calendar_id', selected)}
/>
),
},
{
label: 'Subject',
required: true,
Expand Down
1 change: 1 addition & 0 deletions webapp/src/types/calendar_api_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export type CreateEventPayload = {
subject: string;
location?: string;
channel_id?: string;
calendar_id?: string;
}