# Calendar Sync

The Calendar Sync element is an interactive display of your profile synchronization status.

If you have not yet connected any profiles, it will show you authorization links for supported providers (Google, iCloud, Office 365, Outlook, and Exchange). For editable account types, you can also add new accounts and disconnect existing ones within the element's UI. If you have already connected one or more profiles, a list of those profiles will be displayed along with the synchronization status for each profile which can be one of the following:

- `active` - the calendar is syncing.

- `pending` - the initial sync of the calendar has not completed yet.

- `disconnected` - the calendar profile is disconnected (usually due to expired credentials, awaiting relinking). This means that a relink is required, and the element will display a relink button.

### Demo
*(Interactive UI element — see the HTML version for the live demo)*

## Example initialization
```html
<div id="cronofy-calendar-sync"></div>
<script src="https://elements.cronofy.com/js/CronofyElements.v1.67.6.js"></script>
<script>
    CronofyElements.CalendarSync({
        target_id: "cronofy-calendar-sync",
        authorization: {
            redirect_uri: "https://example.org/oauth/redirect",
            client_id: "XXX",
            scope: "read_only"
        },
        styles: {
            prefix: "CalendarSync"
        }
    });
</script>
```

### Element permissions
`account_management` is required when generating the [Element Token](/developers/ui-elements/authentication/index.md). The Element Token used should be for a single `sub` only.

If the user is connecting for the first time, you should not generate a token, and should omit it from the Element's configuration.

### Adding profiles
The Calendar Sync element includes the ability to add new calendar accounts. This option is available when the `cronofy.type` is `account` which can be viewed in the [callback](#param-callback) response.  Users start the authorization flow by clicking one of the authorization links (exposed by clicking the "Add calendar account" button). When the process is complete, the user is returned to the `redirect_uri` with a `code` included as a URL parameter. This `code` should then be used to request an [access token](/developers/api/authorization/request-token/index.md).

> **WARNING:** The new access token is not required within the element, but needs to be requested to complete the authorization process. This request requires your Client ID and Client Secret, so must take place server-side. This request is therefore not handled by the Calendar Sync element.

### CalendarSync options
##### `element_token` *(optional)*

The [Element Token](/developers/ui-elements/authentication/index.md) the
Calendar Sync Element will use to communicate with Cronofy.

*Not required if the Element is activated in demo mode, and must be omitted if the user is
connecting for the first time.*

##### `target_id` *(required)*

The ID of the DOM node the Element will be loaded in to.

##### `authorization` *(required)*

An object containing the params needed to create an authorization link (used when connecting new profiles). `redirect_uri`, `client_id`, and `scope` are required, but every param you add here will be added to the query string of the generated authorization URL. Full details can be found in the [Authorization](/developers/api/authorization/request-authorization/index.md) section.

##### `authorization.redirect_uri` *(required)*

The HTTP or HTTPS URI you wish the user’s authorization request decision to be redirected to. Full details can be found here: [redirect_uri](/developers/api/authorization/request-authorization/index.md).

##### `authorization.client_id` *(required)*

The client_id issued to you by Cronofy to authenticate your OAuth Client. Authenticates you as a trusted client.

##### `authorization.scope` *(required)*

The scope of the privileges you want the eventual access_token to grant. Full details can be found [in the scopes list](/developers/api/authorization/request-authorization/index.md).

##### `authorization_url` *(optional)*

It is possible to explicitly declare your own authorization url, and bypass the built-in authorization link. The user-selected provider will be appended to the `authorization_url` as a query string (for example, when clicking the link to add a Google provider, the following will be appended to the url: `?provider_name=google`).

Declaring an `authorization_url` removes the need for the `authorization` options outlined above, although any `authorization` options you *do* declare will be appended as query parameters to the `authorization_url`.

##### `data_center` *(optional)*

Designates the Cronofy data center the Element will communicate with.

Default value is `us`.

##### `locale` *(optional)*

The Calendar Sync element supports localization (e.g. `locale: &quot;fr&quot;` to load in French). Defaults to browser language setting.

Supported locales (languages) for the UI Elements are:

- `ar` Arabic

- `cs` Czech

- `cy` Welsh

- `de` German

- `en` US English (default)

- `es` Spanish

- `fr` French

- `fr-CA` Canadian French

- `he` Hebrew

- `it` Italian

- `ja` Japanese

- `nl` Dutch

- `pl` Polish

- `pt-BR` Brazilian Portuguese

- `ru` Russian

- `sv` Swedish

- `tr` Turkish

- `zh-CN` Simplified Chinese

##### `translations` *(optional)*

To override either a locale or a particular string, pass in a translations object here. The Calendar Sync element uses the `calendar_sync` translation "context".

[Read more about customizing translations](/developers/ui-elements/customization/index.md)

##### `single_profile` *(optional)*

Limits the number of profiles that can be added using the Element to 1. Will still display all linked profiles (no matter how many there are) and will allow those profiles to be edited/removed, but will prevent any more from being added. Defaults to `false`.

This sets [`avoid_linking`](/developers/api/authorization/request-authorization/index.md) to `true`, so the element will avoid linking calendar accounts together under one set of credentials.

[Read more about avoid_linking](/developers/api/authorization/request-authorization/index.md)

##### `callback` *(optional)*

The function to be called when an action has occurred within the Element. Receives an object in the format:

```json
{
    "notification": {
        "type": "notification_type"
    },
    "userinfo": {
        "sub": "acc_5700a00eb0ccd07000000000",
        "email": "janed@company.com",
        "name": "Jane Doe",
        "zoneinfo": "Europe/London",
        "cronofy.type": "account",
        "cronofy.data": {
            "authorization": {
                "scope": "read_write"
            },
            "profiles": [
                {
                    "provider_name": "google",
                    "profile_id": "pro_n23kjnwrw2",
                    "profile_name": "example@cronofy.com",
                    "profile_connected": true,
                    "profile_initial_sync_required": true,
                    "profile_calendars": [
                        {
                            "calendar_id": "cal_n23kjnwrw2_jsdfjksn234",
                            "calendar_name": "Home",
                            "calendar_readonly": false,
                            "calendar_deleted": false,
                            "calendar_primary": true,
                            "permission_level": "sandbox"
                        },
                        {
                            "calendar_id": "cal_n23kjnwrw2_n1k323nkj23",
                            "calendar_name": "Work",
                            "calendar_readonly": true,
                            "calendar_deleted": true,
                            "calendar_primary": false,
                            "permission_level": "sandbox"
                        }
                    ]
                }
            ]
        }
    }
}
```

The object will include a `notification` object and [a current `userinfo` object](/developers/api/identity/userinfo/index.md) when the `userinfo` has changed. The `notification` object will always have a `type` attribute to allow you to determine how to handle it. Your application should ignore notifications it does not understand as new ones may be added in future.

###### profile_revoked
Alongside the `type` of `profile_revoked` will be the details of the profile from before its revocation:

```json
{
    "notification": {
        "type": "profile_revoked",
        "profile": {
            "provider_name": "apple",
            "profile_id": "pro_fe145c37de",
            "profile_name": "example@cronofy.com",
            "profile_connected": true,
            "profile_initial_sync_required": false,
            "profile_calendars": [
                {
                  "calendar_id": "cal_fe145c37de_3nkj23wejk1",
                  "calendar_name": "Bank Holidays",
                  "calendar_readonly": true,
                  "calendar_deleted": false,
                  "calendar_primary": false,
                  "permission_level": "sandbox"
                }
            ]
        }
    },
    "userinfo": {
        ...
    }
}
```

###### profile_revoke_pressed
This callback is invoked when the user presses the revoke button. This doesn't change the `userinfo` and so it's not included in the callback.

```json
{
    "notification": {
        "type": "profile_revoke_pressed",
        "profile": {
            "provider_name": "apple",
            "profile_id": "pro_fe145c37de",
            "profile_name": "example@cronofy.com",
            "profile_connected": true,
            "profile_initial_sync_required": false,
            "profile_calendars": [
                {
                  "calendar_id": "cal_fe145c37de_3nkj23wejk1",
                  "calendar_name": "Bank Holidays",
                  "calendar_readonly": true,
                  "calendar_deleted": false,
                  "calendar_primary": false,
                  "permission_level": "sandbox"
                }
            ]
        }
    }
}
```

##### `styles` *(optional)*

An object that controls the pre-packaged element styles.

##### `styles.colors` *(optional)*

Use these options to set the colors for various parts of the Element without the need to add your own custom CSS. Each color option accepts either a valid HEX code (e.g. `available: &quot;#FF0000&quot;`) or a browser-safe color name (e.g. `available: &quot;tomato&quot;`)

- `hairline` - horizontal rules and link borders. Defaults to `&quot;#D8D8D8&quot;`

- `primary` - button background color. Defaults to `&quot;#15B3D6&quot;`

##### `styles.prefix` *(optional)*

Customizable elements are given a prefixed class name using this value. For example, if the `prefix` was set as "Foo", the class name on a slot element would be `Foo__slot`. Defaults to the name of the element (e.g. `&quot;CalendarSync&quot;`).

##### `demo` *(optional)*

Boolean to activate demo-mode. Defaults to `false`. If `demo` is set to `true` the element will return mock data (and not make any API calls).

##### `config.logs` *(optional)*

Set the level of logging you want to appear in the console:

- `info`: show verbose logging (recommended for development use only).

- `warn`: (default) only log errors and warnings.

- `error`: only log errors.

- `none`: suppress all console output from the Element.

##### `config.revoke_mode` *(optional)*

CalendarSync has two options of revocation:

- `trigger_and_callback` (default)

- `callback_only`

When omitted or set to `trigger_and_callback`, pressing the revoke profile button triggers a notification of `profile_revoke_pressed_pressed` and makes an API call to revoke the profile.
Once this call completes, a notification with the type `provile_revoked` is sent to the callback.

When `callback_only` is set, pressing the revoke profile button does not call the API and only triggers the notification with the type `profile_revoke_pressed_pressed`. This allows your application to perform any pre-revoke actions you want (such as calling the [bulk_delete](/developers/api/events/bulk-delete-events/index.md) endpoint to remove all of your events). It is then the responsibility of your application to make the [revoke profile](/developers/api/authorization/revoke-profile/index.md) API call.

## Usage in an iframe
The CalendarSync Element can be placed in an iframe. Our authorization flows do not support being loaded in an iframe, however. To support starting authorization flows, the calendar provider buttons will navigate the top level of the current browser window (i.e. `target=&quot;_top&quot;`).

## Styling
Cronofy UI Elements come with built-in CSS that control their layout (as well as
adding a generic theme with placeholder colors and spacing). You can specify any
style rule you like in your own stylesheet.

To be sure to avoid specificity issues with CSS, make sure any custom selectors
you add are preceded by `.PREFIX`. For example, if your prefix is `ABC`, you
would target the button styles with this selector:

```css
.ABC .ABC__button {
    /* your button styles go here */
}
```

### Element classes
`PREFIX` default is `CalendarSync`.

- `{PREFIX}__title`

- `{PREFIX}__profiles`

- `{PREFIX}__profile`

- `{PREFIX}__profile-name`

- `{PREFIX}__providers`

- `{PREFIX}__provider-icon`

- `{PREFIX}__provider-auth`

- `{PREFIX}__provider-auth-text`

- `{PREFIX}__provider-icon--google`

- `{PREFIX}__provider-icon--apple`

- `{PREFIX}__provider-icon--outlook`

- `{PREFIX}__provider-icon--office365`

- `{PREFIX}__provider-status`

- `{PREFIX}__status--active`

- `{PREFIX}__status--inactive`

- `{PREFIX}__status-label`

- `{PREFIX}__status-icon`

- `{PREFIX}__status-icon--tick`

- `{PREFIX}__status-icon--reload`

- `{PREFIX}__status-icon--pending`

- `{PREFIX}__loading-wrapper`

- `{PREFIX}__footer`

- `{PREFIX}__edit-toggle`

- `{PREFIX}__edit-toggle-button`

- `{PREFIX}__edit-toggle-icon`

- `{PREFIX}__edit-toggle-text`

- `{PREFIX}__add-toggle`

- `{PREFIX}__add-toggle-button`

- `{PREFIX}__add-toggle-icon`

- `{PREFIX}__add-toggle-text`

- `{PREFIX}__remove`

- `{PREFIX}__remove-icon`

### Element methods
##### `refresh()`

From time to time you may wish to reload the CalendarSync UI Element on the page. You can do this with the `CalendarSync.refresh()` method:

```js
// Load CalendarSync Element:
const CalendarSync = CronofyElements.CalendarSync(optionsObject);

// Refresh the CalendarSync Element:
CalendarSync.refresh();
```

> **WARNING:** Being able to refresh a UI Element is useful in cases where your availability may have changed behind the scenes. UI Elements gather their availability data when they are first loaded, so unless they are refreshed they will not be aware of any changes to availability.

##### `update()`

Should you need to update the `options` for any Element, you can reload them with the `.update()` method (this requires you to have saved your Element instance to a variable beforehand):

```js
// Load CalendarSync Element:
const CalendarSync = CronofyElements.CalendarSync(optionsObject);

// Update the CalendarSync Element with new options:
CalendarSync.update(newOptions);
```

When updating, you do not need to redeclare *all* the options; you just need to add the ones you want to update.

**Note:** the `CalendarSync.update()` method must be called with an options object, otherwise a [warning-level log notification](/developers/ui-elements/index.md) will be fired.



---
[Read in HTML](/developers/ui-elements/calendar-sync/)