diff --git a/application/Espo/Controllers/ExternalAccount.php b/application/Espo/Controllers/ExternalAccount.php
new file mode 100644
index 0000000000..3c4b2c887b
--- /dev/null
+++ b/application/Espo/Controllers/ExternalAccount.php
@@ -0,0 +1,104 @@
+getEntityManager()->getRepository('Integration')->find();
+ $arr = array();
+ foreach ($integrations as $entity) {
+ if ($entity->get('enabled') && $this->getMetadata()->get('integrations.' . $entity->id .'.allowUserAccounts')) {
+ $arr[] = array(
+ 'id' => $entity->id
+ );
+ }
+ }
+ return array(
+ 'list' => $arr
+ );
+ }
+
+ public function actionGetOAuthCredentials($params, $data, $request)
+ {
+ $id = $request->get('id');
+ list($integration, $userId) = explode('__', $id);
+
+ if (!$this->getUser()->isAdmin()) {
+ if ($this->getUser()->id != $userId) {
+ throw new Forbidden();
+ }
+ }
+
+ $entity = $this->getEntityManager()->getEntity('Integration', $integration);
+ if ($entity) {
+ return array(
+ 'clientId' => $entity->get('clientId'),
+ 'redirectUri' => $this->getConfig()->get('siteUrl') . '/oauthcallback'
+ );
+ }
+ }
+
+ public function actionRead($params, $data, $request)
+ {
+ list($integration, $userId) = explode('__', $params['id']);
+
+ if (!$this->getUser()->isAdmin()) {
+ if ($this->getUser()->id != $userId) {
+ throw new Forbidden();
+ }
+ }
+
+ $entity = $this->getEntityManager()->getEntity('ExternalAccount', $params['id']);
+ return $entity->toArray();
+ }
+
+ public function actionUpdate($params, $data)
+ {
+ return $this->actionPatch($params, $data);
+ }
+
+ public function actionPatch($params, $data)
+ {
+ list($integration, $userId) = explode('__', $params['id']);
+
+ if (!$this->getUser()->isAdmin()) {
+ if ($this->getUser()->id != $userId) {
+ throw new Forbidden();
+ }
+ }
+
+ $entity = $this->getEntityManager()->getEntity('ExternalAccount', $params['id']);
+ $entity->set($data);
+ $this->getEntityManager()->saveEntity($entity);
+
+ return $entity->toArray();
+ }
+}
+
diff --git a/application/Espo/Entities/ExternalAccount.php b/application/Espo/Entities/ExternalAccount.php
new file mode 100644
index 0000000000..e52c51e256
--- /dev/null
+++ b/application/Espo/Entities/ExternalAccount.php
@@ -0,0 +1,28 @@
+get();
+ $entity->id = $id;
+ }
+ return $entity;
+ }
+}
+
diff --git a/application/Espo/Resources/i18n/en_US/ExternalAccount.json b/application/Espo/Resources/i18n/en_US/ExternalAccount.json
new file mode 100644
index 0000000000..1478eede4d
--- /dev/null
+++ b/application/Espo/Resources/i18n/en_US/ExternalAccount.json
@@ -0,0 +1,7 @@
+{
+ "labels": {
+ "Connect": "Connect"
+ },
+ "help": {
+ }
+}
diff --git a/application/Espo/Resources/i18n/en_US/Global.json b/application/Espo/Resources/i18n/en_US/Global.json
index f60cc725ef..b61bb915cd 100644
--- a/application/Espo/Resources/i18n/en_US/Global.json
+++ b/application/Espo/Resources/i18n/en_US/Global.json
@@ -7,7 +7,8 @@
"EmailTemplate": "Email Template",
"EmailAccount": "Email Account",
"OutboundEmail": "Outbound Email",
- "ScheduledJob": "Scheduled Job"
+ "ScheduledJob": "Scheduled Job",
+ "ExternalAccount": "External Account"
},
"scopeNamesPlural": {
"Email": "Emails",
@@ -17,7 +18,8 @@
"EmailTemplate": "Email Templates",
"EmailAccount": "Email Accounts",
"OutboundEmail": "Outbound Emails",
- "ScheduledJob": "Scheduled Jobs"
+ "ScheduledJob": "Scheduled Jobs",
+ "ExternalAccount": "External Accounts"
},
"labels": {
"Misc": "Misc",
diff --git a/application/Espo/Resources/i18n/en_US/Integration.json b/application/Espo/Resources/i18n/en_US/Integration.json
index fe92108a0f..37aed3d2e5 100644
--- a/application/Espo/Resources/i18n/en_US/Integration.json
+++ b/application/Espo/Resources/i18n/en_US/Integration.json
@@ -2,7 +2,8 @@
"fields": {
"enabled": "Enabled",
"clientId": "Client ID",
- "clientSecret": "Client Secret"
+ "clientSecret": "Client Secret",
+ "redirectUri": "Redirect URI"
},
"messages": {
"selectIntegration": "Select an integration in menu."
diff --git a/application/Espo/Resources/metadata/clientDefs/ExternalAccount.json b/application/Espo/Resources/metadata/clientDefs/ExternalAccount.json
new file mode 100644
index 0000000000..3a3b749aef
--- /dev/null
+++ b/application/Espo/Resources/metadata/clientDefs/ExternalAccount.json
@@ -0,0 +1,3 @@
+{
+ "controller": "Controllers.ExternalAccount"
+}
diff --git a/application/Espo/Resources/metadata/entityDefs/ExternalAccount.json b/application/Espo/Resources/metadata/entityDefs/ExternalAccount.json
new file mode 100644
index 0000000000..3dcdfa336b
--- /dev/null
+++ b/application/Espo/Resources/metadata/entityDefs/ExternalAccount.json
@@ -0,0 +1,10 @@
+{
+ "fields": {
+ "data": {
+ "type": "text"
+ },
+ "enabled": {
+ "type": "bool"
+ }
+ }
+}
diff --git a/application/Espo/Resources/metadata/integrations/Google.json b/application/Espo/Resources/metadata/integrations/Google.json
index 176dc89fa4..c16428360d 100644
--- a/application/Espo/Resources/metadata/integrations/Google.json
+++ b/application/Espo/Resources/metadata/integrations/Google.json
@@ -13,10 +13,8 @@
},
"params": {
"url": "https://accounts.google.com/o/oauth2/auth",
- "scope": "profile calendar contacts"
+ "scope": "https://www.googleapis.com/auth/calendar"
},
"allowUserAccounts": true,
- "authMethod": "OAuth2",
- "adminView": "Integrations.Google.Admin",
- "userView": "Integrations.Google.User"
+ "authMethod": "OAuth2"
}
diff --git a/application/Espo/Resources/metadata/scopes/ExternalAccount.json b/application/Espo/Resources/metadata/scopes/ExternalAccount.json
new file mode 100644
index 0000000000..6fb84e513f
--- /dev/null
+++ b/application/Espo/Resources/metadata/scopes/ExternalAccount.json
@@ -0,0 +1,7 @@
+{
+ "entity":true,
+ "layouts":false,
+ "tab":false,
+ "acl":false,
+ "customizable":false
+}
diff --git a/frontend/client/res/templates/admin/integrations/edit.tpl b/frontend/client/res/templates/admin/integrations/edit.tpl
index 9842ee3182..74c17e7faa 100644
--- a/frontend/client/res/templates/admin/integrations/edit.tpl
+++ b/frontend/client/res/templates/admin/integrations/edit.tpl
@@ -10,17 +10,17 @@
{{{enabled}}}
{{#each dataFieldList}}
-
-
- {{#if helpText}}
- {{{../helpText}}}
- {{/if}}
+ {{#if helpText}}
+
+ {{{../helpText}}}
+ {{/if}}
diff --git a/frontend/client/res/templates/admin/integrations/oauth2.tpl b/frontend/client/res/templates/admin/integrations/oauth2.tpl
new file mode 100644
index 0000000000..f661420a58
--- /dev/null
+++ b/frontend/client/res/templates/admin/integrations/oauth2.tpl
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+ {{#each dataFieldList}}
+
+ {{/each}}
+
+
+
+ {{#if helpText}}
+
+ {{{../helpText}}}
+
+ {{/if}}
+
+
diff --git a/frontend/client/res/templates/external-account/index.tpl b/frontend/client/res/templates/external-account/index.tpl
new file mode 100644
index 0000000000..761e7dcca7
--- /dev/null
+++ b/frontend/client/res/templates/external-account/index.tpl
@@ -0,0 +1,22 @@
+
+
+
+
diff --git a/frontend/client/res/templates/external-account/oauth2.tpl b/frontend/client/res/templates/external-account/oauth2.tpl
new file mode 100644
index 0000000000..46b6a869c5
--- /dev/null
+++ b/frontend/client/res/templates/external-account/oauth2.tpl
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{#if helpText}}
+
+ {{{../helpText}}}
+
+ {{/if}}
+
+
diff --git a/frontend/client/src/controllers/external-account.js b/frontend/client/src/controllers/external-account.js
new file mode 100644
index 0000000000..e05b4bbc02
--- /dev/null
+++ b/frontend/client/src/controllers/external-account.js
@@ -0,0 +1,53 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ ************************************************************************/
+
+Espo.define('Controllers.ExternalAccount', 'Controller', function (Dep) {
+
+ return Dep.extend({
+
+ defaultAction: 'list',
+
+ list: function (options) {
+ this.collectionFactory.create('ExternalAccount', function (collection) {
+ collection.once('sync', function () {
+ this.main('ExternalAccount.Index', {
+ collection: collection,
+ });
+ }, this);
+ collection.fetch();
+ }, this);
+ },
+
+ edit: function (options) {
+ var id = options.id;
+
+ this.collectionFactory.create('ExternalAccount', function (collection) {
+ collection.once('sync', function () {
+ this.main('ExternalAccount.Index', {
+ collection: collection,
+ id: id
+ });
+ }, this);
+ collection.fetch();
+ }, this);
+ },
+ });
+});
diff --git a/frontend/client/src/language.js b/frontend/client/src/language.js
index 677018428d..b571c3606f 100644
--- a/frontend/client/src/language.js
+++ b/frontend/client/src/language.js
@@ -31,6 +31,16 @@ _.extend(Espo.Language.prototype, {
cache: null,
url: 'I18n',
+
+ has: function (name, category, scope) {
+ if (scope in this.data) {
+ if (category in this.data[scope]) {
+ if (name in this.data[scope][category]) {
+ return true;
+ }
+ }
+ }
+ },
get: function (scope, category, name) {
if (scope in this.data) {
diff --git a/frontend/client/src/views/admin/integrations/edit.js b/frontend/client/src/views/admin/integrations/edit.js
index aa7f537665..272bbbefa9 100644
--- a/frontend/client/src/views/admin/integrations/edit.js
+++ b/frontend/client/src/views/admin/integrations/edit.js
@@ -46,7 +46,7 @@ Espo.define('Views.Admin.Integrations.Edit', 'View', function (Dep) {
this.integration = this.options.integration;
this.helpText = false;
- if (this.getLanguage().get(this.integration, 'help', 'Integration') != this.integration) {
+ if (this.getLanguage().has(this.integration, 'help', 'Integration')) {
this.helpText = this.translate(this.integration, 'help', 'Integration');
}
@@ -70,7 +70,7 @@ Espo.define('Views.Admin.Integrations.Edit', 'View', function (Dep) {
this.wait(true);
- var fields = this.fields = this.getMetadata().get('integrations.' + this.integration + '.fields')
+ var fields = this.fields = this.getMetadata().get('integrations.' + this.integration + '.fields');
Object.keys(this.fields).forEach(function (name) {
this.model.defs.fields[name] = this.fields[name];
@@ -88,8 +88,7 @@ Espo.define('Views.Admin.Integrations.Edit', 'View', function (Dep) {
this.wait(false);
}, this);
- this.model.fetch();
-
+ this.model.fetch();
},
hideField: function (name) {
diff --git a/frontend/client/src/views/admin/integrations/index.js b/frontend/client/src/views/admin/integrations/index.js
index 09c5c7626a..8605dc398d 100644
--- a/frontend/client/src/views/admin/integrations/index.js
+++ b/frontend/client/src/views/admin/integrations/index.js
@@ -54,7 +54,6 @@ Espo.define('Views.Admin.Integrations.Index', 'View', function (Dep) {
this.renderDefaultPage();
} else {
this.openIntegration(this.integration);
-
}
});
},
@@ -64,9 +63,9 @@ Espo.define('Views.Admin.Integrations.Index', 'View', function (Dep) {
this.getRouter().navigate('#Admin/integrations/name=' + integration, {trigger: false});
- // TODO get viewName
+ var viewName = 'Admin.Integrations.' + this.getMetadata().get('integrations.' + integration + '.authMethod');
this.notify('Loading...');
- this.createView('content', 'Admin.Integrations.Edit', {
+ this.createView('content', viewName, {
el: '#integration-content',
integration: integration,
}, function (view) {
@@ -88,7 +87,6 @@ Espo.define('Views.Admin.Integrations.Index', 'View', function (Dep) {
return;
}
$('#integration-header').show().html(this.integration);
-
},
updatePageTitle: function () {
diff --git a/frontend/client/src/views/admin/integrations/oauth2.js b/frontend/client/src/views/admin/integrations/oauth2.js
new file mode 100644
index 0000000000..623604980e
--- /dev/null
+++ b/frontend/client/src/views/admin/integrations/oauth2.js
@@ -0,0 +1,37 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ ************************************************************************/
+
+Espo.define('Views.Admin.Integrations.OAuth2', 'Views.Admin.Integrations.Edit', function (Dep) {
+
+ return Dep.extend({
+
+ template: 'admin.integrations.oauth2',
+
+ data: function () {
+
+ return _.extend({
+ redirectUri: this.getConfig().get('siteUrl') + '/oauthcallback'
+ }, Dep.prototype.data.call(this));
+ },
+
+ });
+
+});
diff --git a/frontend/client/src/views/external-account/index.js b/frontend/client/src/views/external-account/index.js
new file mode 100644
index 0000000000..c21dd65219
--- /dev/null
+++ b/frontend/client/src/views/external-account/index.js
@@ -0,0 +1,106 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ ************************************************************************/
+
+Espo.define('Views.ExternalAccount.Index', 'View', function (Dep) {
+
+ return Dep.extend({
+
+ template: 'external-account.index',
+
+ data: function () {
+ return {
+ externalAccountList: this.externalAccountList,
+ id: this.id,
+ externalAccountListCount: this.externalAccountList.length
+ };
+ },
+
+ events: {
+ 'click #external-account-menu a.external-account-link': function (e) {
+ var id = $(e.currentTarget).data('id') + '__' + this.userId;
+ this.openExternalAccount(id);
+ },
+ },
+
+ setup: function () {
+ this.externalAccountList = this.collection.toJSON();
+
+ this.userId = this.getUser().id;
+ this.id = this.options.id || null;
+ if (this.id) {
+ this.userId = this.id.split('__')[1];
+ }
+
+ this.on('after:render', function () {
+ this.renderHeader();
+ if (!this.id) {
+ this.renderDefaultPage();
+ } else {
+ this.openExternalAccount(this.id);
+ }
+ });
+ },
+
+ openExternalAccount: function (id) {
+ this.id = id;
+
+ var integration = this.integration = id.split('__')[0];
+ this.userId = id.split('__')[1];
+
+ this.getRouter().navigate('#ExternalAccount/edit/' + id, {trigger: false});
+
+ var viewName =
+ this.getMetadata().get('integrations.' + integration + '.userView') ||
+ 'ExternalAccount.' + this.getMetadata().get('integrations.' + integration + '.authMethod');
+
+ this.notify('Loading...');
+ this.createView('content', viewName, {
+ el: '#external-account-content',
+ id: id,
+ integration: integration
+ }, function (view) {
+ this.renderHeader();
+ view.render();
+ this.notify(false);
+ $(window).scrollTop(0);
+ }.bind(this));
+ },
+
+ renderDefaultPage: function () {
+ $('#external-account-header').html('').hide();
+ $('#external-account-content').html('');
+ },
+
+ renderHeader: function () {
+ if (!this.id) {
+ $('#external-account-header').html('');
+ return;
+ }
+ $('#external-account-header').show().html(this.integration);
+ },
+
+ updatePageTitle: function () {
+ this.setPageTitle(this.translate('ExternalAccount', 'scopeNamesPlural'));
+ },
+ });
+});
+
+
diff --git a/frontend/client/src/views/external-account/oauth2.js b/frontend/client/src/views/external-account/oauth2.js
new file mode 100644
index 0000000000..512457ad86
--- /dev/null
+++ b/frontend/client/src/views/external-account/oauth2.js
@@ -0,0 +1,243 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ ************************************************************************/
+
+Espo.define('Views.ExternalAccount.OAuth2', 'View', function (Dep) {
+
+ return Dep.extend({
+
+ template: 'external-account.oauth2',
+
+ events: {
+
+ },
+
+ data: function () {
+ return {
+ integration: this.integration,
+ helpText: this.helpText
+ };
+ },
+
+ events: {
+ 'click button[data-action="cancel"]': function () {
+ this.getRouter().navigate('#ExternalAccount', {trigger: true});
+ },
+ 'click button[data-action="save"]': function () {
+ this.save();
+ },
+ 'click [data-action="connect"]': function () {
+ this.connect();
+ }
+ },
+
+ setup: function () {
+ this.integration = this.options.integration;
+ this.id = this.options.id;
+
+
+ this.helpText = false;
+ if (this.getLanguage().has(this.integration, 'help', 'ExternalAccount')) {
+ this.helpText = this.translate(this.integration, 'help', 'ExternalAccount');
+ }
+
+ this.fieldList = [];
+
+ this.dataFieldList = [];
+
+ this.model = new Espo.Model();
+ this.model.id = this.id;
+ this.model.name = 'ExternalAccount';
+ this.model.urlRoot = 'ExternalAccount';
+
+ this.model.defs = {
+ fields: {
+ enabled: {
+ required: true,
+ type: 'bool'
+ },
+ }
+ };
+
+ this.wait(true);
+
+ this.model.populateDefaults();
+
+ this.listenToOnce(this.model, 'sync', function () {
+ this.createFieldView('bool', 'enabled');
+
+ $.ajax({
+ url: 'ExternalAccount/action/getOAuthCredentials?id=' + this.id,
+ dataType: 'json'
+ }).done(function (respose) {
+ this.clientId = respose.clientId;
+ this.redirectUri = respose.redirectUri;
+ this.wait(false);
+ }.bind(this));
+
+ }, this);
+
+ this.model.fetch();
+ },
+
+ hideField: function (name) {
+ this.$el.find('label.field-label-' + name).addClass('hide');
+ this.$el.find('div.field-' + name).addClass('hide');
+ var view = this.getView(name);
+ if (view) {
+ view.enabled = false;
+ }
+ },
+
+ showField: function (name) {
+ this.$el.find('label.field-label-' + name).removeClass('hide');
+ this.$el.find('div.field-' + name).removeClass('hide');
+ var view = this.getView(name);
+ if (view) {
+ view.enabled = true;
+ }
+ },
+
+ afterRender: function () {
+ if (!this.model.get('enabled')) {
+ this.$el.find('.data-panel').addClass('hidden');
+ }
+
+ this.listenTo(this.model, 'change:enabled', function () {
+ if (this.model.get('enabled')) {
+ this.$el.find('.data-panel').removeClass('hidden');
+ } else {
+ this.$el.find('.data-panel').addClass('hidden');
+ }
+ }, this);
+ },
+
+ createFieldView: function (type, name, readOnly, params) {
+ this.createView(name, this.getFieldManager().getViewName(type), {
+ model: this.model,
+ el: this.options.el + ' .field-' + name,
+ defs: {
+ name: name,
+ params: params
+ },
+ mode: readOnly ? 'detail' : 'edit',
+ readOnly: readOnly,
+ });
+ this.fieldList.push(name);
+ },
+
+ save: function () {
+ this.fieldList.forEach(function (field) {
+ var view = this.getView(field);
+ if (!view.readOnly) {
+ view.fetchToModel();
+ }
+ }, this);
+
+ var notValid = false;
+ this.fieldList.forEach(function (field) {
+ notValid = this.getView(field).validate() || notValid;
+ }, this);
+
+ if (notValid) {
+ this.notify('Not valid', 'error');
+ return;
+ }
+
+ this.listenToOnce(this.model, 'sync', function () {
+ this.notify('Saved', 'success');
+ }, this);
+
+ this.notify('Saving...');
+ this.model.save();
+ },
+
+ popup: function (options, callback) {
+ options.windowName = options.windowName || 'ConnectWithOAuth';
+ options.windowOptions = options.windowOptions || 'location=0,status=0,width=800,height=400';
+ options.callback = options.callback || function(){ window.location.reload(); };
+
+ var self = this;
+
+ var path = options.path;
+
+ var arr = [];
+ var params = (options.params || {});
+ for (var name in params) {
+ if (params[name]) {
+ arr.push(name + '=' + encodeURI(params[name]));
+ }
+ }
+ path += '?' + arr.join('&');
+
+ var parseUrl = function (str) {
+ var accessToken = false;
+ var expires = false;
+
+ str = str.substr(str.indexOf('#') + 1, str.length);
+ str.split('&').forEach(function (part) {
+ var arr = part.split('=');
+ var name = decodeURI(arr[0]);
+ var value = decodeURI(arr[1] || '');
+
+ if (name == 'access_token') {
+ accessToken = value;
+ }
+ if (name == 'expires') {
+ expires = value;
+ }
+ }, this);
+ if (accessToken) {
+ return {
+ accessToken: accessToken,
+ expires: expires
+ }
+ }
+ }
+
+ popup = window.open(path, options.windowName, options.windowOptions);
+ interval = window.setInterval(function () {
+ if (popup.closed) {
+ window.clearInterval(interval);
+ } else {
+ var res = parseUrl(popup.location.href.toString());
+ callback.call(self, res.accessToken, res.expires);
+ popup.close();
+ }
+ }, 500);
+ },
+
+ connect: function () {
+ this.popup({
+ path: this.getMetadata().get('integrations.' + this.integration + '.params.url'),
+ params: {
+ client_id: this.clientId,
+ redirect_uri: this.redirectUri,
+ scope: this.getMetadata().get('integrations.' + this.integration + '.params.scope'),
+ response_type: 'token'
+ }
+ }, function (accessToken, expires) {
+
+ });
+ },
+
+ });
+
+});