Skip to content

Commit

Permalink
Merge pull request civicrm#82 from totten/master-civimail-abtest
Browse files Browse the repository at this point in the history
CRM-15578 - DB.php and angular-jquery-dialog-service
  • Loading branch information
totten committed Nov 15, 2014
2 parents 88c9d67 + 4e8a191 commit cad9749
Show file tree
Hide file tree
Showing 9 changed files with 459 additions and 1 deletion.
1 change: 1 addition & 0 deletions DB.php
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ static function isManip($query)
. 'CREATE|DROP|'
. 'LOAD DATA|SELECT .* INTO .* FROM|COPY|'
. 'ALTER|GRANT|REVOKE|'
. 'SAVEPOINT|ROLLBACK|'
. 'LOCK|UNLOCK';
if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) {
return true;
Expand Down
3 changes: 2 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"angular-route": "1.3.x",
"angular-ui-utils": "0.1.x",
"angular-ui-sortable": "0.12.x",
"angular-unsavedChanges": "~0.1.1"
"angular-unsavedChanges": "~0.1.1",
"angular-jquery-dialog-service": "totten/angular-jquery-dialog-service#jquery-closure"
}
}
13 changes: 13 additions & 0 deletions bower_components/angular-jquery-dialog-service/.bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "angular-jquery-dialog-service",
"homepage": "https://github.com/totten/angular-jquery-dialog-service",
"_release": "dad7bd0a99",
"_resolution": {
"type": "branch",
"branch": "jquery-closure",
"commit": "dad7bd0a99408e851683dbfc18f89f57aeff9c14"
},
"_source": "git://github.com/totten/angular-jquery-dialog-service.git",
"_target": "jquery-closure",
"_originalSource": "totten/angular-jquery-dialog-service"
}
21 changes: 21 additions & 0 deletions bower_components/angular-jquery-dialog-service/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2013 Jason Stadler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
79 changes: 79 additions & 0 deletions bower_components/angular-jquery-dialog-service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
angular-jquery-dialog-service
=============================

# Overview
This service allows you to easily work with jQuery UI dialogs from Angular.js. A working sample can be viewed on [Plunker][2].

# Methods
The service exposes three methods for controlling the dialogs. These methods are `open()`, `close()`, and `cancel()`.

## open(id, template, model, options)
The open method displays a dialog. The `id` argument is a unique name to identify this dialog when calling other methods on the service such as close and cancel.


The `template` argument specifies the id of the script block that contains the template to use for the dialog or a url to a template fragment on the web server. Here is an example script block template:

```
<script type="text/ng-template" id="dialogTemplate.html">
<!-- Controller for Dialog -->
<div ng-controller="dialogCtrl">
<!-- The form -->
First Name<br>
<input type="text" ng-model="model.firstName" /><br>
Last Name<br>
<input type="text" ng-model="model.lastName" /><br>
<!-- The buttons -->
<button ng-click="cancelClick()">Cancel</button>
<button ng-click="saveClick()">Save</button>
<button ng-click="confirmClick()">Confirm</button>
</div>
</script>
```

In the case above, `template` would be set to "dialogTemplate.html".

The `model` argument contains the data that should be passed to the dialog controller's scope. It is actually injected into the dialog controller's parent scope, but it is available as `$scope.model` within the dialog.

Finally, the `options` argument contains all of the [jQuery UI dialog options][1] that you would normally pass in the call to `dialog(options)`.

The open method returns a promise that is resolved when the user closes the dialog. If the dialog controller calls dialogService.close(model), the resolve function will be called. If `cancel()` is called or the user closed the dialog using the X or ESC, the reject function will be called.

Here is an example of an open call that opens a dialog whose template is in a script block assigned an id of "dialogTemplate.html":

```javascript
dialogService.open("myDialog","dialogTemplate.html",
model: {
firstName: "Jason",
lastName: "Stadler",
update: false
},
options: {
autoOpen: false,
modal: true
}
}).then(
function(result) {
console.log("Closed");
console.log(result);
},
function(error) {
console.log("Cancelled");
}
);
```

## close(id, model)

This method is typically called by the dialog controller to close the dialog. The `id` argument is the same string passed to the open method. The `model` is the data the dialog should pass back in the promise to the caller.

## cancel(id)

This method is typically called by the dialog controller to cancel the dialog. The `id` argument is the same string passed to the open method.


[1]: http://api.jquery.ui/dialog "JQuery UI Dialog Documentation"
[2]: http://plnkr.co/edit/ADYEsplnYr8NHqASCDgS "Plunker sample"

87 changes: 87 additions & 0 deletions bower_components/angular-jquery-dialog-service/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
var app = angular.module('dialogApp', ['dialogService']);

app.controller('buttonCtrl', ['$scope', '$log', 'dialogService',
function($scope, $log, dialogService) {

$scope.openFromScriptClick = function() {
doDialog("template-from-script.html");
};

$scope.openFromUrlClick = function() {
doDialog("template-from-url.html");
};

function doDialog(template) {

// The data for the dialog
var model = {
firstName: "Jason",
lastName: "Stadler"
};

// jQuery UI dialog options
var options = {
autoOpen: false,
modal: true,
close: function(event, ui) {
$log.debug("Predefined close");
}
};

// Open the dialog using template from script
dialogService.open("myDialog", template, model, options).then(
function(result) {
$log.debug("Close");
$log.debug(result);
},
function(error) {
$log.debug("Cancelled");
}
);

}
}
]);

app.controller('dialogCtrl', ['$scope', 'dialogService',
function($scope, dialogService) {

// $scope.model contains the object passed to open in config.model

$scope.saveClick = function() {
dialogService.close("myDialog", $scope.model);
};

$scope.cancelClick = function() {
dialogService.cancel("myDialog");
};

$scope.confirmClick = function() {
// Open another dialog here
dialogService.open("myConfirm", "confirmTemplate.html")
.then(
function(result) {
console.log("Confirm");
},
function(error) {
console.log("Cancel");
}
);
};

}
]);

app.controller('confirmCtrl', ['$scope', 'dialogService',
function($scope, dialogService) {

$scope.confirmClick = function() {
dialogService.close("myConfirm");
};

$scope.cancelClick = function() {
dialogService.cancel("myConfirm");
};

}
]);
163 changes: 163 additions & 0 deletions bower_components/angular-jquery-dialog-service/dialog-service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
(function($, angular){
angular.module('dialogService', []).service('dialogService',
['$rootScope', '$q', '$compile', '$templateCache', '$http',
function($rootScope, $q, $compile, $templateCache, $http) {

var _this = this;
_this.dialogs = {};

this.open = function(id, template, model, options) {

// Check our required arguments
if (!angular.isDefined(id)) {
throw "dialogService requires id in call to open";
}

if (!angular.isDefined(template)) {
throw "dialogService requires template in call to open";
}

// Set the defaults for model
if (!angular.isDefined(model)) {
model = null;
}

// Copy options so the change ot close isn't propogated back.
// Extend is used instead of copy because window references are
// often used in the options for positioning and they can't be deep
// copied.
var dialogOptions = {};
if (angular.isDefined(options)) {
angular.extend(dialogOptions, options);
}

// Initialize our dialog structure
var dialog = { scope: null, ref: null, deferred: $q.defer() };

// Get the template from teh cache or url
loadTemplate(template).then(
function(dialogTemplate) {

// Create a new scope, inherited from the parent.
dialog.scope = $rootScope.$new();
dialog.scope.model = model;
var dialogLinker = $compile(dialogTemplate);
dialog.ref = $(dialogLinker(dialog.scope));

// Handle the case where the user provides a custom close and also
// the case where the user clicks the X or ESC and doesn't call
// close or cancel.
var customCloseFn = dialogOptions.close;
dialogOptions.close = function(event, ui) {
if (customCloseFn) {
customCloseFn(event, ui);
}
cleanup(id);
};

// Initialize the dialog and open it
dialog.ref.dialog(dialogOptions);
dialog.ref.dialog("open");

// Cache the dialog
_this.dialogs[id] = dialog;

}, function(error) {
throw error;
}
);

// Return our cached promise to complete later
return dialog.deferred.promise;
};

this.close = function(id, result) {

// Get the dialog and throw exception if not found
var dialog = getExistingDialog(id);

// Notify those waiting for the result
// This occurs first because the close calls the close handler on the
// dialog whose default action is to cancel.
dialog.deferred.resolve(result);

// Close the dialog (must be last)
dialog.ref.dialog("close");
};

this.cancel = function(id) {

// Get the dialog and throw exception if not found
var dialog = getExistingDialog(id);

// Notify those waiting for the result
// This occurs first because the cancel calls the close handler on the
// dialog whose default action is to cancel.
dialog.deferred.reject();

// Cancel and close the dialog (must be last)
dialog.ref.dialog("close");
};

function cleanup (id) {

// Get the dialog and throw exception if not found
var dialog = getExistingDialog(id);

// This is only called from the close handler of the dialog
// in case the x or escape are used to cancel the dialog. Don't
// call this from close, cancel, or externally.
dialog.deferred.reject();
dialog.scope.$destroy();

// Remove the object from the DOM
dialog.ref.remove();

// Delete the dialog from the cache
delete _this.dialogs[id];
};

function getExistingDialog(id) {

// Get the dialog from the cache
var dialog = _this.dialogs[id];
// Throw an exception if the dialog is not found
if (!angular.isDefined(dialog)) {
throw "DialogService does not have a reference to dialog id " + id;
}
return dialog;
};

// Loads the template from cache or requests and adds it to the cache
function loadTemplate(template) {

var deferred = $q.defer();
var html = $templateCache.get(template);

if (angular.isDefined(html)) {
// The template was cached or a script so return it
html = html.trim();
deferred.resolve(html);
} else {
// Retrieve the template if it is a URL
return $http.get(template, { cache : $templateCache }).then(
function(response) {
var html = response.data;
if(!html || !html.length) {
// Nothing was found so reject the promise
return $q.reject("Template " + template + " was not found");
}
html = html.trim();
// Add it to the template cache using the url as the key
$templateCache.put(template, html);
return html;
}, function() {
return $q.reject("Template " + template + " was not found");
}
);
}
return deferred.promise;
}
}
]);
})(jQuery, angular);
Loading

0 comments on commit cad9749

Please sign in to comment.