First commit

This commit is contained in:
Theodotos Andreou 2018-01-14 13:10:16 +00:00
commit c6e2478c40
13918 changed files with 2303184 additions and 0 deletions

View file

@ -0,0 +1,14 @@
<div ng-controller="CrmCxnConfirmAboutCtrl">
<div crm-ui-accordion="{title: ts('About'), collapsed: false}">
<div ng-bind-html="appMeta.desc"></div>
</div>
<div crm-ui-accordion="{title: ts('Permissions: Summary'), collapsed: true}">
<div ng-bind-html="appMeta.perm.desc"></div>
</div>
<div crm-ui-accordion="{title: ts('Permissions: Details'), collapsed: true}">
<div crm-cxn-perm-table="{perm: appMeta.perm}"></div>
</div>
<div crm-ui-accordion="{title: ts('Advanced'), collapsed: true}">
<div crm-cxn-adv-table="{appMeta: appMeta}"></div>
</div>
</div>

View file

@ -0,0 +1,5 @@
(function(angular, $, _) {
angular.module('crmCxn').controller('CrmCxnConfirmAboutCtrl', function($scope) {
$scope.ts = CRM.ts(null);
});
})(angular, CRM.$, CRM._);

View file

@ -0,0 +1,18 @@
<table>
<thead>
<tr>
<th>{{ts('Property')}}</th>
<th>{{ts('Value')}}</th>
</tr>
</thead>
<tbody>
<tr class="odd-row odd">
<td>App ID</td>
<td>{{appMeta.appId}}</td>
</tr>
<tr class="even-row even">
<td>App URL</td>
<td><code>{{appMeta.appUrl}}</code></td>
</tr>
</tbody>
</table>

View file

@ -0,0 +1,20 @@
(function(angular, $, _) {
// This directive formats the data in appMeta as a nice table.
// example: <div crm-cxn-perm-table="{appMeta: cxn.app_meta}"></div>
angular.module('crmCxn').directive('crmCxnAdvTable', function crmCxnAdvTable() {
return {
restrict: 'EA',
scope: {
crmCxnAdvTable: '='
},
templateUrl: '~/crmCxn/AdvTable.html',
link: function(scope, element, attrs) {
scope.ts = CRM.ts(null);
scope.$watch('crmCxnAdvTable', function(crmCxnAdvTable){
scope.appMeta = crmCxnAdvTable.appMeta;
});
}
};
});
})(angular, CRM.$, CRM._);

View file

@ -0,0 +1,33 @@
(function (angular, $, _) {
angular.module('crmCxn').factory('crmCxnCheckAddr', function($q, $timeout) {
var TIMEOUT = 6000, CHECK_ADDR = 'https://mycivi.org/check-addr';
return function(url) {
var dfr = $q.defer(), result = null;
function onErr() {
if (result !== null) return;
result = {url: url, valid: false};
dfr.resolve(result);
}
$.ajax({
url: CHECK_ADDR,
data: {url: url},
jsonp: "callback",
dataType: "jsonp"
}).fail(onErr)
.done(function(response) {
if (result !== null) return;
result = {url: url, valid: response.result};
dfr.resolve(result);
}
);
// JSONP may not provide errors directly.
$timeout(onErr, TIMEOUT);
return dfr.promise;
};
});
})(angular, CRM.$, CRM._);

View file

@ -0,0 +1,15 @@
<div ng-controller="CrmCxnConfirmConnectCtrl">
<p>{{ts('The application, \"%1\", requests permission to access your system.', {1: appMeta.title})}}</p>
<div crm-ui-accordion="{title: ts('About'), collapsed: true}">
<div ng-bind-html="appMeta.desc"></div>
</div>
<div crm-ui-accordion="{title: ts('Permissions: Summary'), collapsed: true}">
<div ng-bind-html="appMeta.perm.desc"></div>
</div>
<div crm-ui-accordion="{title: ts('Permissions: Details'), collapsed: true}">
<div crm-cxn-perm-table="{perm: appMeta.perm}"></div>
</div>
<div crm-ui-accordion="{title: ts('Advanced'), collapsed: true}">
<div crm-cxn-adv-table="{appMeta: appMeta}"></div>
</div>
</div>

View file

@ -0,0 +1,5 @@
(function(angular, $, _) {
angular.module('crmCxn').controller('CrmCxnConfirmConnectCtrl', function($scope) {
$scope.ts = CRM.ts(null);
});
})(angular, CRM.$, CRM._);

View file

@ -0,0 +1,23 @@
<div ng-controller="CrmCxnConfirmReconnectCtrl">
<p>{{ts('Are you sure you want to reconnect \"%1\"?', {1: appMeta.title})}}</p>
<p>{{ts('Reconnecting will change the connection details (such as callback URLs and permissions). This can be useful in a few cases, such as:')}}</p>
<ul>
<li>{{ts('After your site has migrated to a new URL.')}}</li>
<li>{{ts('After the application has migrated to a new URL.')}}</li>
<li>{{ts('After the application has changed permission requirements.')}}</li>
<li>{{ts('After the application has a major failure or reset.')}}</li>
</ul>
<div crm-ui-accordion="{title: ts('Permissions: Summary'), collapsed: true}">
<div ng-bind-html="appMeta.perm.desc"></div>
</div>
<div crm-ui-accordion="{title: ts('Permissions: Details'), collapsed: true}">
<div crm-cxn-perm-table="{perm: appMeta.perm}"></div>
</div>
<div crm-ui-accordion="{title: ts('Advanced'), collapsed: true}">
<div crm-cxn-adv-table="{appMeta: appMeta}"></div>
</div>
</div>

View file

@ -0,0 +1,5 @@
(function(angular, $, _) {
angular.module('crmCxn').controller('CrmCxnConfirmReconnectCtrl', function($scope) {
$scope.ts = CRM.ts(null);
});
})(angular, CRM.$, CRM._);

View file

@ -0,0 +1,4 @@
<p>{{ts('There was a problem verifying that this site is available on the public Internet.')}}</p>
<p>{{ts('See also:')}}
<a href="https://civicrm.org/inapp/civiconnect-firewall" target="_blank">{{ts('Firewalls and Proxies')}}</a>
</p>

View file

@ -0,0 +1,3 @@
<div ng-controller="CrmCxnLinkDialogCtrl">
<iframe crm-ui-iframe crm-ui-iframe-src="model.url"></iframe>
</div>

View file

@ -0,0 +1,11 @@
(function(angular, $, _) {
// Controller for the "Open Link" dialog
// Scope members:
// - [input] "model": Object
// - "url": string
angular.module('crmCxn').controller('CrmCxnLinkDialogCtrl', function CrmCxnLinkDialogCtrl($scope, dialogService) {
var ts = $scope.ts = CRM.ts(null);
});
})(angular, CRM.$, CRM._);

View file

@ -0,0 +1,117 @@
<div crm-ui-debug="appMetas"></div>
<div crm-ui-debug="cxns"></div>
<div crm-ui-debug="alerts"></div>
<!--
The merits of this layout:
* On a fresh install, the available connections show up first.
* Once you've made a connection, the extant connections bubble up.
* Extant connections can be portrayed as enabled or disabled.
-->
<div class="help">
<p>{{ts('Connections provide a simplified way to link your CiviCRM installation to an external service.')}}</p>
</div>
<div ng-show="cxns.length > 0">
<span crm-ui-order="{var: 'cxnOrder', defaults: ['-created_date']}"></span>
<h3>{{ts('Existing Connections')}}</h3>
<table class="display">
<thead>
<tr>
<th>{{ts('Title')}}</th> <!-- <a crm-ui-order-by="[cxnOrder, 'app_meta.appId']"> -->
<th>{{ts('Description')}}</th> <!-- <a crm-ui-order-by="[cxnOrder, 'desc']"> -->
<th>{{ts('Status')}}</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="cxn in cxns | orderBy:cxnOrder.get()" ng-class-even="'even-row even'" ng-class-odd="'odd-row odd'">
<td>
<a class="action-item"
crm-confirm='{width: "65%", resizable: true, title:ts("%1: About", {1: cxn.app_meta.title}), templateUrl: "~/crmCxn/AboutCtrl.html", export: {appMeta: cxn.app_meta}}'
>{{cxn.app_meta.title}}</a>
</td>
<td><div ng-bind-html="cxn.app_meta.desc"></div></td>
<td>{{cxn.is_active=="1" ? ts('Enabled') : ts('Disabled')}}</td>
<td>
<span>
<a class="action-item crm-hover-button" ng-click="openLink(cxn.app_meta, 'settings', {title: ts('%1: Settings (External)', {1: cxn.app_meta.title})})" ng-show="cxn.app_meta.links.settings">{{ts('Settings')}}</a>
<span class="btn-slide crm-hover-button">{{ts('more')}}
<ul class="panel" style="display: none;">
<li ng-show="cxn.app_meta.links.logs">
<a class="action-item crm-hover-button" ng-click="openLink(cxn.app_meta, 'logs', {title: ts('%1: Logs (External)', {1: cxn.app_meta.title})})">
{{ts('Logs')}}
</a>
</li>
<li ng-show="cxn.app_meta.links.docs">
<a class="action-item crm-hover-button" ng-click="openLink(cxn.app_meta, 'docs', {title: ts('%1: Documentation (External)', {1: cxn.app_meta.title})})">
{{ts('Docs')}}
</a>
</li>
<li ng-show="cxn.app_meta.links.support">
<a class="action-item crm-hover-button" ng-click="openLink(cxn.app_meta, 'support', {title: ts('%1: Support (External)', {1: cxn.app_meta.title})})">
{{ts('Support')}}
</a>
</li>
<li>
<a class="action-item crm-hover-button" ng-click="toggleCxn(cxn)">{{ cxn.is_active=="1" ? ts('Disable') : ts('Enable')}}</a>
</li>
<li>
<a class="action-item crm-hover-button"
crm-confirm='{width: "65%", resizable: true, title:ts("%1: Reconnect", {1: cxn.app_meta.title}), templateUrl: "~/crmCxn/ConfirmReconnectCtrl.html", export: {cxn: cxn, appMeta: findAppByAppId(cxn.app_guid)}}'
on-yes="reregister(cxn.app_meta)"
>{{ts('Reconnect')}}</a>
</li>
<li>
<a class="action-item crm-hover-button"
crm-confirm='{width: "65%", resizable: true, title: ts("%1: Disconnect", {1: cxn.app_meta.title}), message: ts("Are you sure you want to disconnect \"%1?\". Doing so may permanently destroy data linkage.", {1: cxn.app_meta.title})}'
on-yes="unregister(cxn.app_meta)">
{{ts('Disconnect')}}
</a>
</li>
</ul>
</span>
</span>
</td>
</tr>
</tbody>
</table>
<br/>
</div>
<div ng-show="hasAvailApps()">
<span crm-ui-order="{var: 'availOrder', defaults: ['title']}"></span>
<h3>{{ts('New Connections')}}</h3>
<table class="display">
<thead>
<tr>
<th><a crm-ui-order-by="[availOrder, 'title']">{{ts('Title')}}</a></th>
<th><a crm-ui-order-by="[availOrder, 'desc']">{{ts('Description')}}</a></th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="appMeta in appMetas | orderBy:availOrder.get()" ng-show="!findCxnByAppId(appMeta.appId)" ng-class-even="'even-row even'" ng-class-odd="'odd-row odd'">
<td>
<a crm-confirm='{width: "65%", resizable: true, title:ts("%1: About", {1: appMeta.title}), templateUrl: "~/crmCxn/AboutCtrl.html", export: {appMeta: appMeta}}'
>{{appMeta.title}}</a>
</td>
<td><div ng-bind-html="appMeta.desc"></div></td>
<td>
<a class="action-item crm-hover-button"
crm-confirm='{width: "65%", resizable: true, title:ts("%1: Connect", {1: appMeta.title}), templateUrl: "~/crmCxn/ConfirmConnectCtrl.html", export: {appMeta: appMeta}}'
on-yes="register(appMeta)"
>{{ts('Connect')}}</a>
</td>
</tr>
</tbody>
</table>
</div>
<div ng-show="appMetas.length === 0" class="messages status no-popup">
<i class="crm-i fa-info-circle"></i>
{{ts('No available applications')}}
</div>

View file

@ -0,0 +1,153 @@
(function(angular, $, _) {
angular.module('crmCxn').controller('CrmCxnManageCtrl', function CrmCxnManageCtrl($scope, apiCalls, crmApi, crmUiAlert, crmBlocker, crmStatus, $timeout, dialogService, crmCxnCheckAddr) {
var ts = $scope.ts = CRM.ts(null);
if (apiCalls.appMetas.is_error) {
$scope.appMetas = [];
CRM.alert(apiCalls.appMetas.error_message, ts('Application List Unavailable'), 'error');
}
else {
$scope.appMetas = apiCalls.appMetas.values;
}
$scope.cxns = apiCalls.cxns.values;
$scope.alerts = _.where(apiCalls.sysCheck.values, {name: 'checkCxnOverrides'});
crmCxnCheckAddr(apiCalls.cfg.values.siteCallbackUrl).then(function(response) {
if (response.valid) return;
crmUiAlert({
type: 'warning',
title: ts('Internet Access Required'),
templateUrl: '~/crmCxn/Connectivity.html',
scope: $scope.$new(),
options: {expires: false}
});
});
$scope.filter = {};
var block = $scope.block = crmBlocker();
_.each($scope.alerts, function(alert){
crmUiAlert({text: alert.message, title: alert.title, type: 'error'});
});
// Convert array [x] to x|null|error
function asOne(result, msg) {
switch (result.length) {
case 0:
return null;
case 1:
return result[0];
default:
throw msg;
}
}
$scope.findCxnByAppId = function(appId) {
var result = _.where($scope.cxns, {
app_guid: appId
});
return asOne(result, "Error: Too many connections for appId: " + appId);
};
$scope.findAppByAppId = function(appId) {
var result = _.where($scope.appMetas, {
appId: appId
});
return asOne(result, "Error: Too many apps for appId: " + appId);
};
$scope.hasAvailApps = function() {
// This should usu return after the 1st or 2nd item, but in testing with small# apps, we may exhaust the list.
for (var i = 0; i< $scope.appMetas.length; i++) {
if (!$scope.findCxnByAppId($scope.appMetas[i].appId)) {
return true;
}
}
return false;
};
$scope.refreshCxns = function() {
crmApi('Cxn', 'get', {sequential: 1}).then(function(result) {
$timeout(function(){
$scope.cxns = result.values;
});
});
};
$scope.register = function(appMeta) {
var reg = crmApi('Cxn', 'register', {app_guid: appMeta.appId}).then($scope.refreshCxns).then(function() {
if (appMeta.links.welcome) {
return $scope.openLink(appMeta, 'welcome', {title: ts('%1: Welcome (External)', {1: appMeta.title})});
}
});
return block(crmStatus({start: ts('Connecting...'), success: ts('Connected')}, reg));
};
$scope.reregister = function(appMeta) {
var reg = crmApi('Cxn', 'register', {app_guid: appMeta.appId}).then($scope.refreshCxns).then(function() {
if (appMeta.links.welcome) {
return $scope.openLink(appMeta, 'welcome', {title: ts('%1: Welcome (External)', {1: appMeta.title})});
}
});
return block(crmStatus({start: ts('Reconnecting...'), success: ts('Reconnected')}, reg));
};
$scope.unregister = function(appMeta) {
var reg = crmApi('Cxn', 'unregister', {app_guid: appMeta.appId, debug: 1}).then($scope.refreshCxns);
return block(crmStatus({start: ts('Disconnecting...'), success: ts('Disconnected')}, reg));
};
$scope.toggleCxn = function toggleCxn(cxn) {
var is_active = (cxn.is_active=="1" ? 0 : 1); // we switch the flag
var reg = crmApi('Cxn', 'create', {id: cxn.id, app_guid: cxn.app_meta.appId, is_active: is_active, debug: 1}).then(function(){
cxn.is_active = is_active;
});
return block(crmStatus({start: ts('Saving...'), success: ts('Saved')}, reg));
};
$scope.openLink = function openLink(appMeta, page, options) {
var promise = crmApi('Cxn', 'getlink', {app_guid: appMeta.appId, page_name: page}).then(function(result) {
var mode = result.values.mode ? result.values.mode : 'popup';
switch (result.values.mode) {
case 'iframe':
var passThrus = ['height', 'width']; // Options influenced by remote server.
options = angular.extend(_.pick(result.values, passThrus), options);
$scope.openIframe(result.values.url, options);
break;
case 'popup':
CRM.alert(ts('The page "%1" will open in a popup. If it does not appear automatically, check your browser for notifications.', {1: options.title}), '', 'info');
window.open(result.values.url, 'cxnSettings', 'resizable,scrollbars,status');
break;
case 'redirect':
window.location = result.values.url;
break;
default:
CRM.alert(ts('Cannot open link. Unrecognized mode.'), '', 'error');
}
});
return block(crmStatus({start: ts('Opening...'), success: ''}, promise));
};
// @param Object options -- see dialogService.open
$scope.openIframe = function openIframe(url, options) {
var model = {
url: url
};
options = CRM.utils.adjustDialogDefaults(angular.extend(
{
autoOpen: false,
height: 'auto',
width: '40%',
title: ts('External Link')
},
options
));
return dialogService.open('cxnLinkDialog', '~/crmCxn/LinkDialogCtrl.html', model, options)
.then(function(item) {
mailing.msg_template_id = item.id;
return item;
});
};
});
})(angular, CRM.$, CRM._);

View file

@ -0,0 +1,42 @@
<table>
<thead>
<tr>
<th>{{ts('Entity')}}</th>
<th>{{ts('Action(s)')}}</th>
<th>{{ts('Filter(s)')}}</th>
<th>{{ts('Field(s)')}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="api in perm.api"
ng-class-even="'even-row even'"
ng-class-odd="'odd-row odd'">
<td>
<em ng-show="api.entity == '*'">{{ts('Any')}}</em>
<code ng-hide="api.entity == '*'">{{api.entity}}</code>
</td>
<td>
<div ng-switch="isString(api.actions)">
<span ng-switch-when="true">
<em ng-show="api.actions == '*'">{{ts('Any')}}</em>
<code ng-hide="api.actions == '*'">{{api.actions}}</code>
</span>
<span ng-switch-default="">
<span ng-repeat="action in api.actions"><code>{{action}}</code><span ng-show="!$last">, </span></span>
</span>
</div>
</td>
<td>
<em ng-show="!hasRequiredFilters(api)">{{ts('Any')}}</em>
<div ng-repeat="(field,value) in api.required"><code>{{field}}</code> = "<code>{{value}}</code>"<span ng-show="!$last">, </span></div>
</td>
<td>
<em ng-show="api.fields == '*'">{{ts('Any')}}</em>
<span ng-hide="api.fields == '*'" ng-repeat="field in api.fields"><code>{{field}}</code><span ng-show="!$last">, </span></span>
</td>
</tr>
</tbody>
</table>
<div class="crmCxn-footer">
<em ng-bind-html="ts('For in-depth details about entities and actions, see the <a href=\'%1\' target=\'%2\'>API Explorer</a>.', {1: apiExplorerUrl, 2: '_blank'})"></em>
</div>

View file

@ -0,0 +1,27 @@
(function(angular, $, _) {
// This directive formats the data in appMeta.perm as a nice table.
// example: <div crm-cxn-perm-table="{perm: cxn.app_meta.perm}"></div>
angular.module('crmCxn').directive('crmCxnPermTable', function crmCxnPermTable() {
return {
restrict: 'EA',
scope: {
crmCxnPermTable: '='
},
templateUrl: '~/crmCxn/PermTable.html',
link: function(scope, element, attrs) {
scope.ts = CRM.ts(null);
scope.hasRequiredFilters = function(api) {
return !_.isEmpty(api.required);
};
scope.isString = function(v) {
return _.isString(v);
};
scope.apiExplorerUrl = CRM.url('civicrm/api');
scope.$watch('crmCxnPermTable', function(crmCxnPermTable){
scope.perm = crmCxnPermTable.perm;
});
}
};
});
})(angular, CRM.$, CRM._);