InteractionDesignFoundation / add-event-to-calendar-docs

📅 Docs how to generate links to add events to online calendar services
https://interactiondesignfoundation.github.io/add-event-to-calendar-docs/
MIT License
428 stars 57 forks source link

Use new URL and data formats for outlook #11

Closed alies-dev closed 4 years ago

alies-dev commented 4 years ago

outlook has changed formats of dates and URL to add an event

Previous PR: #10

alies-dev commented 4 years ago
// webpack://owa/packages/calendar-common/owa-calendar-compose-form-store/lib/actions/initActions/showFullComposeFromDeeplink.ts
import { action } from 'satcheljs/lib/legacy';
import { getQueryStringParameters } from 'owa-querystring';
import { getOrigin } from 'owa-url';
import { CalendarEvent } from 'owa-calendar-types';
import { HtmlSanitizer } from 'roosterjs-html-sanitizer';
import { owaDate } from 'owa-datetime';
import { getUserConfiguration } from 'owa-session-store';
import EnhancedLocation from 'owa-service/lib/contract/EnhancedLocation';
import showFullComposeInEditMode from './showFullComposeInEditMode';
import EventScope from 'owa-service/lib/contract/EventScope';
import { FULL_COMPOSE_VIEW_TYPE_MODAL } from 'owa-calendar-helpers-types/lib/ComposeTypes';
import processRecipientsFromUrlParameter from 'owa-recipient-email-address/lib/utils/processRecipientsFromUrlParameter';
import AttendeeType from 'owa-service/lib/contract/AttendeeType';
import EmailAddressWrapper from 'owa-service/lib/contract/EmailAddressWrapper';

const SUBJECT_QUERYSTRING_KEY = 'subject';
const BODY_QUERYSTRING_KEY = 'body';
const START_DATE_QUERYSTRING_KEY = 'startdt';
const END_DATE_QUERYSTRING_KEY = 'enddt';
const ALL_DAY_QUERYSTRING_KEY = 'allday';
const LOCATION_QUERYSTRING_KEY = 'location';
const IS_ONLINE_MEETING = 'online';
const REQUIRED_ATTENDEES = 'to';
const OPTIONAL_ATTENDEES = 'cc';

/**
 * This action is called when we want to show full compose in deeplink scenario.
 * This does not need any parameters since we pick the parameters from the url parameters
 */
export default action('showFullComposeFromDeeplink')(
    async function showFullComposeFromDeeplink(): Promise<void> {
        const params = getQueryStringParameters();

        let event: CalendarEvent = {} as CalendarEvent;

        if (params[SUBJECT_QUERYSTRING_KEY]) {
            event.Subject = HtmlSanitizer.sanitizeHtml(params[SUBJECT_QUERYSTRING_KEY]);
        }

        if (params[BODY_QUERYSTRING_KEY]) {
            event.Body = {
                BodyType: 'HTML',
                Value: HtmlSanitizer.sanitizeHtml(params[BODY_QUERYSTRING_KEY]),
            };
        }

        const { UserOptions } = getUserConfiguration();
        const timeZone = UserOptions?.TimeZone;
        if (params[START_DATE_QUERYSTRING_KEY]) {
            try {
                event.Start = owaDate(timeZone, params[START_DATE_QUERYSTRING_KEY]);
            } catch {
                // Do nothing. If we cannot parse startdt, then we let the form set the default start
            }
        }

        if (params[END_DATE_QUERYSTRING_KEY]) {
            try {
                event.End = owaDate(timeZone, params[END_DATE_QUERYSTRING_KEY]);
            } catch {
                // Do nothing. If we cannot parse enddt, then we let the form set the default end
            }
        }

        if (params[ALL_DAY_QUERYSTRING_KEY]) {
            event.IsAllDayEvent = params[ALL_DAY_QUERYSTRING_KEY].toLowerCase() == 'true';
        }

        if (params[LOCATION_QUERYSTRING_KEY]) {
            event.Locations = [
                {
                    Id: params[LOCATION_QUERYSTRING_KEY],
                    DisplayName: params[LOCATION_QUERYSTRING_KEY],
                    PostalAddress: {
                        Type: 'Business',
                        LocationSource: 'None',
                    },
                } as EnhancedLocation,
            ];
        }

        if (IS_ONLINE_MEETING in params) {
            event.IsOnlineMeeting = true;
        }

        if (params[REQUIRED_ATTENDEES] || params[OPTIONAL_ATTENDEES]) {
            const convertEmailsToAttendeeTypes = (
                emails: EmailAddressWrapper[]
            ): AttendeeType[] => {
                return emails.map(email => <AttendeeType>{ Mailbox: email });
            };

            if (params[REQUIRED_ATTENDEES]) {
                let requiredAttendeesEmails: EmailAddressWrapper[] = [];
                processRecipientsFromUrlParameter(
                    params[REQUIRED_ATTENDEES],
                    requiredAttendeesEmails
                );
                event.RequiredAttendees = convertEmailsToAttendeeTypes(requiredAttendeesEmails);
            }

            if (params[OPTIONAL_ATTENDEES]) {
                let optionalAttendeesEmails: EmailAddressWrapper[] = [];
                processRecipientsFromUrlParameter(
                    params[OPTIONAL_ATTENDEES],
                    optionalAttendeesEmails
                );
                event.OptionalAttendees = convertEmailsToAttendeeTypes(optionalAttendeesEmails);
            }
        }

        // cleaning up url parameters so that they don't stay in the url
        const newUrl = `${getOrigin()}${location.pathname}`;
        window.history.replaceState(null, null, newUrl);

        return showFullComposeInEditMode(
            event,
            EventScope.Default,
            null /* itemHasUpdates */,
            'Deeplink_Compose' /* FullComposeEntrySourceType */,
            FULL_COMPOSE_VIEW_TYPE_MODAL /* FullComposeFormViewType */,
            null /* extractionSourceId */
        );
    }
);