8000 feat: add video conferencing option (Google Meet) to Google Calendar integration by akurungadam · Pull Request #17851 · frappe/frappe · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: add video conferencing option (Google Meet) to Google Calendar integration #17851

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

Merged
merged 18 commits into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
25b1414
feat: add video conferencing (via google meet) for events syncing wit…
akurungadam Aug 10, 2022
435a3c3
fix: unset add_video_conferencing if sync_with_google_calendar not en…
akurungadam Aug 11, 2022
984159c
fix: remove conference data if add_video_conferencing disabled during…
akurungadam Aug 11, 2022
f3e3d5f
fix: restrict add conferencing if event_category in Event, Meeting an…
akurungadam Aug 12, 2022
555f8f5
fix: save meet link while pulling from calendar
akurungadam Aug 12, 2022
f5e476b
feat: show link to join video conference with google meet
akurungadam Aug 13, 2022
c002a77
fix(style): linter errors
akurungadam Aug 17, 2022
b30ae52
fix(style): linter errors
akurungadam Aug 17, 2022
142c0aa
fix: set conferenceDataVersion 1 only if google meet conferencing ena…
akurungadam Aug 20, 2022
45035ec
Update frappe/desk/doctype/event/event.py
akurungadam Sep 16, 2022
4e7afbe
Update frappe/desk/doctype/event/event.json
akurungadam Sep 16, 2022
32321a8
fix: handle empty ends_on, use starts_on
akurungadam Sep 17, 2022
e867a42
fix: do not update Event modified time on db set meet link
akurungadam Sep 17, 2022
63e8797
fix: add email field event participants table
akurungadam Sep 27, 2022
13cadca
fix: attendees not cleared from google calendar event
akurungadam Sep 27, 2022
2810666
fix(style): linter suggestions
akurungadam Sep 27, 2022
ad796f0
fix: make email field non-read only, called set_participants_email fr…
phot0n Oct 18, 2022
44c5bdf
test: update new no of fields in event doctype in test_fetch_to_custo…
phot0n Oct 18, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test_fetch_to_customize(self):

d = self.get_customize_form("Event")
self.assertEqual(d.doc_type, "Event")
self.assertEqual(len(d.get("fields")), 36)
self.assertEqual(len(d.get("fields")), 38)

d = self.get_customize_form("Event")
self.assertEqual(d.doc_type, "Event")
Expand Down
12 changes: 12 additions & 0 deletions frappe/desk/doctype/event/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ frappe.ui.form.on("Event", {
},
__("Add Participants")
);

const [ends_on_date] = frm.doc.ends_on
? frm.doc.ends_on.split(" ")
: frm.doc.starts_on.split(" ");

if (frm.doc.google_meet_link && frappe.datetime.now_date() <= ends_on_date) {
frm.dashboard.set_headline(
__("Join video conference with {0}", [
`<a target='_blank' href='${frm.doc.google_meet_link}'>Google Meet</a>`,
])
);
}
},
repeat_on: function (frm) {
if (frm.doc.repeat_on === "Every Day") {
Expand Down
26 changes: 22 additions & 4 deletions frappe/desk/doctype/event/event.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
"sender",
"all_day",
"sync_with_google_calendar",
"add_video_conferencing",
"sb_00",
"google_calendar",
"pulled_from_google_calendar",
"cb_00",
"google_calendar_id",
"cb_00",
"google_calendar_event_id",
"google_meet_link",
"pulled_from_google_calendar",
"section_break_13",
"repeat_on",
"repeat_till",
Expand Down Expand Up @@ -225,7 +227,7 @@
},
{
"collapsible": 1,
"depends_on": "eval:doc.sync_with_google_calendar",
"depends_on": "eval:doc.sync_with_google_calendar || doc.pulled_from_google_calendar",
"fieldname": "sb_00",
"fieldtype": "Section Break",
"label": "Google Calendar"
Expand All @@ -245,6 +247,7 @@
"fieldname": "google_calendar_event_id",
"fieldtype": "Data",
"label": "Google Calendar Event ID",
"no_copy": 1,
"read_only": 1
},
{
Expand Down Expand Up @@ -272,12 +275,27 @@
"label": "Sender",
"options": "Email",
"read_only": 1
},
{
"default": "0",
"depends_on": "eval:doc.sync_with_google_calendar",
"description": "via Google Meet",
"fieldname": "add_video_conferencing",
"fieldtype": "Check",
"label": "Add Video Conferencing"
},
{
"fieldname": "google_meet_link",
"fieldtype": "Data",
"label": "Google Meet Link",
"no_copy": 1,
"read_only": 1
}
],
"icon": "fa fa-calendar",
"idx": 1,
"links": [],
"modified": "2022-05-12 05:43:27.935510",
"modified": "2022-08-12 19:24:34.794098",
"modified_by": "Administrator",
"module": "Desk",
"name": "Event",
Expand Down
19 changes: 19 additions & 0 deletions frappe/desk/doctype/event/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import frappe
from frappe import _
from frappe.contacts.doctype.contact.contact import get_default_contact
from frappe.desk.doctype.notification_settings.notification_settings import (
is_email_notifications_enabled_for_type,
)
Expand Down Expand Up @@ -55,6 +56,12 @@ def validate(self):
if self.sync_with_google_calendar and not self.google_calendar:
frappe.throw(_("Select Google Calendar to which event should be synced."))

if not self.sync_with_google_calendar:
self.add_video_conferencing = 0

def before_save(self):
self.set_participants_email()

def on_update(self):
self.sync_communication()

Expand Down Expand Up @@ -131,6 +138,18 @@ def add_participants(self, participants):
for participant in participants:
self.add_participant(participant["doctype"], participant["docname"])

def set_participants_email(self):
for participant in self.event_participants:
if participant.email:
continue

participant_contact = get_default_contact(
participant.reference_doctype, participant.reference_docname
)
participant.email = (
frappe.get_value("Contact", participant_contact, "email_id") if participant_contact else None
)


@frappe.whitelist()
def delete_communication(event, reference_doctype, reference_docname):
Expand Down
11 changes: 9 additions & 2 deletions frappe/desk/doctype/event_participants/event_participants.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"engine": "InnoDB",
"field_order": [
"reference_doctype",
"reference_docname"
"reference_docname",
"email"
],
"fields": [
{
Expand All @@ -24,11 +25,17 @@
"label": "Reference Name",
"options": "reference_doctype",
"reqd": 1
},
{
"fieldname": "email",
"fieldtype": "Data",
"label": "Email",
"options": "Email"
}
],
"istable": 1,
"links": [],
"modified": "2022-08-03 12:20:50.466370",
"modified": "2022-10-18 17:49:33.549459",
"modified_by": "Administrator",
"module": "Desk",
"name": "Event Participants",
Expand Down
122 changes: 116 additions & 6 deletions frappe/integrations/doctype/google_calendar/google_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def sync_events_from_google_calendar(g_calendar, method=None):
if err.resp.status == 410:
set_encrypted_password("Google Calendar", account.name, "", "next_sync_token")
frappe.db.commit()
msg += " " + _("Sync token was invalid and has been resetted, Retry syncing.")
msg += " " + _("Sync token was invalid and has been reset, Retry syncing.")
frappe.msgprint(msg, title="Invalid Sync Token", indicator="blue")
else:
frappe.throw(msg)
Expand Down Expand Up @@ -356,6 +356,7 @@ def insert_event_to_calendar(account, event, recurrence=None):
"google_calendar": account.name,
"google_calendar_id": account.google_calendar_id,
"google_calendar_event_id": event.get("id"),
"google_meet_link": event.get("hangoutLink"),
"pulled_from_google_calendar": 1,
}
calendar_event.update(
Expand All @@ -373,6 +374,7 @@ def update_event_in_calendar(account, event, recurrence=None):
calendar_event = frappe.get_doc("Event", {"google_calendar_event_id": event.get("id")})
calendar_event.subject = event.get("summary")
calendar_event.description = event.get("description")
calendar_event.google_meet_link = event.get("hangoutLink")
calendar_event.update(
google_calendar_to_repeat_on(
recurrence=recurrence, start=event.get("start"), end=event.get("end")
Expand Down Expand Up @@ -407,11 +409,30 @@ def insert_event_in_google_calendar(doc, method=None):
if doc.repeat_on:
event.update({"recurrence": repeat_on_to_google_calendar_recurrence_rule(doc)})

event.update({"attendees": get_attendees(doc)})

conference_data_version = 0
Copy link
Contributor

Choose a reason for hiding this comment

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

we don't really need this variable over here right? we can just say if doc.add_video_conferencing is there, we need a meet link.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this i guess we should go with the variable as it wouldn't be so obvious if we use the add_video_conferencing flag to be passed as the version?


if doc.add_video_conferencing:
event.update({"conferenceData": get_conference_data(doc)})
conference_data_version = 1

try:
event = google_calendar.events().insert(calendarId=doc.google_calendar_id, body=event).execute()
event = (
google_calendar.events()
.insert(
calendarId=doc.google_calendar_id, body=event, conferenceDataVersion=conference_data_version
)
.execute()
)

frappe.db.set_value(
"Event", doc.name, "google_calendar_event_id", event.get("id"), update_modified=False
"Event",
doc.name,
{"google_calendar_event_id": event.get("id"), "google_meet_link": event.get("hangoutLink")},
update_modified=False,
)

frappe.msgprint(_("Event Synced with Google Calendar."))
except HttpError as err:
frappe.throw(
Expand Down Expand Up @@ -450,6 +471,7 @@ def update_event_in_google_calendar(doc, method=None):
.get(calendarId=doc.google_calendar_id, eventId=doc.google_calendar_event_id)
.execute()
)

event["summary"] = doc.subject
event["description"] = doc.description
event["recurrence"] = repeat_on_to_google_calendar_recurrence_rule(doc)
Expand All @@ -462,9 +484,38 @@ def update_event_in_google_calendar(doc, method=None):
)
)

google_calendar.events().update(
calendarId=doc.google_calendar_id, eventId=doc.google_calendar_event_id, body=event
).execute()
conference_data_version = 0

if doc.add_video_conferencing:
event.update({"conferenceData": get_conference_data(doc)})
conference_data_version = 1
elif doc.get_doc_before_save().add_video_conferencing or event.get("hangoutLink"):
# remove google meet from google calendar event, if turning off add_video_conferencing
event.update({"conferenceData": None})
conference_data_version = 1

event.update({"attendees": get_attendees(doc)})

event = (
google_calendar.events()
.update(
calendarId=doc.google_calendar_id,
eventId=doc.google_calendar_event_id,
body=event,
conferenceDataVersion=conference_data_version,
)
.execute()
)

# if add_video_conferencing enabled or disabled during update, overwrite
frappe.db.set_value(
"Event",
doc.name,
{"google_meet_link": event.get("hangoutLink")},
update_modified=False,
)
doc.notify_update()

frappe.msgprint(_("Event Synced with Google Calendar."))
except HttpError as err:
frappe.throw(
Expand Down Expand Up @@ -682,6 +733,39 @@ def get_recurrence_parameters(recurrence):
return frequency, until, byday


def get_conference_data(doc):
return {
"createRequest": {"requestId": doc.name, "conferenceSolutionKey": {"type": "hangoutsMeet"}},
"notes": doc.description,
}


def get_attendees(doc):
"""
Returns a list of dicts with attendee emails, if available in event_participants table
"""
attendees, email_not_found = [], []

for participant in doc.event_participants:
if participant.get("email"):
attendees.append({"email": participant.email})
else:
email_not_found.append(
{"dt": participant.reference_doctype, "dn": participant.reference_docname}
)

if email_not_found:
frappe.msgprint(
_("Google Calendar - Contact / email not found. Did not add attendee for -<br>{0}").format(
"<br>".join(f"{d.get('dt')} {d.get('dn')}" for d in email_not_found)
),
alert=True,
indicator="yellow",
)

return attendees


"""API Response
{
'kind': 'calendar#events',
Expand Down Expand Up @@ -721,6 +805,32 @@ def get_recurrence_parameters(recurrence):
'recurrence': *recurrence,
'iCalUID': 'uid',
'sequence': 1,
'hangoutLink': 'https://meet.google.com/mee-ting-uri',
'conferenceData': {
'createRequest': {
'requestId': 'EV00001',
'conferenceSolutionKey': {
'type': 'hangoutsMeet'
},
'status': {
'statusCode': 'success'
}
},
'entryPoints': [
{
'entryPointType': 'video',
'uri': 'https://meet.google.com/mee-ting-uri',
'label': 'meet.google.com/mee-ting-uri'
}
],
'conferenceSolution': {
'key': {
'type': 'hangoutsMeet'
},
'name': 'Google Meet',
'iconUri': 'https://fonts.gstatic.com/s/i/productlogos/meet_2020q4/v6/web-512dp/logo_meet_2020q4_color_2x_web_512dp.png'
},
'conferenceId': 'mee-ting-uri'
'reminders': {
'useDefault': True
}
Expand Down
0