Pārlūkot izejas kodu

GSuite integration (#3252)

* GSuite initial commit

* GSuite initial commit

* cleanups

* exception handle

* gsuite script: add doGet

* Add GSuite integration to the upload popup

* hide dialog fields if gsuite disabled

* move gsuite code to gsuite.js from upload.js

* documentation

* change name format

* typo on GSuite

* copy paste the file .gs

* fix:don't show gsuite when creating a file in filemanager

* add version to webapp

* add webapp default url

* move webapp to html fied

* fix rebase

* fixes for codecy
version-14
almeidapaulopt pirms 8 gadiem
committed by Rushabh Mehta
vecāks
revīzija
b17b73c4f3
17 mainītis faili ar 942 papildinājumiem un 8 dzēšanām
  1. +5
    -1
      frappe/boot.py
  2. +15
    -0
      frappe/config/integrations.py
  3. +72
    -0
      frappe/docs/user/en/guides/integration/google_gsuite.md
  4. +1
    -0
      frappe/docs/user/en/guides/integration/index.txt
  5. +0
    -0
      frappe/integrations/doctype/gsuite_settings/__init__.py
  6. +42
    -0
      frappe/integrations/doctype/gsuite_settings/gsuite_settings.js
  7. +404
    -0
      frappe/integrations/doctype/gsuite_settings/gsuite_settings.json
  8. +87
    -0
      frappe/integrations/doctype/gsuite_settings/gsuite_settings.py
  9. +0
    -0
      frappe/integrations/doctype/gsuite_templates/__init__.py
  10. +8
    -0
      frappe/integrations/doctype/gsuite_templates/gsuite_templates.js
  11. +215
    -0
      frappe/integrations/doctype/gsuite_templates/gsuite_templates.json
  12. +42
    -0
      frappe/integrations/doctype/gsuite_templates/gsuite_templates.py
  13. +10
    -0
      frappe/integrations/doctype/gsuite_templates/test_gsuite_templates.py
  14. +1
    -0
      frappe/public/build.json
  15. +10
    -4
      frappe/public/js/frappe/form/footer/attachments.js
  16. +15
    -3
      frappe/public/js/frappe/upload.js
  17. +15
    -0
      frappe/public/js/integrations/gsuite.js

+ 5
- 1
frappe/boot.py Parādīt failu

@@ -71,6 +71,7 @@ def get_bootinfo():
bootinfo.treeviews = frappe.get_hooks("treeviews") or [] bootinfo.treeviews = frappe.get_hooks("treeviews") or []
bootinfo.lang_dict = get_lang_dict() bootinfo.lang_dict = get_lang_dict()
bootinfo.feedback_triggers = get_enabled_feedback_trigger() bootinfo.feedback_triggers = get_enabled_feedback_trigger()
bootinfo.gsuite_enabled = get_gsuite_status()
bootinfo.update(get_email_accounts(user=frappe.session.user)) bootinfo.update(get_email_accounts(user=frappe.session.user))


return bootinfo return bootinfo
@@ -239,4 +240,7 @@ def get_unseen_notes():
return frappe.db.sql('''select name, title, content, notify_on_every_login from tabNote where notify_on_login=1 return frappe.db.sql('''select name, title, content, notify_on_every_login from tabNote where notify_on_login=1
and expire_notification_on > %s and %s not in and expire_notification_on > %s and %s not in
(select user from `tabNote Seen By` nsb (select user from `tabNote Seen By` nsb
where nsb.parent=tabNote.name)''', (frappe.utils.now(), frappe.session.user), as_dict=True)
where nsb.parent=tabNote.name)''', (frappe.utils.now(), frappe.session.user), as_dict=True)

def get_gsuite_status():
return (frappe.get_value('Gsuite Settings', None, 'enable') == '1')

+ 15
- 0
frappe/config/integrations.py Parādīt failu

@@ -58,5 +58,20 @@ def get_data():
"description": _("Settings for OAuth Provider"), "description": _("Settings for OAuth Provider"),
}, },
] ]
},
{
"label": _("External Documents"),
"items": [
{
"type": "doctype",
"name": "GSuite Settings",
"description": _("Enter keys to enable integration with Google GSuite"),
},
{
"type": "doctype",
"name": "GSuite Templates",
"description": _("Google GSuite Templates to integration with DocTypes"),
},
]
} }
] ]

+ 72
- 0
frappe/docs/user/en/guides/integration/google_gsuite.md Parādīt failu

@@ -0,0 +1,72 @@
# Google GSuite

You can create and attach Google GSuite Docs to your Documents using your predefined GSuite Templates.
These Templates could use variables from Doctype that will be automatically filled.

## 1. Enable integration with Google Gsuite

### 1.1 Publish Google apps script

*If you will use the default script you can go to 1.2*

1. Go to [https://script.google.com](https://script.google.com)
1. Create a new Project. Click on **File > New > Project**
1. Copy the code of **Desk > Explore > Integrations > GSuite Settings > Google Apps Script** to clipboard and paste to an empty Code.gs in script.google.com
1. Save the Project. Click on **File > Save > Enter new project name**
1. Deploy the app. Click on **Publish > Deploy as web app**
1. Copy "Current web app URL" into **Desk > Explore > Integrations > GSuite Settings > Script URL**
1. Click on OK but don't close the script

### 1.2

### 1.2 Get Google access

1. Go to your Google project console and select your project or create a new. [https://console.developers.google.com](https://console.developers.google.com)
1. In Library click on **Google Drive API** and **Enable**
1. Click on **Credentials > Create Credentials > OAuth Client ID**
1. Fill the form with:
- Web Application
- Authorized redirect URI as **http://{{ yoursite }}/?cmd=frappe.integrations.doctype.gsuite_settings.gsuite_settings.gsuite_callback**
1. Copy the Client ID and Client Secret into **Desk > Explore > Integrations > GSuite Settings > Client ID and Client Secret**
1. Save GSuite Settings

### 1.3 Test Script

1. Click on **Allow GSuite Access** and you will be redirected to select the user and give access. If you have any error please verify you are using the correct Authorized redirect URI.
1. Click on **Run Script test**. You should be asked to give permission.

## 2. GSuite Templates

### 2.1 Google Document as Template

1. Create a new Document or use one you already have. Set variables as you need. Variables are defined with ***{{VARIABLE}}*** with ***VARIABLE*** is the field of your Doctype

For Example,
If this document will be used to employee and the Doctype has the field ***name*** then you can use it in Google Docs ad {{name}}

1. Get the ID of that Document from url of your document

For example: in this address the ID is in bold
https://docs.google.com/document/d/**1Y2_btbwSqPIILLcJstHnSm1u5dgYE0QJspcZBImZQso**/edit

1. Get the ID of the folder where you want to place the generated documents. (You can step this point if you want to place the generated documents in Google Drive root. )

For example: in this folder url the ID is in bold
https://drive.google.com/drive/u/0/folders/**0BxmFzZZUHbgyQzVJNzY5eG5jbmc**

### 2.2 Associate the Template to a Doctype

1. Go to **Desk > Explore > Integrations > GSuite Templates > New**
1. Fill the form with:
- Template Name (Example: Employee Contract)
- Related DocType (Example: Employee)
- Template ID is the Document ID you get from your Google Docs (Example: 1Y2_btbwSqPIILLcJstHnSm1u5dgYE0QJspcZBImZQso)
- Document name is the name of the new files. You can use field from DocType (Example: Employee Contract of {name})
- Destination ID is the folder ID of your files created from this Template. (Example: 0BxmFzZZUHbgyQzVJNzY5eG5jbmc)

## 3. Create Documents

1. Go to a Document you already have a Template (Example: Employee > John Doe)
2. Click on **Attach File**
3. O **GSuite Document** section select the Template and click **Attach**
4. You should see the generated document is already created and attached

+ 1
- 0
frappe/docs/user/en/guides/integration/index.txt Parādīt failu

@@ -2,3 +2,4 @@ rest_api
how_to_setup_oauth how_to_setup_oauth
using_oauth using_oauth
openid_connect_and_frappe_social_login openid_connect_and_frappe_social_login
google_gsuite

+ 0
- 0
frappe/integrations/doctype/gsuite_settings/__init__.py Parādīt failu


+ 42
- 0
frappe/integrations/doctype/gsuite_settings/gsuite_settings.js Parādīt failu

@@ -0,0 +1,42 @@
// Copyright (c) 2017, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.ui.form.on('GSuite Settings', {
refresh: function(frm) {
frm.clear_custom_buttons();
},

allow_gsuite_access: function(frm) {
if (frm.doc.client_id && frm.doc.client_secret) {
frappe.call({
method: "frappe.integrations.doctype.gsuite_settings.gsuite_settings.gsuite_callback",
callback: function(r) {
if(!r.exc) {
frm.save();
window.open(r.message.url);
}
}
});
}
else {
frappe.msgprint(__("Please enter values for GSuite Access Key and GSuite Access Secret"))
}
},
run_script_test: function(frm) {
if (frm.doc.client_id && frm.doc.client_secret) {
frappe.call({
method: "frappe.integrations.doctype.gsuite_settings.gsuite_settings.run_script_test",
callback: function(r) {
if(!r.exc) {
if (r.message == 'ping') {
frappe.msgprint(__('GSuite test executed with success. GSuite integration is correctly configured'),__('GSuite script test'));
}
}
}
});
}
else {
frappe.msgprint(__("Please enter values for GSuite Access Key and GSuite Access Secret"));
}
}
});

+ 404
- 0
frappe/integrations/doctype/gsuite_settings/gsuite_settings.json Parādīt failu

@@ -0,0 +1,404 @@
{
"allow_copy": 1,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2017-04-21 16:57:30.264478",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "System",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "enable",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Enable",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.enable",
"fieldname": "google_credentials",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Google Credentials",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "client_id",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Client ID",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "client_secret",
"fieldtype": "Password",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Client Secret",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:(doc.client_secret && doc.client_id)",
"fieldname": "allow_gsuite_access",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow GSuite access",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"depends_on": "eval:doc.enable",
"fieldname": "google_apps_script",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Google Apps Script",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "https://script.google.com/macros/s/AKfycbxIFOx3301xwtF2IFPJ4pUQGqkNF3hBiBebppWkeKn6fKZRQvk/exec",
"depends_on": "",
"description": "If you aren't using own publish Google Apps Script webapp you can use the default https://script.google.com/macros/s/AKfycbxIFOx3301xwtF2IFPJ4pUQGqkNF3hBiBebppWkeKn6fKZRQvk/exec ",
"fieldname": "script_url",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Script URL",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"description": "Copy and paste this code into and empty Code.gs in your project at script.google.com",
"fieldname": "script_code",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Script Code",
"length": 0,
"no_copy": 0,
"options": "<code>// ERPNEXT GSuite integration\n//\n\nfunction doGet(e){\n return ContentService.createTextOutput('ok');\n}\n\nfunction doPost(e) {\n var p = JSON.parse(e.postData.contents);\n\n switch(p.exec){\n case 'new':\n var url = createDoc(p);\n result = { 'url': url };\n break;\n case 'test':\n result = { 'test':'ping' , 'version':'1.0'}\n }\n return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);\n}\n\nfunction replaceVars(body,p){\n for (key in p) {\n if (p.hasOwnProperty(key)) {\n if (p[key] != null) {\n body.replaceText('{{'+key+'}}', p[key]);\n }\n }\n } \n}\n\nfunction createDoc(p) {\n if(p.destination){\n var folder = DriveApp.getFolderById(p.destination);\n } else {\n var folder = DriveApp.getRootFolder();\n }\n var template = DriveApp.getFileById( p.template )\n var newfile = template.makeCopy( p.filename , folder );\n\n switch(newfile.getMimeType()){\n case MimeType.GOOGLE_DOCS:\n var body = DocumentApp.openById(newfile.getId()).getBody();\n replaceVars(body,p.vars);\n break;\n case MimeType.GOOGLE_SHEETS:\n //TBD\n case MimeType.GOOGLE_SLIDES:\n //TBD\n }\n return newfile.getUrl()\n}\n\n</code>",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:(doc.client_id && doc.client_secret && doc.authorization_code && doc.refresh_token && doc.script_url)",
"fieldname": "run_script_test",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Run Script Test",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "refresh_token",
"fieldtype": "Password",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "refresh_token",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "authorization_code",
"fieldtype": "Password",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Authorization Code",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 1,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2017-05-19 15:28:44.663715",
"modified_by": "Administrator",
"module": "Integrations",
"name": "GSuite Settings",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 1,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

+ 87
- 0
frappe/integrations/doctype/gsuite_settings/gsuite_settings.py Parādīt failu

@@ -0,0 +1,87 @@
# Copyright (c) 2017, Frappe Technologies and contributors
# -*- coding: utf-8 -*-
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import get_request_site_address
import requests
from json import dumps
from frappe.utils.response import json_handler

SCOPES = 'https://www.googleapis.com/auth/drive'

class GSuiteSettings(Document):

def get_access_token(self):
if not self.refresh_token:
raise UserError(_("Google GSuite is not configured."))
data = {
'client_id': self.client_id,
'client_secret': self.get_password(fieldname='client_secret',raise_exception=False),
'refresh_token': self.get_password(fieldname='refresh_token',raise_exception=False),
'grant_type': "refresh_token",
'scope': SCOPES
}
try:
r = requests.post('https://www.googleapis.com/oauth2/v4/token', data=data).json()
except requests.exceptions.HTTPError:
frappe.throw(_("Something went wrong during the token generation. Please request again an authorization code."))
return r.get('access_token')

@frappe.whitelist()
def gsuite_callback(code=None):
doc = frappe.get_doc("GSuite Settings")
if code is None:
return {
'url': 'https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id={}&scope={}&redirect_uri={}?cmd=frappe.integrations.doctype.gsuite_settings.gsuite_settings.gsuite_callback'.format(doc.client_id, SCOPES, get_request_site_address(True))
}
else:
try:
data = {'code': code,
'client_id': doc.client_id,
'client_secret': doc.get_password(fieldname='client_secret',raise_exception=False),
'redirect_uri': get_request_site_address(True) + '?cmd=frappe.integrations.doctype.gsuite_settings.gsuite_settings.gsuite_callback',
'grant_type': 'authorization_code'}
r = requests.post('https://www.googleapis.com/oauth2/v4/token', data=data).json()
frappe.db.set_value("Gsuite Settings", None, "authorization_code", code)
if r.has_key('refresh_token'):
frappe.db.set_value("Gsuite Settings", None, "refresh_token", r['refresh_token'])
frappe.db.commit()
return
except Exception, e:
frappe.throw(e.message)

def run_gsuite_script(option, filename = None, template_id = None, destination_id = None, json_data = None):
gdoc = frappe.get_doc('GSuite Settings')
if gdoc.script_url:
data = {
'exec': option,
'filename': filename,
'template': template_id,
'destination': destination_id,
'vars' : json_data
}
headers = {'Authorization': 'Bearer {}'.format( gdoc.get_access_token() )}

try:
r = requests.post(gdoc.script_url, headers=headers, data=dumps(data, default=json_handler, separators=(',',':')))
except Exception, e:
frappe.throw(e.message)

try:
r = r.json()
except:
# if request doesn't return json show HTML ask permissions or to identify the error on google side
frappe.throw(r.text)

return r
else:
frappe.throw(_('Please set script URL on Gsuite Settings'))

@frappe.whitelist()
def run_script_test():
r = run_gsuite_script('test')
return r['test']

+ 0
- 0
frappe/integrations/doctype/gsuite_templates/__init__.py Parādīt failu


+ 8
- 0
frappe/integrations/doctype/gsuite_templates/gsuite_templates.js Parādīt failu

@@ -0,0 +1,8 @@
// Copyright (c) 2017, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.ui.form.on('GSuite Templates', {
refresh: function(frm) {

}
});

+ 215
- 0
frappe/integrations/doctype/gsuite_templates/gsuite_templates.json Parādīt failu

@@ -0,0 +1,215 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:template_name",
"beta": 0,
"creation": "2017-04-24 09:53:41.813982",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "template_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Template Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "related_doctype",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Related DocType",
"length": 0,
"no_copy": 0,
"options": "DocType",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "template_id",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Template ID",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "New Document for {name} ",
"fieldname": "document_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Document Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "destination_id",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Destination ID",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-05-12 16:50:08.074882",
"modified_by": "Administrator",
"module": "Integrations",
"name": "GSuite Templates",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

+ 42
- 0
frappe/integrations/doctype/gsuite_templates/gsuite_templates.py Parādīt failu

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.integrations.doctype.gsuite_settings.gsuite_settings import run_gsuite_script
from frappe.utils.file_manager import save_url

class GSuiteTemplates(Document):
pass

@frappe.whitelist()
def create_gsuite_doc(doctype, docname, gs_template=None):
templ = frappe.get_doc('GSuite Templates', gs_template)
doc = frappe.get_doc(doctype, docname)

if not doc.has_permission("read"):
raise frappe.PermissionError

json_data = doc.as_dict()
filename = templ.document_name.format(**json_data)

r = run_gsuite_script('new', filename, templ.template_id, templ.destination_id, json_data)

filedata = save_url(r['url'], filename, doctype, docname, "Home/Attachments", True)
comment = frappe.get_doc(doctype, docname).add_comment("Attachment",
_("added {0}").format("<a href='{file_url}' target='_blank'>{file_name}</a>{icon}".format(**{
"icon": ' <i class="fa fa-lock text-warning"></i>' if filedata.is_private else "",
"file_url": filedata.file_url.replace("#", "%23") if filedata.file_name else filedata.file_url,
"file_name": filedata.file_name or filedata.file_url
})))

return {
"name": filedata.name,
"file_name": filedata.file_name,
"file_url": filedata.file_url,
"is_private": filedata.is_private,
"comment": comment.as_dict() if comment else {}
}

+ 10
- 0
frappe/integrations/doctype/gsuite_templates/test_gsuite_templates.py Parādīt failu

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies and Contributors
# See license.txt
from __future__ import unicode_literals

import frappe
import unittest

class TestGSuiteTemplates(unittest.TestCase):
pass

+ 1
- 0
frappe/public/build.json Parādīt failu

@@ -133,6 +133,7 @@


"public/js/frappe/ui/upload.html", "public/js/frappe/ui/upload.html",
"public/js/frappe/upload.js", "public/js/frappe/upload.js",
"public/js/integrations/gsuite.js",
"public/js/frappe/ui/tree.js", "public/js/frappe/ui/tree.js",


"public/js/frappe/views/container.js", "public/js/frappe/views/container.js",


+ 10
- 4
frappe/public/js/frappe/form/footer/attachments.js Parādīt failu

@@ -211,11 +211,12 @@ frappe.ui.get_upload_dialog = function(opts){
title: __('Upload Attachment'), title: __('Upload Attachment'),
no_focus: true, no_focus: true,
fields: [ fields: [
{fieldtype: "Section Break"},
{"fieldtype": "Section Break"},
{"fieldtype": "Link" , "fieldname": "file" , "label": __("Select uploaded file"), "options": "File"}, {"fieldtype": "Link" , "fieldname": "file" , "label": __("Select uploaded file"), "options": "File"},
{"hidden": !opts.args.doctype || !frappe.boot.gsuite_enabled,"fieldtype": "Section Break", "label": __("GSuite Document")},
{"fieldtype": "Link" ,"fieldname": "gs_template" ,"label": __("Select template"), "options": "GSuite Templates", reqd : false, filters: {'related_doctype': opts.args.doctype}},
], ],
}); });

var btn = dialog.set_primary_action(__("Attach")); var btn = dialog.set_primary_action(__("Attach"));
btn.removeClass("btn-primary").addClass("btn-default"); btn.removeClass("btn-primary").addClass("btn-default");


@@ -223,6 +224,11 @@ frappe.ui.get_upload_dialog = function(opts){
var upload_area = $('<div style="padding-bottom: 25px;"></div>').prependTo(dialog.body); var upload_area = $('<div style="padding-bottom: 25px;"></div>').prependTo(dialog.body);


var fd = dialog.fields_dict; var fd = dialog.fields_dict;

$(fd.gs_template.input).change(function() {
opts.args.gs_template = fd.gs_template.get_value();
});

$(fd.file.input).change(function() { $(fd.file.input).change(function() {
frappe.call({ frappe.call({
'method': 'frappe.client.get_value', 'method': 'frappe.client.get_value',
@@ -237,7 +243,7 @@ frappe.ui.get_upload_dialog = function(opts){
if(!r.message) return; if(!r.message) return;
dialog.$wrapper.find('[name="file_url"]').val(r.message.file_url); dialog.$wrapper.find('[name="file_url"]').val(r.message.file_url);
dialog.$wrapper.find('.private-file input').prop('checked', r.message.is_private); dialog.$wrapper.find('.private-file input').prop('checked', r.message.is_private);
opts.args.filename = r.message.file_name
opts.args.filename = r.message.file_name;
} }
}); });
}); });
@@ -262,4 +268,4 @@ frappe.ui.get_upload_dialog = function(opts){
}); });


return dialog; return dialog;
}
}

+ 15
- 3
frappe/public/js/frappe/upload.js Parādīt failu

@@ -144,8 +144,9 @@ frappe.upload = {
// Get file url if input is visible // Get file url if input is visible
var file_url = $upload.find('[name="file_url"]:visible'); var file_url = $upload.find('[name="file_url"]:visible');
file_url = file_url.length && file_url.get(0).value; file_url = file_url.length && file_url.get(0).value;

if(file_url) {
if(opts.args.gs_template) {
frappe.integration_service.gsuite.create_gsuite_file(opts.args,opts);
} else if(file_url) {
opts.args.file_url = file_url; opts.args.file_url = file_url;
frappe.upload.upload_file(null, opts.args, opts); frappe.upload.upload_file(null, opts.args, opts);
} else { } else {
@@ -371,12 +372,23 @@ frappe.upload = {
frappe.upload.upload_file(fileobjs[i], args, opts); frappe.upload.upload_file(fileobjs[i], args, opts);
i++; i++;
} }
}
};


opts.loopcallback(); opts.loopcallback();
} }
}); });
d.show(); d.show();
opts.confirm_is_private = 0; opts.confirm_is_private = 0;
},
create_gsuite_file: function(args, opts) {
return frappe.call({
type:'POST',
method: 'frappe.integrations.doctype.gsuite_templates.gsuite_templates.create_gsuite_doc',
args: args,
callback: function(r) {
var attachment = r.message;
opts.callback && opts.callback(attachment, r);
}
});
} }
} }

+ 15
- 0
frappe/public/js/integrations/gsuite.js Parādīt failu

@@ -0,0 +1,15 @@
frappe.provide("frappe.integration_service");

frappe.integration_service.gsuite = {
create_gsuite_file: function(args, opts) {
return frappe.call({
type:'POST',
method: 'frappe.integrations.doctype.gsuite_templates.gsuite_templates.create_gsuite_doc',
args: args,
callback: function(r) {
var attachment = r.message;
opts.callback && opts.callback(attachment, r);
}
});
}
};

Notiek ielāde…
Atcelt
Saglabāt