diff --git a/core/ArchiveProcessor/Rules.php b/core/ArchiveProcessor/Rules.php index 2b14bc975428699830f4f9ff9404ee45fc3598d8..a64a4f81ad2ce4a9f2d9a6b9c344db9ac854515b 100644 --- a/core/ArchiveProcessor/Rules.php +++ b/core/ArchiveProcessor/Rules.php @@ -293,7 +293,7 @@ class Rules */ public static function shouldSkipUniqueVisitorsCalculationForMultipleSites() { - return Config::getInstance()->General['enable_processing_unique_visitors_multiple_sites'] == 1; + return Config::getInstance()->General['enable_processing_unique_visitors_multiple_sites'] != 1; } /** diff --git a/core/Piwik.php b/core/Piwik.php index 9e53964e60520090094978402cd773f421b9598b..ccaee84962fd44c70021952904540b9dda90a545 100644 --- a/core/Piwik.php +++ b/core/Piwik.php @@ -131,7 +131,7 @@ class Piwik public static function getJavascriptCode($idSite, $piwikUrl, $mergeSubdomains = false, $groupPageTitlesByDomain = false, $mergeAliasUrls = false, $visitorCustomVariables = false, $pageCustomVariables = false, $customCampaignNameQueryParam = false, $customCampaignKeywordParam = false, - $doNotTrack = false) + $doNotTrack = false, $disableCookies = false) { // changes made to this code should be mirrored in plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js var generateJsCode $jsCode = file_get_contents(PIWIK_INCLUDE_PATH . "/plugins/Morpheus/templates/javascriptCode.tpl"); @@ -182,6 +182,9 @@ class Piwik if ($doNotTrack) { $options .= ' _paq.push(["setDoNotTrack", true]);' . PHP_EOL; } + if ($disableCookies) { + $options .= ' _paq.push(["disableCookies"]);' . PHP_EOL; + } $codeImpl = array( 'idSite' => $idSite, diff --git a/core/Plugin/Segment.php b/core/Plugin/Segment.php index 4281495a35d2b7c961b06f98002c2b1fbfe6b92e..cc3392eebc1e77cc07af142f2c45a7a32888ded4 100644 --- a/core/Plugin/Segment.php +++ b/core/Plugin/Segment.php @@ -50,6 +50,7 @@ class Segment private $sqlFilterValue; private $acceptValues; private $permission; + private $suggestedValuesCallback; /** * @ignore @@ -185,6 +186,15 @@ class Segment return $this->type; } + /** + * Set callback which will be executed when user will call for suggested values for segment. + * + * @param callable $suggestedValuesCallback + */ + public function setSuggestedValuesCallback($suggestedValuesCallback) { + $this->suggestedValuesCallback = $suggestedValuesCallback; + } + /** * You can restrict the access to this segment by passing a boolean `false`. For instance if you want to make * a certain segment only available to users having super user access you could do the following: @@ -227,6 +237,10 @@ class Segment $segment['permission'] = $this->permission; } + if (is_callable($this->suggestedValuesCallback)) { + $segment['suggestedValuesCallback'] = $this->suggestedValuesCallback; + } + return $segment; } } diff --git a/libs/angularjs/ngDialog/.gitignore b/libs/angularjs/ngDialog/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4bcc1e1e1496ee61827319dda876d8d1bdfddaa0 --- /dev/null +++ b/libs/angularjs/ngDialog/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +node_modules +bower_components +*.log \ No newline at end of file diff --git a/libs/angularjs/ngDialog/.jshintrc b/libs/angularjs/ngDialog/.jshintrc new file mode 100644 index 0000000000000000000000000000000000000000..9ded1c286674e5bccdda1c13baecd6abbd593f8a --- /dev/null +++ b/libs/angularjs/ngDialog/.jshintrc @@ -0,0 +1,35 @@ +{ + "predef": [ + "angular" + ], + + "asi" : false, + "bitwise" : true, + "boss" : false, + "browser" : true, + "curly" : true, + "debug": false, + "devel": false, + "eqeqeq": true, + "evil": false, + "expr": true, + "forin": false, + "immed": true, + "jquery" : true, + "latedef" : false, + "laxbreak": false, + "multistr": true, + "newcap": true, + "noarg": true, + "node" : true, + "noempty": false, + "nonew": true, + "onevar": false, + "plusplus": false, + "regexp": false, + "strict": false, + "sub": false, + "trailing" : true, + "undef": true, + "unused": "vars" +} diff --git a/libs/angularjs/ngDialog/Gruntfile.js b/libs/angularjs/ngDialog/Gruntfile.js new file mode 100644 index 0000000000000000000000000000000000000000..599216b880a770507236e4e255bb98e8f948741f --- /dev/null +++ b/libs/angularjs/ngDialog/Gruntfile.js @@ -0,0 +1,52 @@ +module.exports = function (grunt) { + + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + uglify: { + options: { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> (<%= pkg.homepage %>) */\n' + }, + ngDialog: { + files: { + './js/ngDialog.min.js': ['./js/ngDialog.js'] + } + } + }, + jshint: { + options: { + ignores: ['./js/ngDialog.min.js'] + }, + files: ['*.js'] + }, + myth: { + dist: { + files: { + './css/ngDialog.css': './css/myth/ngDialog.css', + './css/ngDialog-theme-default.css': './css/myth/ngDialog-theme-default.css', + './css/ngDialog-theme-plain.css': './css/myth/ngDialog-theme-plain.css' + } + } + }, + cssmin: { + options: { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> (<%= pkg.homepage %>) */\n' + }, + minify:{ + files: { + 'css/ngDialog.min.css': ['css/ngDialog.css'], + 'css/ngDialog-theme-default.min.css': ['css/ngDialog-theme-default.css'], + 'css/ngDialog-theme-plain.min.css': ['css/ngDialog-theme-plain.css'] + } + } + } + }); + + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-myth'); + grunt.loadNpmTasks('grunt-contrib-cssmin'); + + grunt.registerTask('default', ['jshint']); + grunt.registerTask('build', ['uglify', 'myth', 'cssmin']); + grunt.registerTask('css', ['myth', 'cssmin']); +}; \ No newline at end of file diff --git a/libs/angularjs/ngDialog/README.md b/libs/angularjs/ngDialog/README.md new file mode 100644 index 0000000000000000000000000000000000000000..907dc44d6589b5011ec3c94f70c484eda014654c --- /dev/null +++ b/libs/angularjs/ngDialog/README.md @@ -0,0 +1,326 @@ +# ngDialog + +Modal dialogs and popups provider for [Angular.js](http://angularjs.org/) applications. + +ngDialog is small (~2Kb), has minimalistic API, highly customizable through themes and has only Angular.js as dependency. + +### [Demo](http://likeastore.github.io/ngDialog) + +## Install + +You can download all necessary ngDialog files manually or install it with bower: + +```bash +bower install ngDialog +``` + +## Usage + +You need only to include ``ngDialog.js`` and ``ngDialog.css`` (as minimal setup) to your project and then you can start using ``ngDialog`` provider in your directives, controllers and services. For example in controllers: + +```javascript +var app = angular.module('exampleApp', ['ngDialog']); + +app.controller('MainCtrl', function ($scope, ngDialog) { + $scope.clickToOpen = function () { + ngDialog.open({ template: 'popupTmpl.html' }); + }; +}); +``` + +## API + +ngDialog service provides easy to use and minimalistic API, but in the same time it's powerful enough. Here is the list of accessible methods that you can use: + +=== + +### ``.open(options)`` + +Method allows to open dialog window, creates new dialog instance on each call. It accepts ``options`` object as the only argument. + +### Options: + +##### ``template {String}`` + +Dialog template can be loaded through ``path`` to external html template or ``<script>`` tag with ``text/ng-template``: + +```html +<script type="text/ng-template" id="templateId"> + <h1>Template heading</h1> + <p>Content goes here</p> +</script> +``` + +```javascript +ngDialog.open({ template: 'templateId' }); +``` + +Also it is possible to use simple string as template together with ``plain`` option. + +##### ``plain {Boolean}`` + +If ``true`` allows to use plain string as template, default ``false``: + +```javascript +ngDialog.open({ + template: '<p>my template</p>', + plain: true +}); +``` + +##### ``controller {String} | {Array} | {Object}`` + +Controller that will be used for dialog window if necessary. The controller can be specified either by referring it by name or directly inline. + +```javascript +ngDialog.open({ + template: 'externalTemplate.html', + controller: 'SomeController' +}); +``` + +or + +```javascript +ngDialog.open({ + template: 'externalTemplate.html', + controller: ['$scope', 'otherService', function($scope, otherService) { + // controller logic + }] +}); +``` + +##### ``scope {Object}`` + +Scope object that will be passed to dialog. If you use controller with separate ``$scope`` service this object will be passed to ``$scope.$parent`` param: + +```javascript +$scope.value = true; + +ngDialog.open({ + template: 'externalTemplate.html', + className: 'ngdialog-theme-plain', + scope: $scope +}); +``` + +```html +<script type="text/ng-template" id="externalTemplate.html"> +<p>External scope: <code>{{value}}</code></p> +</script> +``` + +##### ``scope.closeThisDialog(value)`` + +In addition ``.closeThisDialog(value)`` method gets injected to passed ``$scope``. This allows you to close dialog straight from handler in a popup element, for example: + +```html +<div class="dialog-contents"> + <input type="text"/> + <input type="button" value="OK" ng-click="checkInput() && closeThisDialog('Some value')"/> +</div> +``` + +Any value passed to this function will be attached to the object which resolves on the close promise for this dialog. For dialogs opened with the ``openConfirm()`` method the value is used as the reject reason. + +##### ``data {String | Object | Array}`` + +Any data that you want to be stored in controller's ``$parent`` scope, it could be stringified JSON as well. + +##### ``className {String}`` + +This option allows to controll dialog look, you can use built-in [themes](https://github.com/likeastore/ngDialog#themes) or create your own styled modals. + +This example enables one of built-in ngDialog themes - ``ngdialog-theme-default`` (do not forget to include necessary css files): + +```javascript +ngDialog.open({ + template: 'templateId', + className: 'ngdialog-theme-default' +}); +``` + +Check [themes](https://github.com/likeastore/ngDialog#themes) block to learn more. + +##### ``showClose {Boolean}`` + +If ``false`` it allows to hide close button on modals, default ``true``. + +##### ``closeByEscape {Boolean}`` + +It allows to close modals by clicking ``Esc`` button, default ``true``. + +This will close all open modals if there several of them open at the same time. + +##### ``closeByDocument {Boolean}`` + +It allows to close modals by clicking on overlay background, default ``true``. If [Hammer.js](https://github.com/EightMedia/hammer.js) is loaded, it will listen for ``tap`` instead of ``click``. + +##### ``appendTo {String}`` + +Specify your element where to append dialog instance, accepts selector string (e.g. ``#yourId``, ``.yourClass``). If not specified appends dialog to ``body`` as default behavior. + +### Defaults + +##### ``setDefaults(options)`` + +You're able to set default settings through ``ngDialogProvider``: + +```javascript +var app = angular.module('myApp', ['ngDialog']); +app.config(['ngDialogProvider', function (ngDialogProvider) { + ngDialogProvider.setDefaults({ + className: 'ngdialog-theme-default', + plain: true, + showClose: true, + closeByDocument: true, + closeByEscape: true + }); +}]); +``` + +### Returns: + +The ``open()`` method returns an object with some useful properties. + +##### ``id {String}`` + +This is the ID of the dialog which was just created. It is the ID on the dialog's DOM element. + +##### ``close(value) {Function}`` + +This is a function which will close the dialog which was opened by the current call to ``open()``. It takes an optional value to pass to the close promise. + +##### ``closePromise {Promise}`` + +A promise which will resolve when the dialog is closed. It is resolved with an object containing: ``id`` - the ID of the closed dialog, ``value`` - the value the dialog was closed with, ``$dialog`` - the dialog element which at this point has been removed from the DOM and ``remainingDialogs`` - the number of dialogs still open. + +The value property will be a special string if the dialog is dismissed by one of the built in mechanisms: `'$escape'`, `'$closeButton'` or `'$document'`. + +This allows you do to something like this: + +```javascript +var dialog = ngDialog.open({ + template: 'templateId' +}); + +dialog.closePromise.then(function (data) { + console.log(data.id + ' has been dismissed.'); +}); +``` + +=== + +### ``.openConfirm(options)`` + +Opens a dialog that by default does not close when hitting escape or clicking outside the dialog window. The function returns a promise that is either resolved or rejected depending on the way the dialog was closed. + +### Options: + +The options are the same as the regular [``.open()``](https://github.com/likeastore/ngDialog#options) method with an extra function added to the scope: + +##### ``scope.confirm()`` + +In addition to the ``.closeThisDialog()`` method. The method ``.confirm()`` is also injected to passed ``$scope``. Use this method to close the dialog and ``resolve`` the promise that was returned when opening the modal. + +The function accepts a single optional parameter which is used as the value of the resolved promise. + +```html +<div class="dialog-contents"> + Some message + <button ng-click="closeThisDialog()">Cancel</button> + <button ng-click="confirm()">Confirm</button> +</div> +``` + +### Returns: + +An Angular promise object that is resolved if the ``.confirm()`` function is used to close the dialog, otherwise the promise is rejected. The resolve value and the reject reason is defined by the value passed to the ``confirm()`` or ``closeThisDialog()`` call respectively. + +=== + +### ``.close(id, value)`` + +Method accepts dialog's ``id`` as string argument to close specific dialog window, if ``id`` is not specified it will close all currently active modals (same behavior as ``.closeAll()``). Takes an optional value to resolve the dialog promise with (or all dialog promises). + +=== + +### ``.closeAll(value)`` + +Method manages closing all active modals on the page. Takes an optional value to resolve all of the dialog promises with. + +=== + +### ``.setForceBodyReload({Boolean})`` + +Adds additional listener on every ``$locationChangeSuccess`` event and gets update version of ``body`` into dialog. Maybe useful in some rare cases when you're dependant on DOM changes, defaults to ``false``. Use it in module's config as provider instance: + +```javascript +var app = angular.module('exampleApp', ['ngDialog']); + +app.config(function (ngDialogProvider) { + ngDialogProvider.setForceBodyReload(true); +}); +``` + +## Directive + +By default ngDialog module is served with ``ngDialog`` directive which can be used as attribute for buttons, links, etc. Almost all ``.open()`` options are available through tag attributes as well, the only difference is that ``ng-template`` id or path of template file is required. + +Some imaginary button, for example, will look like: + +```html +<button type="button" + ng-dialog="templateId.html" + ng-dialog-class="ngdialog-theme-flat" + ng-dialog-controller="ModalCtrl" + ng-dialog-close-previous> + Open modal text +</button> +``` + +Directive contains one more additional but very useful option, it's an attribute named ``ng-dialog-close-previous``. It allows you to close previously opened dialogs automaticly. + +## Events + +Everytime when ngDialog is opened or closed we're broadcasting two events (dispatching events downwards to all child scopes): + +- ``ngDialog.opened`` + +- ``ngDialog.closed`` + +This allows you to register your own listeners, example: + +```javascript +$rootScope.$on('ngDialog.opened', function (e, $dialog) { + console.log('ngDialog opened: ' + $dialog.attr('id')); +}); +``` + +## Themes + +Currently ngDialog contains two default themes that show how easily you can create your own. Check ``example`` folder for demonstration purposes. + +## CDN + +ngDialog is available for public on [cdnjs](http://cdnjs.com/libraries/ng-dialog). Please use following urls for version 0.1.6. + +```html +//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.1.6/ng-dialog.min.css +//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.1.6/ng-dialog-theme-plain.min.css +//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.1.6/ng-dialog.min.js +``` + +## License + +MIT Licensed + +Copyright (c) 2013-2014, Likeastore.com <info@likeastore.com> + +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. + +[](https://bitdeli.com/free "Bitdeli Badge") diff --git a/libs/angularjs/ngDialog/bower.json b/libs/angularjs/ngDialog/bower.json new file mode 100644 index 0000000000000000000000000000000000000000..8d7dd14e7ad0b6f8727ce239e6f36fe3d1da515a --- /dev/null +++ b/libs/angularjs/ngDialog/bower.json @@ -0,0 +1,38 @@ +{ + "name": "ngDialog", + "version": "0.2.14", + "homepage": "https://github.com/likeastore/ngDialog", + "description": "Modal dialogs and popups provider for Angular.js applications", + "main": [ + "js/ngDialog.js", + "css/ngDialog.css", + "css/ngDialog-theme-default.css" + ], + "keywords": [ + "angular.js", + "modals", + "popups", + "dialog", + "ng", + "provider", + "factory", + "directive" + ], + "authors": [ + "Dmitri Voronianski" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests", + "example", + "css/myth", + "Gruntfile.js" + ], + "dependencies": { + "angular": "~1" + } +} diff --git a/libs/angularjs/ngDialog/css/myth/ngDialog-theme-default.css b/libs/angularjs/ngDialog/css/myth/ngDialog-theme-default.css new file mode 100644 index 0000000000000000000000000000000000000000..742c1bd220f24835ce17288d65b7831bf2f4c20f --- /dev/null +++ b/libs/angularjs/ngDialog/css/myth/ngDialog-theme-default.css @@ -0,0 +1,146 @@ +@keyframes ngdialog-flyin { + 0% { + opacity: 0; + transform: translateY(-40px); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes ngdialog-flyout { + 0% { + opacity: 1; + transform: translateY(0); + } + + 100% { + opacity: 0; + transform: translateY(-40px); + } +} + +.ngdialog.ngdialog-theme-default { + padding-bottom: 160px; + padding-top: 160px; +} + +.ngdialog.ngdialog-theme-default.ngdialog-closing .ngdialog-content { + animation: ngdialog-flyout .5s; +} + +.ngdialog.ngdialog-theme-default .ngdialog-content { + animation: ngdialog-flyin .5s; + background: #f0f0f0; + border-radius: 5px; + color: #444; + font-family: 'Helvetica',sans-serif; + font-size: 1.1em; + line-height: 1.5em; + margin: 0 auto; + max-width: 100%; + padding: 1em; + position: relative; + width: 450px; +} + +.ngdialog.ngdialog-theme-default .ngdialog-close { + border-radius: 5px; + cursor: pointer; + position: absolute; + right: 0; + top: 0; +} + +.ngdialog.ngdialog-theme-default .ngdialog-close:before { + background: transparent; + border-radius: 3px; + color: #bbb; + content: '\00D7'; + font-size: 26px; + font-weight: 400; + height: 30px; + line-height: 26px; + position: absolute; + right: 3px; + text-align: center; + top: 3px; + width: 30px; +} + +.ngdialog.ngdialog-theme-default .ngdialog-close:hover:before,.ngdialog.ngdialog-theme-default .ngdialog-close:active:before { + color: #777; +} + +.ngdialog.ngdialog-theme-default .ngdialog-message { + margin-bottom: .5em; +} + +.ngdialog.ngdialog-theme-default .ngdialog-input { + margin-bottom: 1em; +} + +.ngdialog.ngdialog-theme-default .ngdialog-input textarea,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="text"],.ngdialog.ngdialog-theme-default .ngdialog-input input[type="password"],.ngdialog.ngdialog-theme-default .ngdialog-input input[type="email"],.ngdialog.ngdialog-theme-default .ngdialog-input input[type="url"] { + background: #fff; + border: 0; + border-radius: 3px; + font-family: inherit; + font-size: inherit; + font-weight: inherit; + margin: 0 0 .25em; + min-height: 2.5em; + padding: .25em .67em; + width: 100%; +} + +.ngdialog.ngdialog-theme-default .ngdialog-input textarea:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="text"]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="password"]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="email"]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type="url"]:focus { + box-shadow: inset 0 0 0 2px #8dbdf1; + outline: none; +} + +.ngdialog.ngdialog-theme-default .ngdialog-buttons { + *zoom: 1; +} + +.ngdialog.ngdialog-theme-default .ngdialog-buttons:after { + content: ''; + display: table; + clear: both; +} + +.ngdialog.ngdialog-theme-default .ngdialog-button { + border: 0; + border-radius: 3px; + cursor: pointer; + float: right; + font-family: inherit; + font-size: .8em; + letter-spacing: .1em; + line-height: 1em; + margin: 0 0 0 .5em; + padding: .75em 2em; + text-transform: uppercase; +} + +.ngdialog.ngdialog-theme-default .ngdialog-button:focus { + animation: ngdialog-pulse 1.1s infinite; + outline: none; +} + +@media (max-width: 568px) { + .ngdialog.ngdialog-theme-default .ngdialog-button:focus { + animation: none; + } +} + +.ngdialog.ngdialog-theme-default .ngdialog-button.ngdialog-button-primary { + background: #3288e6; + color: #fff; +} + +.ngdialog.ngdialog-theme-default .ngdialog-button.ngdialog-button-secondary { + background: #e0e0e0; + color: #777; +} diff --git a/libs/angularjs/ngDialog/css/myth/ngDialog-theme-plain.css b/libs/angularjs/ngDialog/css/myth/ngDialog-theme-plain.css new file mode 100644 index 0000000000000000000000000000000000000000..2b101f4e1fee76e21600da01b098b5f8e41f4aa8 --- /dev/null +++ b/libs/angularjs/ngDialog/css/myth/ngDialog-theme-plain.css @@ -0,0 +1,112 @@ +.ngdialog.ngdialog-theme-plain { + padding-bottom: 160px; + padding-top: 160px; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-content { + background: #fff; + color: #444; + font-family: 'Helvetica Neue',sans-serif; + font-size: 1.1em; + line-height: 1.5em; + margin: 0 auto; + max-width: 100%; + padding: 1em; + position: relative; + width: 450px; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-content h1,.ngdialog.ngdialog-theme-plain .ngdialog-content h2,.ngdialog.ngdialog-theme-plain .ngdialog-content h3,.ngdialog.ngdialog-theme-plain .ngdialog-content h4,.ngdialog.ngdialog-theme-plain .ngdialog-content h5,.ngdialog.ngdialog-theme-plain .ngdialog-content h6,.ngdialog.ngdialog-theme-plain .ngdialog-content p,.ngdialog.ngdialog-theme-plain .ngdialog-content ul,.ngdialog.ngdialog-theme-plain .ngdialog-content li { + color: inherit; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-close { + cursor: pointer; + position: absolute; + right: 0; + top: 0; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-close:before { + background: transparent; + color: #bbb; + content: "\00D7"; + font-size: 26px; + font-weight: 400; + height: 30px; + line-height: 26px; + position: absolute; + right: 3px; + text-align: center; + top: 3px; + width: 30px; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-close:hover:before,.ngdialog.ngdialog-theme-plain .ngdialog-close:active:before { + color: #777; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-message { + margin-bottom: .5em; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-input { + margin-bottom: 1em; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-input textarea,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="text"],.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="password"],.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="email"],.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="url"] { + background: #f0f0f0; + border: 0; + font-family: inherit; + font-size: inherit; + font-weight: inherit; + margin: 0 0 .25em; + min-height: 2.5em; + padding: .25em .67em; + width: 100%; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-input textarea:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="text"]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="password"]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="email"]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="url"]:focus { + box-shadow: inset 0 0 0 2px rgba(0,0,0,0.2); + outline: none; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-buttons:after { + clear: both; + content: ''; + display: table; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button { + border: 0; + cursor: pointer; + float: right; + font-family: inherit; + font-size: .8em; + letter-spacing: .1em; + line-height: 1em; + margin: 0 0 0 .5em; + padding: .75em 2em; + text-transform: uppercase; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button:focus { + animation: ngdialog-pulse 1.1s infinite; + outline: none; +} + +@media (max-width: 568px) { + .ngdialog.ngdialog-theme-plain .ngdialog-button:focus { + animation: none; + } +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button.ngdialog-button-primary { + background: #3288e6; + color: #fff; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button.ngdialog-button-secondary { + background: #e0e0e0; + color: #777; +} diff --git a/libs/angularjs/ngDialog/css/myth/ngDialog.css b/libs/angularjs/ngDialog/css/myth/ngDialog.css new file mode 100644 index 0000000000000000000000000000000000000000..40acd9d63d508f2faa3dfeec3508b371b8472703 --- /dev/null +++ b/libs/angularjs/ngDialog/css/myth/ngDialog.css @@ -0,0 +1,71 @@ +@keyframes ngdialog-fadeout { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes ngdialog-fadein { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +.ngdialog, .ngdialog *, .ngdialog *:before, .ngdialog *:after { + box-sizing: border-box; +} + +.ngdialog { + position: fixed; + overflow: auto; + -webkit-overflow-scrolling: touch; + z-index: 10000; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +.ngdialog-overlay { + position: fixed; + background: rgba(0, 0, 0, 0.4); + top: 0; + right: 0; + bottom: 0; + left: 0; + -webkit-backface-visibility: hidden; + animation: ngdialog-fadein 0.5s; +} + +.ngdialog.ngdialog-closing .ngdialog-overlay { + -webkit-backface-visibility: hidden; + animation: ngdialog-fadeout 0.5s; +} + +.ngdialog-content { + background: white; + -webkit-backface-visibility: hidden; + animation: ngdialog-fadein 0.5s; +} + +.ngdialog.ngdialog-closing .ngdialog-content { + -webkit-backface-visibility: hidden; + animation: ngdialog-fadeout 0.5s; +} + +.ngdialog-close:before { + font-family: 'Helvetica', Arial, sans-serif; + content: '\00D7'; + cursor: pointer; +} + +body.ngdialog-open { + overflow: hidden; +} diff --git a/libs/angularjs/ngDialog/css/ngDialog-theme-default.css b/libs/angularjs/ngDialog/css/ngDialog-theme-default.css new file mode 100644 index 0000000000000000000000000000000000000000..d163a5403ad14637c085f4341970a13c72e15289 --- /dev/null +++ b/libs/angularjs/ngDialog/css/ngDialog-theme-default.css @@ -0,0 +1,196 @@ +@-webkit-keyframes ngdialog-flyin { + 0% { + opacity: 0; + -webkit-transform: translateY(-40px); + transform: translateY(-40px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes ngdialog-flyin { + 0% { + opacity: 0; + -webkit-transform: translateY(-40px); + -ms-transform: translateY(-40px); + transform: translateY(-40px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +@-webkit-keyframes ngdialog-flyout { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-40px); + transform: translateY(-40px); + } +} + +@keyframes ngdialog-flyout { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-40px); + -ms-transform: translateY(-40px); + transform: translateY(-40px); + } +} + +.ngdialog.ngdialog-theme-default { + padding-bottom: 160px; + padding-top: 160px; +} + +.ngdialog.ngdialog-theme-default.ngdialog-closing .ngdialog-content { + -webkit-animation: ngdialog-flyout .5s; + animation: ngdialog-flyout .5s; +} + +.ngdialog.ngdialog-theme-default .ngdialog-content { + -webkit-animation: ngdialog-flyin .5s; + animation: ngdialog-flyin .5s; + background: #f0f0f0; + border-radius: 5px; + color: #444; + font-family: 'Helvetica',sans-serif; + font-size: 1.1em; + line-height: 1.5em; + margin: 0 auto; + max-width: 100%; + padding: 1em; + position: relative; + width: 450px; +} + +.ngdialog.ngdialog-theme-default .ngdialog-close { + border-radius: 5px; + cursor: pointer; + position: absolute; + right: 0; + top: 0; +} + +.ngdialog.ngdialog-theme-default .ngdialog-close:before { + background: transparent; + border-radius: 3px; + color: #bbb; + content: '\00D7'; + font-size: 26px; + font-weight: 400; + height: 30px; + line-height: 26px; + position: absolute; + right: 3px; + text-align: center; + top: 3px; + width: 30px; +} + +.ngdialog.ngdialog-theme-default .ngdialog-close:hover:before, +.ngdialog.ngdialog-theme-default .ngdialog-close:active:before { + color: #777; +} + +.ngdialog.ngdialog-theme-default .ngdialog-message { + margin-bottom: .5em; +} + +.ngdialog.ngdialog-theme-default .ngdialog-input { + margin-bottom: 1em; +} + +.ngdialog.ngdialog-theme-default .ngdialog-input textarea, +.ngdialog.ngdialog-theme-default .ngdialog-input input[type="text"], +.ngdialog.ngdialog-theme-default .ngdialog-input input[type="password"], +.ngdialog.ngdialog-theme-default .ngdialog-input input[type="email"], +.ngdialog.ngdialog-theme-default .ngdialog-input input[type="url"] { + background: #fff; + border: 0; + border-radius: 3px; + font-family: inherit; + font-size: inherit; + font-weight: inherit; + margin: 0 0 .25em; + min-height: 2.5em; + padding: .25em .67em; + width: 100%; +} + +.ngdialog.ngdialog-theme-default .ngdialog-input textarea:focus, +.ngdialog.ngdialog-theme-default .ngdialog-input input[type="text"]:focus, +.ngdialog.ngdialog-theme-default .ngdialog-input input[type="password"]:focus, +.ngdialog.ngdialog-theme-default .ngdialog-input input[type="email"]:focus, +.ngdialog.ngdialog-theme-default .ngdialog-input input[type="url"]:focus { + -webkit-box-shadow: inset 0 0 0 2px #8dbdf1; + box-shadow: inset 0 0 0 2px #8dbdf1; + outline: none; +} + +.ngdialog.ngdialog-theme-default .ngdialog-buttons { + *zoom: 1; +} + +.ngdialog.ngdialog-theme-default .ngdialog-buttons:after { + content: ''; + display: table; + clear: both; +} + +.ngdialog.ngdialog-theme-default .ngdialog-button { + border: 0; + border-radius: 3px; + cursor: pointer; + float: right; + font-family: inherit; + font-size: .8em; + letter-spacing: .1em; + line-height: 1em; + margin: 0 0 0 .5em; + padding: .75em 2em; + text-transform: uppercase; +} + +.ngdialog.ngdialog-theme-default .ngdialog-button:focus { + -webkit-animation: ngdialog-pulse 1.1s infinite; + animation: ngdialog-pulse 1.1s infinite; + outline: none; +} + +@media (max-width: 568px) { + .ngdialog.ngdialog-theme-default .ngdialog-button:focus { + -webkit-animation: none; + animation: none; + } +} + +.ngdialog.ngdialog-theme-default .ngdialog-button.ngdialog-button-primary { + background: #3288e6; + color: #fff; +} + +.ngdialog.ngdialog-theme-default .ngdialog-button.ngdialog-button-secondary { + background: #e0e0e0; + color: #777; +} \ No newline at end of file diff --git a/libs/angularjs/ngDialog/css/ngDialog-theme-default.min.css b/libs/angularjs/ngDialog/css/ngDialog-theme-default.min.css new file mode 100644 index 0000000000000000000000000000000000000000..24bcfccb2753942d302245504f8a3f6e2e3fdda1 --- /dev/null +++ b/libs/angularjs/ngDialog/css/ngDialog-theme-default.min.css @@ -0,0 +1,3 @@ +/*! ng-dialog - v0.2.14 (https://github.com/likeastore/ngDialog) */ + +@-webkit-keyframes ngdialog-flyin{0%{opacity:0;-webkit-transform:translateY(-40px);transform:translateY(-40px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes ngdialog-flyin{0%{opacity:0;-webkit-transform:translateY(-40px);-ms-transform:translateY(-40px);transform:translateY(-40px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes ngdialog-flyout{0%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-40px);transform:translateY(-40px)}}@keyframes ngdialog-flyout{0%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-40px);-ms-transform:translateY(-40px);transform:translateY(-40px)}}.ngdialog.ngdialog-theme-default{padding-bottom:160px;padding-top:160px}.ngdialog.ngdialog-theme-default.ngdialog-closing .ngdialog-content{-webkit-animation:ngdialog-flyout .5s;animation:ngdialog-flyout .5s}.ngdialog.ngdialog-theme-default .ngdialog-content{-webkit-animation:ngdialog-flyin .5s;animation:ngdialog-flyin .5s;background:#f0f0f0;border-radius:5px;color:#444;font-family:Helvetica,sans-serif;font-size:1.1em;line-height:1.5em;margin:0 auto;max-width:100%;padding:1em;position:relative;width:450px}.ngdialog.ngdialog-theme-default .ngdialog-close{border-radius:5px;cursor:pointer;position:absolute;right:0;top:0}.ngdialog.ngdialog-theme-default .ngdialog-close:before{background:0 0;border-radius:3px;color:#bbb;content:'\00D7';font-size:26px;font-weight:400;height:30px;line-height:26px;position:absolute;right:3px;text-align:center;top:3px;width:30px}.ngdialog.ngdialog-theme-default .ngdialog-close:active:before,.ngdialog.ngdialog-theme-default .ngdialog-close:hover:before{color:#777}.ngdialog.ngdialog-theme-default .ngdialog-message{margin-bottom:.5em}.ngdialog.ngdialog-theme-default .ngdialog-input{margin-bottom:1em}.ngdialog.ngdialog-theme-default .ngdialog-input input[type=email],.ngdialog.ngdialog-theme-default .ngdialog-input input[type=password],.ngdialog.ngdialog-theme-default .ngdialog-input input[type=text],.ngdialog.ngdialog-theme-default .ngdialog-input input[type=url],.ngdialog.ngdialog-theme-default .ngdialog-input textarea{background:#fff;border:0;border-radius:3px;font-family:inherit;font-size:inherit;font-weight:inherit;margin:0 0 .25em;min-height:2.5em;padding:.25em .67em;width:100%}.ngdialog.ngdialog-theme-default .ngdialog-input input[type=email]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type=password]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type=text]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input input[type=url]:focus,.ngdialog.ngdialog-theme-default .ngdialog-input textarea:focus{-webkit-box-shadow:inset 0 0 0 2px #8dbdf1;box-shadow:inset 0 0 0 2px #8dbdf1;outline:0}.ngdialog.ngdialog-theme-default .ngdialog-buttons{*zoom:1}.ngdialog.ngdialog-theme-default .ngdialog-buttons:after{content:'';display:table;clear:both}.ngdialog.ngdialog-theme-default .ngdialog-button{border:0;border-radius:3px;cursor:pointer;float:right;font-family:inherit;font-size:.8em;letter-spacing:.1em;line-height:1em;margin:0 0 0 .5em;padding:.75em 2em;text-transform:uppercase}.ngdialog.ngdialog-theme-default .ngdialog-button:focus{-webkit-animation:ngdialog-pulse 1.1s infinite;animation:ngdialog-pulse 1.1s infinite;outline:0}@media (max-width:568px){.ngdialog.ngdialog-theme-default .ngdialog-button:focus{-webkit-animation:none;animation:none}}.ngdialog.ngdialog-theme-default .ngdialog-button.ngdialog-button-primary{background:#3288e6;color:#fff}.ngdialog.ngdialog-theme-default .ngdialog-button.ngdialog-button-secondary{background:#e0e0e0;color:#777} \ No newline at end of file diff --git a/libs/angularjs/ngDialog/css/ngDialog-theme-plain.css b/libs/angularjs/ngDialog/css/ngDialog-theme-plain.css new file mode 100644 index 0000000000000000000000000000000000000000..b058b53eb9a5449e50b3a79ef4a522709952f670 --- /dev/null +++ b/libs/angularjs/ngDialog/css/ngDialog-theme-plain.css @@ -0,0 +1,132 @@ +.ngdialog.ngdialog-theme-plain { + padding-bottom: 160px; + padding-top: 160px; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-content { + background: #fff; + color: #444; + font-family: 'Helvetica Neue',sans-serif; + font-size: 1.1em; + line-height: 1.5em; + margin: 0 auto; + max-width: 100%; + padding: 1em; + position: relative; + width: 450px; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-content h1, +.ngdialog.ngdialog-theme-plain .ngdialog-content h2, +.ngdialog.ngdialog-theme-plain .ngdialog-content h3, +.ngdialog.ngdialog-theme-plain .ngdialog-content h4, +.ngdialog.ngdialog-theme-plain .ngdialog-content h5, +.ngdialog.ngdialog-theme-plain .ngdialog-content h6, +.ngdialog.ngdialog-theme-plain .ngdialog-content p, +.ngdialog.ngdialog-theme-plain .ngdialog-content ul, +.ngdialog.ngdialog-theme-plain .ngdialog-content li { + color: inherit; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-close { + cursor: pointer; + position: absolute; + right: 0; + top: 0; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-close:before { + background: transparent; + color: #bbb; + content: "\00D7"; + font-size: 26px; + font-weight: 400; + height: 30px; + line-height: 26px; + position: absolute; + right: 3px; + text-align: center; + top: 3px; + width: 30px; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-close:hover:before, +.ngdialog.ngdialog-theme-plain .ngdialog-close:active:before { + color: #777; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-message { + margin-bottom: .5em; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-input { + margin-bottom: 1em; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-input textarea, +.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="text"], +.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="password"], +.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="email"], +.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="url"] { + background: #f0f0f0; + border: 0; + font-family: inherit; + font-size: inherit; + font-weight: inherit; + margin: 0 0 .25em; + min-height: 2.5em; + padding: .25em .67em; + width: 100%; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-input textarea:focus, +.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="text"]:focus, +.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="password"]:focus, +.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="email"]:focus, +.ngdialog.ngdialog-theme-plain .ngdialog-input input[type="url"]:focus { + -webkit-box-shadow: inset 0 0 0 2px rgba(0,0,0,0.2); + box-shadow: inset 0 0 0 2px rgba(0,0,0,0.2); + outline: none; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-buttons:after { + clear: both; + content: ''; + display: table; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button { + border: 0; + cursor: pointer; + float: right; + font-family: inherit; + font-size: .8em; + letter-spacing: .1em; + line-height: 1em; + margin: 0 0 0 .5em; + padding: .75em 2em; + text-transform: uppercase; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button:focus { + -webkit-animation: ngdialog-pulse 1.1s infinite; + animation: ngdialog-pulse 1.1s infinite; + outline: none; +} + +@media (max-width: 568px) { + .ngdialog.ngdialog-theme-plain .ngdialog-button:focus { + -webkit-animation: none; + animation: none; + } +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button.ngdialog-button-primary { + background: #3288e6; + color: #fff; +} + +.ngdialog.ngdialog-theme-plain .ngdialog-button.ngdialog-button-secondary { + background: #e0e0e0; + color: #777; +} \ No newline at end of file diff --git a/libs/angularjs/ngDialog/css/ngDialog-theme-plain.min.css b/libs/angularjs/ngDialog/css/ngDialog-theme-plain.min.css new file mode 100644 index 0000000000000000000000000000000000000000..45e07ec821f3626149b6592756930ee168e3a674 --- /dev/null +++ b/libs/angularjs/ngDialog/css/ngDialog-theme-plain.min.css @@ -0,0 +1,3 @@ +/*! ng-dialog - v0.2.14 (https://github.com/likeastore/ngDialog) */ + +.ngdialog.ngdialog-theme-plain{padding-bottom:160px;padding-top:160px}.ngdialog.ngdialog-theme-plain .ngdialog-content{background:#fff;color:#444;font-family:'Helvetica Neue',sans-serif;font-size:1.1em;line-height:1.5em;margin:0 auto;max-width:100%;padding:1em;position:relative;width:450px}.ngdialog.ngdialog-theme-plain .ngdialog-content h1,.ngdialog.ngdialog-theme-plain .ngdialog-content h2,.ngdialog.ngdialog-theme-plain .ngdialog-content h3,.ngdialog.ngdialog-theme-plain .ngdialog-content h4,.ngdialog.ngdialog-theme-plain .ngdialog-content h5,.ngdialog.ngdialog-theme-plain .ngdialog-content h6,.ngdialog.ngdialog-theme-plain .ngdialog-content li,.ngdialog.ngdialog-theme-plain .ngdialog-content p,.ngdialog.ngdialog-theme-plain .ngdialog-content ul{color:inherit}.ngdialog.ngdialog-theme-plain .ngdialog-close{cursor:pointer;position:absolute;right:0;top:0}.ngdialog.ngdialog-theme-plain .ngdialog-close:before{background:0 0;color:#bbb;content:"\00D7";font-size:26px;font-weight:400;height:30px;line-height:26px;position:absolute;right:3px;text-align:center;top:3px;width:30px}.ngdialog.ngdialog-theme-plain .ngdialog-close:active:before,.ngdialog.ngdialog-theme-plain .ngdialog-close:hover:before{color:#777}.ngdialog.ngdialog-theme-plain .ngdialog-message{margin-bottom:.5em}.ngdialog.ngdialog-theme-plain .ngdialog-input{margin-bottom:1em}.ngdialog.ngdialog-theme-plain .ngdialog-input input[type=email],.ngdialog.ngdialog-theme-plain .ngdialog-input input[type=password],.ngdialog.ngdialog-theme-plain .ngdialog-input input[type=text],.ngdialog.ngdialog-theme-plain .ngdialog-input input[type=url],.ngdialog.ngdialog-theme-plain .ngdialog-input textarea{background:#f0f0f0;border:0;font-family:inherit;font-size:inherit;font-weight:inherit;margin:0 0 .25em;min-height:2.5em;padding:.25em .67em;width:100%}.ngdialog.ngdialog-theme-plain .ngdialog-input input[type=email]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type=password]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type=text]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input input[type=url]:focus,.ngdialog.ngdialog-theme-plain .ngdialog-input textarea:focus{-webkit-box-shadow:inset 0 0 0 2px rgba(0,0,0,.2);box-shadow:inset 0 0 0 2px rgba(0,0,0,.2);outline:0}.ngdialog.ngdialog-theme-plain .ngdialog-buttons:after{clear:both;content:'';display:table}.ngdialog.ngdialog-theme-plain .ngdialog-button{border:0;cursor:pointer;float:right;font-family:inherit;font-size:.8em;letter-spacing:.1em;line-height:1em;margin:0 0 0 .5em;padding:.75em 2em;text-transform:uppercase}.ngdialog.ngdialog-theme-plain .ngdialog-button:focus{-webkit-animation:ngdialog-pulse 1.1s infinite;animation:ngdialog-pulse 1.1s infinite;outline:0}@media (max-width:568px){.ngdialog.ngdialog-theme-plain .ngdialog-button:focus{-webkit-animation:none;animation:none}}.ngdialog.ngdialog-theme-plain .ngdialog-button.ngdialog-button-primary{background:#3288e6;color:#fff}.ngdialog.ngdialog-theme-plain .ngdialog-button.ngdialog-button-secondary{background:#e0e0e0;color:#777} \ No newline at end of file diff --git a/libs/angularjs/ngDialog/css/ngDialog.css b/libs/angularjs/ngDialog/css/ngDialog.css new file mode 100644 index 0000000000000000000000000000000000000000..cfbbb65272e60eb0fa5428232a4b0331a7d65588 --- /dev/null +++ b/libs/angularjs/ngDialog/css/ngDialog.css @@ -0,0 +1,100 @@ +@-webkit-keyframes ngdialog-fadeout { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes ngdialog-fadeout { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@-webkit-keyframes ngdialog-fadein { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes ngdialog-fadein { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +.ngdialog, +.ngdialog *, +.ngdialog *:before, +.ngdialog *:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.ngdialog { + position: fixed; + overflow: auto; + -webkit-overflow-scrolling: touch; + z-index: 10000; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +.ngdialog-overlay { + position: fixed; + background: rgba(0, 0, 0, 0.4); + top: 0; + right: 0; + bottom: 0; + left: 0; + -webkit-backface-visibility: hidden; + -webkit-animation: ngdialog-fadein 0.5s; + animation: ngdialog-fadein 0.5s; +} + +.ngdialog.ngdialog-closing .ngdialog-overlay { + -webkit-backface-visibility: hidden; + -webkit-animation: ngdialog-fadeout 0.5s; + animation: ngdialog-fadeout 0.5s; +} + +.ngdialog-content { + background: white; + -webkit-backface-visibility: hidden; + -webkit-animation: ngdialog-fadein 0.5s; + animation: ngdialog-fadein 0.5s; +} + +.ngdialog.ngdialog-closing .ngdialog-content { + -webkit-backface-visibility: hidden; + -webkit-animation: ngdialog-fadeout 0.5s; + animation: ngdialog-fadeout 0.5s; +} + +.ngdialog-close:before { + font-family: 'Helvetica', Arial, sans-serif; + content: '\00D7'; + cursor: pointer; +} + +body.ngdialog-open { + overflow: hidden; +} \ No newline at end of file diff --git a/libs/angularjs/ngDialog/css/ngDialog.min.css b/libs/angularjs/ngDialog/css/ngDialog.min.css new file mode 100644 index 0000000000000000000000000000000000000000..746f2564fc4d8cb596b976e8f650afa7753fe46a --- /dev/null +++ b/libs/angularjs/ngDialog/css/ngDialog.min.css @@ -0,0 +1,3 @@ +/*! ng-dialog - v0.2.14 (https://github.com/likeastore/ngDialog) */ + +@-webkit-keyframes ngdialog-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes ngdialog-fadeout{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes ngdialog-fadein{0%{opacity:0}100%{opacity:1}}@keyframes ngdialog-fadein{0%{opacity:0}100%{opacity:1}}.ngdialog,.ngdialog *,.ngdialog :after,.ngdialog :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.ngdialog{position:fixed;overflow:auto;-webkit-overflow-scrolling:touch;z-index:10000;top:0;right:0;bottom:0;left:0}.ngdialog-overlay{position:fixed;background:rgba(0,0,0,.4);top:0;right:0;bottom:0;left:0;-webkit-backface-visibility:hidden;-webkit-animation:ngdialog-fadein .5s;animation:ngdialog-fadein .5s}.ngdialog.ngdialog-closing .ngdialog-overlay{-webkit-backface-visibility:hidden;-webkit-animation:ngdialog-fadeout .5s;animation:ngdialog-fadeout .5s}.ngdialog-content{background:#fff;-webkit-backface-visibility:hidden;-webkit-animation:ngdialog-fadein .5s;animation:ngdialog-fadein .5s}.ngdialog.ngdialog-closing .ngdialog-content{-webkit-backface-visibility:hidden;-webkit-animation:ngdialog-fadeout .5s;animation:ngdialog-fadeout .5s}.ngdialog-close:before{font-family:Helvetica,Arial,sans-serif;content:'\00D7';cursor:pointer}body.ngdialog-open{overflow:hidden} \ No newline at end of file diff --git a/libs/angularjs/ngDialog/example/README.md b/libs/angularjs/ngDialog/example/README.md new file mode 100644 index 0000000000000000000000000000000000000000..2a87d1a6ab39aa04489d97c597712c8da0699d70 --- /dev/null +++ b/libs/angularjs/ngDialog/example/README.md @@ -0,0 +1,24 @@ +# Usage examples + +### Static file + +You can try ``index.html`` file simply by opening it in a browser. + +### Server demo + +Or you can check usage of external templates by starting a web server in this folder. At first install npm dependencies from a route folder: + +```bash +$ ngDialog_folder: npm install +``` + +Then go to examples folder and start server: + +```bash +$ ngDialog_folder: cd example +$ ngDialog_folder/example: node server.js +>> Strata web server version 0.20.1 +>> Listening on 0.0.0.0:1982, CTRL+C to stop +``` + +And check in browser url ``0.0.0.0:1982/example/index.html``. diff --git a/libs/angularjs/ngDialog/example/externalTemplate.html b/libs/angularjs/ngDialog/example/externalTemplate.html new file mode 100644 index 0000000000000000000000000000000000000000..22529e23d8e26dbed876d0e4a71d615d107a8bde --- /dev/null +++ b/libs/angularjs/ngDialog/example/externalTemplate.html @@ -0,0 +1 @@ +<p>External modal template with external scope: <code>{{value}}</code></p> \ No newline at end of file diff --git a/libs/angularjs/ngDialog/example/index.html b/libs/angularjs/ngDialog/example/index.html new file mode 100644 index 0000000000000000000000000000000000000000..f48cf90dfb872eb15ae8ab0eb8cb104bbef3ec90 --- /dev/null +++ b/libs/angularjs/ngDialog/example/index.html @@ -0,0 +1,225 @@ +<!doctype html> +<html ng-app="exampleDialog"> +<head> + <meta charset="utf-8"> + <title>ngDialog demo</title> + <link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700,400italic' rel='stylesheet' type='text/css'> + <link rel="stylesheet" href="../css/ngDialog.css"> + <link rel="stylesheet" href="../css/ngDialog-theme-default.css"> + <link rel="stylesheet" href="../css/ngDialog-theme-plain.css"> + + <style> + a, button { + font: 14px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + display: block; + color: #333; + margin-bottom: 10px; + } + </style> +</head> +<body ng-controller="MainCtrl"> + + <a href="" ng-click="open()">Open via service</a> + + <button type="button" + ng-dialog="firstDialogId" + ng-dialog-controller="InsideCtrl" + ng-dialog-data="{{jsonData}}" + ng-dialog-class="ngdialog-theme-default" + ng-dialog-scope="this" + ng-dialog-show-close="false">Open via directive</button> + + <a href="" ng-click="openDefault()">Default theme</a> + <a href="" ng-click="openPlain()">Plain theme</a> + <a href="" ng-click="openInlineController()">Inline controller</a> + <a href="" ng-click="openTemplate()">Open with external template for modal</a> + <a href="" ng-click="openTimed()">Open and use return value to close later</a> + <a href="" ng-click="openNotify()">Open and use promise to know when closed</a> + <a href="" ng-click="openConfirm()">Open confirm modal</a> + + <script type="text/ng-template" id="firstDialogId"> + <div class="ngdialog-message"> + <h3>ngDialog template</h3> + <p ng-show="theme">Test content for <code>{{theme}}</code></p> + <p ng-show="ngDialogData.foo">Data passed through directive: <code>{{ngDialogData.foo}}</code></p> + <p ng-show="dialogModel.message">Scope passed through directive: <code>{{dialogModel.message}}</code></p> + </div> + <div class="ngdialog-buttons"> + <button type="button" class="ngdialog-button ngdialog-button-secondary" + ng-dialog="secondDialogId" + ng-dialog-class="ngdialog-theme-default" + ng-dialog-controller="SecondModalCtrl" + ng-dialog-close-previous>Close and open</button> + <button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="openSecond()">Open next</button> + </div> + </script> + + <script type="text/ng-template" id="withInlineController"> + <div class="ngdialog-message"> + <h3>ngDialog template</h3> + <p ng-show="theme">Test content for <code>{{theme}}</code></p> + <p ng-show="exampleExternalData">Example data from external service: <code>{{exampleExternalData}}</code></p> + </div> + <div class="ngdialog-buttons"> + <button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="closeThisDialog()">Close</button> + </div> + </script> + + <script type="text/ng-template" id="secondDialogId"> + <h3><a href="" ng-click="closeSecond()">Close all by click here!</a></h3> + </script> + + <script type="text/ng-template" id="modalDialogId"> + <div class="ngdialog-message"> + <h3>ngDialog modal example</h3> + <p>The <code>.openConfirm()</code> function returns a promise that is resolved when confirmed and rejected when otherwise closed. Modal dialogs by default do not close when clicked outside the dialog or when hitting escape. This can ofcourse be overridden when opening the dialog.</p> + <p>Confirm can take a value. Enter one here for example and see the console output: <input ng-model="confirmValue" /></p> + </div> + <div class="ngdialog-buttons"> + <button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="confirm(confirmValue)">Confirm</button> + <button type="button" class="ngdialog-button ngdialog-button-secondary" ng-click="closeThisDialog('button')">Cancel</button> + </div> + </script> + + <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script> + <script>window.angular || document.write('<script src="../bower_components/angular/angular.min.js">\x3C/script>')</script> + <script src="../js/ngDialog.js"></script> + <script> + var app = angular.module('exampleDialog', ['ngDialog']); + + // Example of how to set default values for all dialogs + app.config(['ngDialogProvider', function (ngDialogProvider) { + ngDialogProvider.setDefaults({ + className: 'ngdialog-theme-default', + plain: false, + showClose: true, + closeByDocument: true, + closeByEscape: true, + appendTo: false + }); + }]); + + app.controller('MainCtrl', function ($scope, $rootScope, ngDialog) { + $rootScope.jsonData = '{"foo": "bar"}'; + $rootScope.theme = 'ngdialog-theme-default'; + + $scope.open = function () { + ngDialog.open({ template: 'firstDialogId', controller: 'InsideCtrl' }); + }; + + $scope.openDefault = function () { + ngDialog.open({ + template: 'firstDialogId', + controller: 'InsideCtrl', + className: 'ngdialog-theme-default' + }); + }; + + $scope.openConfirm = function () { + ngDialog.openConfirm({ + template: 'modalDialogId', + className: 'ngdialog-theme-default' + }).then(function (value) { + console.log('Modal promise resolved. Value: ', value); + }, function (reason) { + console.log('Modal promise rejected. Reason: ', reason); + }); + }; + + $scope.openPlain = function () { + $rootScope.theme = 'ngdialog-theme-plain'; + + ngDialog.open({ + template: 'firstDialogId', + controller: 'InsideCtrl', + className: 'ngdialog-theme-plain', + closeByDocument: false + }); + }; + + $scope.openInlineController = function () { + $rootScope.theme = 'ngdialog-theme-plain'; + + ngDialog.open({ + template: 'withInlineController', + controller: ['$scope', '$timeout', function ($scope, $timeout) { + var counter = 0; + var timeout; + function count() { + $scope.exampleExternalData = 'Counter ' + (counter++); + timeout = $timeout(count, 450); + } + count(); + $scope.$on('$destroy', function () { + $timeout.cancel(timeout); + }); + }], + className: 'ngdialog-theme-plain' + }); + }; + + $scope.openTemplate = function () { + $scope.value = true; + + ngDialog.open({ + template: 'externalTemplate.html', + className: 'ngdialog-theme-plain', + scope: $scope + }); + }; + + $scope.openTimed = function () { + var dialog = ngDialog.open({ + template: '<p>Just passing through!</p>', + plain: true, + closeByDocument: false, + closeByEscape: false + }); + setTimeout(function () { + dialog.close(); + }, 2000); + }; + + $scope.openNotify = function () { + var dialog = ngDialog.open({ + template: '<p>You can do whatever you want when I close, however that happens.</p>' + + '<div class="ngdialog-buttons"><button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="closeThisDialog(1)">Close Me</button></div>', + plain: true + }); + dialog.closePromise.then(function (data) { + console.log('ngDialog closed' + (data.value === 1 ? ' using the button' : '') + ' and notified by promise: ' + data.id); + }); + }; + + $rootScope.$on('ngDialog.opened', function (e, $dialog) { + console.log('ngDialog opened: ' + $dialog.attr('id')); + }); + + $rootScope.$on('ngDialog.closed', function (e, $dialog) { + console.log('ngDialog closed: ' + $dialog.attr('id')); + }); + }); + + app.controller('InsideCtrl', function ($scope, ngDialog) { + $scope.dialogModel = { + message : 'message from passed scope' + }; + $scope.openSecond = function () { + ngDialog.open({ + template: '<h3><a href="" ng-click="closeSecond()">Close all by click here!</a></h3>', + plain: true, + closeByEscape: false, + controller: 'SecondModalCtrl' + }); + }; + }); + + app.controller('SecondModalCtrl', function ($scope, ngDialog) { + $scope.closeSecond = function () { + ngDialog.close(); + }; + }); + + </script> +</body> +</html> diff --git a/libs/angularjs/ngDialog/example/server.js b/libs/angularjs/ngDialog/example/server.js new file mode 100644 index 0000000000000000000000000000000000000000..f381235441e614599bd9b6fc2934618d7c48fd2c --- /dev/null +++ b/libs/angularjs/ngDialog/example/server.js @@ -0,0 +1,10 @@ +var path = require('path'); +var server = require('strata'); +var address = require('network-address'); + +var root = path.resolve('../'); + +server.use(server.commonLogger); +server.use(server.file, root); +server.run(); +console.log(address()); diff --git a/libs/angularjs/ngDialog/js/ngDialog.js b/libs/angularjs/ngDialog/js/ngDialog.js new file mode 100644 index 0000000000000000000000000000000000000000..5c393901e858c46484b125172d98fc656fcd2a33 --- /dev/null +++ b/libs/angularjs/ngDialog/js/ngDialog.js @@ -0,0 +1,348 @@ +/* + * ngDialog - easy modals and popup windows + * http://github.com/likeastore/ngDialog + * (c) 2013 MIT License, https://likeastore.com + */ + +(function (window, angular, undefined) { + 'use strict'; + + var module = angular.module('ngDialog', []); + + var $el = angular.element; + var isDef = angular.isDefined; + var style = (document.body || document.documentElement).style; + var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation); + var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend'; + var forceBodyReload = false; + + module.provider('ngDialog', function () { + var defaults = this.defaults = { + className: 'ngdialog-theme-default', + plain: false, + showClose: true, + closeByDocument: true, + closeByEscape: true, + appendTo: false + }; + + this.setForceBodyReload = function (_useIt) { + forceBodyReload = _useIt || false; + }; + + this.setDefaults = function (newDefaults) { + angular.extend(defaults, newDefaults); + }; + + var globalID = 0, dialogsCount = 0, closeByDocumentHandler, defers = {}; + + this.$get = ['$document', '$templateCache', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller', + function ($document, $templateCache, $compile, $q, $http, $rootScope, $timeout, $window, $controller) { + var $body = $document.find('body'); + if (forceBodyReload) { + $rootScope.$on('$locationChangeSuccess', function () { + $body = $document.find('body'); + }); + } + + var privateMethods = { + onDocumentKeydown: function (event) { + if (event.keyCode === 27) { + publicMethods.close('$escape'); + } + }, + + setBodyPadding: function (width) { + var originalBodyPadding = parseInt(($body.css('padding-right') || 0), 10); + $body.css('padding-right', (originalBodyPadding + width) + 'px'); + $body.data('ng-dialog-original-padding', originalBodyPadding); + }, + + resetBodyPadding: function () { + var originalBodyPadding = $body.data('ng-dialog-original-padding'); + if (originalBodyPadding) { + $body.css('padding-right', originalBodyPadding + 'px'); + } else { + $body.css('padding-right', ''); + } + }, + + closeDialog: function ($dialog, value) { + var id = $dialog.attr('id'); + if (typeof window.Hammer !== 'undefined') { + window.Hammer($dialog[0]).off('tap', closeByDocumentHandler); + } else { + $dialog.unbind('click'); + } + + if (dialogsCount === 1) { + $body.unbind('keydown'); + } + + if (!$dialog.hasClass("ngdialog-closing")){ + dialogsCount -= 1; + } + + if (animationEndSupport) { + $dialog.unbind(animationEndEvent).bind(animationEndEvent, function () { + $dialog.scope().$destroy(); + $dialog.remove(); + if (dialogsCount === 0) { + $body.removeClass('ngdialog-open'); + privateMethods.resetBodyPadding(); + } + $rootScope.$broadcast('ngDialog.closed', $dialog); + }).addClass('ngdialog-closing'); + } else { + $dialog.scope().$destroy(); + $dialog.remove(); + if (dialogsCount === 0) { + $body.removeClass('ngdialog-open'); + privateMethods.resetBodyPadding(); + } + $rootScope.$broadcast('ngDialog.closed', $dialog); + } + if (defers[id]) { + defers[id].resolve({ + id: id, + value: value, + $dialog: $dialog, + remainingDialogs: dialogsCount + }); + delete defers[id]; + } + } + }; + + var publicMethods = { + + /* + * @param {Object} options: + * - template {String} - id of ng-template, url for partial, plain string (if enabled) + * - plain {Boolean} - enable plain string templates, default false + * - scope {Object} + * - controller {String} + * - className {String} - dialog theme class + * - showClose {Boolean} - show close button, default true + * - closeByEscape {Boolean} - default true + * - closeByDocument {Boolean} - default true + * + * @return {Object} dialog + */ + open: function (opts) { + var self = this; + var options = angular.copy(defaults); + + opts = opts || {}; + angular.extend(options, opts); + + globalID += 1; + + self.latestID = 'ngdialog' + globalID; + + var defer; + defers[self.latestID] = defer = $q.defer(); + + var scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new(); + var $dialog, $dialogParent; + + $q.when(loadTemplate(options.template)).then(function (template) { + template = angular.isString(template) ? + template : + template.data && angular.isString(template.data) ? + template.data : + ''; + + $templateCache.put(options.template, template); + + if (options.showClose) { + template += '<div class="ngdialog-close"></div>'; + } + + self.$result = $dialog = $el('<div id="ngdialog' + globalID + '" class="ngdialog"></div>'); + $dialog.html('<div class="ngdialog-overlay"></div><div class="ngdialog-content">' + template + '</div>'); + + if (options.data && angular.isString(options.data)) { + var firstLetter = options.data.replace(/^\s*/, '')[0]; + scope.ngDialogData = (firstLetter === '{' || firstLetter === '[') ? angular.fromJson(options.data) : options.data; + } else if (options.data && angular.isObject(options.data)) { + scope.ngDialogData = angular.fromJson(angular.toJson(options.data)); + } + + if (options.controller && (angular.isString(options.controller) || angular.isArray(options.controller) || angular.isFunction(options.controller))) { + var controllerInstance = $controller(options.controller, { + $scope: scope, + $element: $dialog + }); + $dialog.data('$ngDialogControllerController', controllerInstance); + } + + if (options.className) { + $dialog.addClass(options.className); + } + + if (options.appendTo && angular.isString(options.appendTo)) { + $dialogParent = angular.element(document.querySelector(options.appendTo)); + } else { + $dialogParent = $body; + } + + scope.closeThisDialog = function (value) { + privateMethods.closeDialog($dialog, value); + }; + + $timeout(function () { + $compile($dialog)(scope); + + var widthDiffs = $window.innerWidth - $body.prop('clientWidth'); + $body.addClass('ngdialog-open'); + var scrollBarWidth = widthDiffs - ($window.innerWidth - $body.prop('clientWidth')); + if (scrollBarWidth > 0) { + privateMethods.setBodyPadding(scrollBarWidth); + } + $dialogParent.append($dialog); + $rootScope.$broadcast('ngDialog.opened', $dialog); + }); + + if (options.closeByEscape) { + $body.bind('keydown', privateMethods.onDocumentKeydown); + } + + closeByDocumentHandler = function (event) { + var isOverlay = options.closeByDocument ? $el(event.target).hasClass('ngdialog-overlay') : false; + var isCloseBtn = $el(event.target).hasClass('ngdialog-close'); + + if (isOverlay || isCloseBtn) { + publicMethods.close($dialog.attr('id'), isCloseBtn ? '$closeButton' : '$document'); + } + }; + + if (typeof window.Hammer !== 'undefined') { + window.Hammer($dialog[0]).on('tap', closeByDocumentHandler); + } else { + $dialog.bind('click', closeByDocumentHandler); + } + + dialogsCount += 1; + + return publicMethods; + }); + + return { + id: 'ngdialog' + globalID, + closePromise: defer.promise, + close: function(value) { + privateMethods.closeDialog($dialog, value); + } + }; + + function loadTemplate (tmpl) { + if (!tmpl) { + return 'Empty template'; + } + + if (angular.isString(tmpl) && options.plain) { + return tmpl; + } + + return $templateCache.get(tmpl) || $http.get(tmpl, { cache: true }); + } + }, + + /* + * @param {Object} options: + * - template {String} - id of ng-template, url for partial, plain string (if enabled) + * - plain {Boolean} - enable plain string templates, default false + * - scope {Object} + * - controller {String} + * - className {String} - dialog theme class + * - showClose {Boolean} - show close button, default true + * - closeByEscape {Boolean} - default false + * - closeByDocument {Boolean} - default false + * + * @return {Object} dialog + */ + openConfirm: function (opts) { + var defer = $q.defer(); + + var options = { + closeByEscape: false, + closeByDocument: false + }; + angular.extend(options, opts); + + options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new(); + options.scope.confirm = function (value) { + defer.resolve(value); + openResult.close(value); + }; + + var openResult = publicMethods.open(options); + openResult.closePromise.then(function (data) { + if (data) { + return defer.reject(data.value); + } + return defer.reject(); + }); + + return defer.promise; + }, + + /* + * @param {String} id + * @return {Object} dialog + */ + close: function (id, value) { + var $dialog = $el(document.getElementById(id)); + + if ($dialog.length) { + privateMethods.closeDialog($dialog, value); + } else { + publicMethods.closeAll(value); + } + + return publicMethods; + }, + + closeAll: function (value) { + var $all = document.querySelectorAll('.ngdialog'); + + angular.forEach($all, function (dialog) { + privateMethods.closeDialog($el(dialog), value); + }); + } + }; + + return publicMethods; + }]; + }); + + module.directive('ngDialog', ['ngDialog', function (ngDialog) { + return { + restrict: 'A', + scope : { + ngDialogScope : '=' + }, + link: function (scope, elem, attrs) { + elem.on('click', function (e) { + e.preventDefault(); + + var ngDialogScope = angular.isDefined(scope.ngDialogScope) ? scope.ngDialogScope : 'noScope'; + angular.isDefined(attrs.ngDialogClosePrevious) && ngDialog.close(attrs.ngDialogClosePrevious); + + ngDialog.open({ + template: attrs.ngDialog, + className: attrs.ngDialogClass, + controller: attrs.ngDialogController, + scope: ngDialogScope , + data: attrs.ngDialogData, + showClose: attrs.ngDialogShowClose === 'false' ? false : true, + closeByDocument: attrs.ngDialogCloseByDocument === 'false' ? false : true, + closeByEscape: attrs.ngDialogCloseByEscape === 'false' ? false : true + }); + }); + } + }; + }]); + +})(window, window.angular); diff --git a/libs/angularjs/ngDialog/js/ngDialog.min.js b/libs/angularjs/ngDialog/js/ngDialog.min.js new file mode 100644 index 0000000000000000000000000000000000000000..1849205be8aa9b06d089fecf840df8a8694813a6 --- /dev/null +++ b/libs/angularjs/ngDialog/js/ngDialog.min.js @@ -0,0 +1,2 @@ +/*! ng-dialog - v0.2.14 (https://github.com/likeastore/ngDialog) */ +!function(a,b){"use strict";var c=b.module("ngDialog",[]),d=b.element,e=b.isDefined,f=(document.body||document.documentElement).style,g=e(f.animation)||e(f.WebkitAnimation)||e(f.MozAnimation)||e(f.MsAnimation)||e(f.OAnimation),h="animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend",i=!1;c.provider("ngDialog",function(){var c=this.defaults={className:"ngdialog-theme-default",plain:!1,showClose:!0,closeByDocument:!0,closeByEscape:!0,appendTo:!1};this.setForceBodyReload=function(a){i=a||!1},this.setDefaults=function(a){b.extend(c,a)};var e,f=0,j=0,k={};this.$get=["$document","$templateCache","$compile","$q","$http","$rootScope","$timeout","$window","$controller",function(l,m,n,o,p,q,r,s,t){var u=l.find("body");i&&q.$on("$locationChangeSuccess",function(){u=l.find("body")});var v={onDocumentKeydown:function(a){27===a.keyCode&&w.close("$escape")},setBodyPadding:function(a){var b=parseInt(u.css("padding-right")||0,10);u.css("padding-right",b+a+"px"),u.data("ng-dialog-original-padding",b)},resetBodyPadding:function(){var a=u.data("ng-dialog-original-padding");a?u.css("padding-right",a+"px"):u.css("padding-right","")},closeDialog:function(b,c){var d=b.attr("id");"undefined"!=typeof a.Hammer?a.Hammer(b[0]).off("tap",e):b.unbind("click"),1===j&&u.unbind("keydown"),b.hasClass("ngdialog-closing")||(j-=1),g?b.unbind(h).bind(h,function(){b.scope().$destroy(),b.remove(),0===j&&(u.removeClass("ngdialog-open"),v.resetBodyPadding()),q.$broadcast("ngDialog.closed",b)}).addClass("ngdialog-closing"):(b.scope().$destroy(),b.remove(),0===j&&(u.removeClass("ngdialog-open"),v.resetBodyPadding()),q.$broadcast("ngDialog.closed",b)),k[d]&&(k[d].resolve({id:d,value:c,$dialog:b,remainingDialogs:j}),delete k[d])}},w={open:function(g){function h(a){return a?b.isString(a)&&l.plain?a:m.get(a)||p.get(a,{cache:!0}):"Empty template"}var i=this,l=b.copy(c);g=g||{},b.extend(l,g),f+=1,i.latestID="ngdialog"+f;var x;k[i.latestID]=x=o.defer();var y,z,A=b.isObject(l.scope)?l.scope.$new():q.$new();return o.when(h(l.template)).then(function(c){if(c=b.isString(c)?c:c.data&&b.isString(c.data)?c.data:"",m.put(l.template,c),l.showClose&&(c+='<div class="ngdialog-close"></div>'),i.$result=y=d('<div id="ngdialog'+f+'" class="ngdialog"></div>'),y.html('<div class="ngdialog-overlay"></div><div class="ngdialog-content">'+c+"</div>"),l.data&&b.isString(l.data)){var g=l.data.replace(/^\s*/,"")[0];A.ngDialogData="{"===g||"["===g?b.fromJson(l.data):l.data}else l.data&&b.isObject(l.data)&&(A.ngDialogData=b.fromJson(b.toJson(l.data)));if(l.controller&&(b.isString(l.controller)||b.isArray(l.controller)||b.isFunction(l.controller))){var h=t(l.controller,{$scope:A,$element:y});y.data("$ngDialogControllerController",h)}return l.className&&y.addClass(l.className),z=l.appendTo&&b.isString(l.appendTo)?b.element(document.querySelector(l.appendTo)):u,A.closeThisDialog=function(a){v.closeDialog(y,a)},r(function(){n(y)(A);var a=s.innerWidth-u.prop("clientWidth");u.addClass("ngdialog-open");var b=a-(s.innerWidth-u.prop("clientWidth"));b>0&&v.setBodyPadding(b),z.append(y),q.$broadcast("ngDialog.opened",y)}),l.closeByEscape&&u.bind("keydown",v.onDocumentKeydown),e=function(a){var b=l.closeByDocument?d(a.target).hasClass("ngdialog-overlay"):!1,c=d(a.target).hasClass("ngdialog-close");(b||c)&&w.close(y.attr("id"),c?"$closeButton":"$document")},"undefined"!=typeof a.Hammer?a.Hammer(y[0]).on("tap",e):y.bind("click",e),j+=1,w}),{id:"ngdialog"+f,closePromise:x.promise,close:function(a){v.closeDialog(y,a)}}},openConfirm:function(a){var c=o.defer(),d={closeByEscape:!1,closeByDocument:!1};b.extend(d,a),d.scope=b.isObject(d.scope)?d.scope.$new():q.$new(),d.scope.confirm=function(a){c.resolve(a),e.close(a)};var e=w.open(d);return e.closePromise.then(function(a){return a?c.reject(a.value):c.reject()}),c.promise},close:function(a,b){var c=d(document.getElementById(a));return c.length?v.closeDialog(c,b):w.closeAll(b),w},closeAll:function(a){var c=document.querySelectorAll(".ngdialog");b.forEach(c,function(b){v.closeDialog(d(b),a)})}};return w}]}),c.directive("ngDialog",["ngDialog",function(a){return{restrict:"A",scope:{ngDialogScope:"="},link:function(c,d,e){d.on("click",function(d){d.preventDefault();var f=b.isDefined(c.ngDialogScope)?c.ngDialogScope:"noScope";b.isDefined(e.ngDialogClosePrevious)&&a.close(e.ngDialogClosePrevious),a.open({template:e.ngDialog,className:e.ngDialogClass,controller:e.ngDialogController,scope:f,data:e.ngDialogData,showClose:"false"===e.ngDialogShowClose?!1:!0,closeByDocument:"false"===e.ngDialogCloseByDocument?!1:!0,closeByEscape:"false"===e.ngDialogCloseByEscape?!1:!0})})}}}])}(window,window.angular); \ No newline at end of file diff --git a/libs/angularjs/ngDialog/package.json b/libs/angularjs/ngDialog/package.json new file mode 100644 index 0000000000000000000000000000000000000000..cd2140bb0e6474b2eb99e51c5404133ad7f6281a --- /dev/null +++ b/libs/angularjs/ngDialog/package.json @@ -0,0 +1,40 @@ +{ + "name": "ng-dialog", + "version": "0.2.14", + "homepage": "https://github.com/likeastore/ngDialog", + "description": "Modal dialogs and popups provider for Angular.js applications", + "main": "./js/ngDialog.js", + "keywords": [ + "angular.js", + "modals", + "popups", + "dialog", + "ng", + "provider", + "factory", + "directive" + ], + "author": { + "name": "Dmitri Voronianski", + "email": "dmitri.voronianski@gmail.com", + "web": "http://pixelhunter.me", + "twitter": "voronianski" + }, + "bugs": "https://github.com/likeastore/ngDialog/issues", + "repository": { + "type": "git", + "url": "https://github.com/likeastore/ngDialog" + }, + "readmeFilename": "README.md", + "license": "MIT", + "devDependencies": { + "grunt": "~0.4.2", + "grunt-contrib-cssmin": "^0.9.0", + "grunt-contrib-jshint": "~0.7.2", + "grunt-contrib-uglify": "~0.2.7", + "grunt-myth": "~0.1.0", + "myth": "~0.1.6", + "network-address": "0.0.4", + "strata": "~0.20.1" + } +} diff --git a/misc/others/phpstorm-codestyles/Piwik_codestyle.xml b/misc/phpstorm-codestyles/Piwik_codestyle.xml similarity index 100% rename from misc/others/phpstorm-codestyles/Piwik_codestyle.xml rename to misc/phpstorm-codestyles/Piwik_codestyle.xml diff --git a/misc/others/phpstorm-codestyles/README.md b/misc/phpstorm-codestyles/README.md similarity index 71% rename from misc/others/phpstorm-codestyles/README.md rename to misc/phpstorm-codestyles/README.md index ce4f8e94bbdfa8a4d72ecc8d4561cf2771036e02..0dc88684404cd1ee9ae1b8d843c9f03b9a389f11 100644 --- a/misc/others/phpstorm-codestyles/README.md +++ b/misc/phpstorm-codestyles/README.md @@ -5,13 +5,13 @@ Piwik uses PSR coding standard for php source code. We use a slightly customized Steps: * Use latest Phpstorm - * Copy this Piwik_codestyle.xml file in your ~/.WebIde60/config/codestyles/ + * Copy this Piwik_codestyle.xml file in your `~/.WebIde80/config/codestyles/` * If you use Windows or Mac see which path to copy at: http://intellij-support.jetbrains.com/entries/23358108 * To automatically link to the file in Piwik: - `$ ln -s ~/dev/piwik-master/misc/others/phpstorm-codestyles/Piwik_codestyle.xml ~/.WebIde70/config/codestyles/Piwik_codestyle.xml` + `$ ln -s ~/dev/piwik-master/misc/phpstorm-codestyles/Piwik_codestyle.xml ~/.WebIde80/config/codestyles/Piwik_codestyle.xml` - * Restart PhpStorm. - * Select this coding in Settings>Code style. + * Restart PhpStorm + * Select this coding in Settings > Code style. Phpstorm can also be configured to apply the style automatically before commit. diff --git a/plugins/API/API.php b/plugins/API/API.php index fd22791a2c57572f2361b2c7dc161d806a7ced3b..7060d6af1ee46ea2ad1627d5e7dfd0acff510f13 100644 --- a/plugins/API/API.php +++ b/plugins/API/API.php @@ -515,6 +515,11 @@ class API extends \Piwik\Plugin\API throw new \Exception("Requested segment not found."); } + // if segment has suggested values callback then return result from it instead + if (isset($segmentFound['suggestedValuesCallback'])) { + return call_user_func($segmentFound['suggestedValuesCallback'], $idSite, $maxSuggestionsToReturn); + } + // if period=range is disabled, do not proceed if(!Period\Factory::isPeriodEnabledForAPI('range')) { return array(); diff --git a/plugins/Annotations/stylesheets/annotations.less b/plugins/Annotations/stylesheets/annotations.less index 9f06273e77af3581ceadc25966d5b6700a562965..c92f96fe49775b1b801e6c740ddf86abd546c9ef 100755 --- a/plugins/Annotations/stylesheets/annotations.less +++ b/plugins/Annotations/stylesheets/annotations.less @@ -13,10 +13,6 @@ } #content, .ui-dialog { - .evolution-annotations { - margin-top: -5px; - margin-bottom: -5px; - } .evolution-annotations > span { top: -1px; position: absolute; @@ -26,6 +22,11 @@ } } +.evolution-annotations { + margin-top: -5px; + margin-bottom: -5px; +} + .ui-dialog .evolution-annotations > span { top: 25px; } diff --git a/plugins/CoreAdminHome/Controller.php b/plugins/CoreAdminHome/Controller.php index 6886b0d336e64e37cd3bcc4887ab4cc19709bc35..6b672d07e8bc0ecc4c14856bbf0756b8b3848818 100644 --- a/plugins/CoreAdminHome/Controller.php +++ b/plugins/CoreAdminHome/Controller.php @@ -263,6 +263,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin // an error when setBasicVariablesAdminView is called, and MenuTop is requested (the idSite query // parameter is required) $view = new View("@CoreAdminHome/optOut"); + $view->setXFrameOptions('allow'); $view->trackVisits = $trackVisits; $view->nonce = Nonce::getNonce('Piwik_OptOut', 3600); $view->language = $lang; diff --git a/plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js b/plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js index b8a48de1d9010bdf1f8156e5de28b3980dd0e553..93010a3252409d89c8c85a22fc16c8a19071aa0d 100644 --- a/plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js +++ b/plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js @@ -161,7 +161,8 @@ pageCustomVariables: getCustomVariables('javascript-tracking-page-cv'), customCampaignNameQueryParam: null, customCampaignKeywordParam: null, - doNotTrack: $('#javascript-tracking-do-not-track').is(':checked') ? 1 : 0 + doNotTrack: $('#javascript-tracking-do-not-track').is(':checked') ? 1 : 0, + disableCookies: $('#javascript-tracking-disable-cookies').is(':checked') ? 1 : 0 }; if ($('#custom-campaign-query-params-check').is(':checked')) { diff --git a/plugins/CoreAdminHome/lang/en.json b/plugins/CoreAdminHome/lang/en.json index 43a84464750c81166ce6a19be0adf7a047f45a68..7c1d9f3f9239760ee5cc0a6b533fc88a49f76d5f 100644 --- a/plugins/CoreAdminHome/lang/en.json +++ b/plugins/CoreAdminHome/lang/en.json @@ -26,6 +26,8 @@ "JSTracking_CodeNote": "Make sure this code is on every page of your website before the %1$s tag.", "JSTracking_CustomCampaignQueryParam": "Use custom query parameter names for the campaign name & keyword", "JSTracking_CustomCampaignQueryParamDesc": "Note: %1$sPiwik will automatically detect Google Analytics parameters.%2$s", + "JSTracking_DisableCookies": "Disable all tracking cookies", + "JSTracking_DisableCookiesDesc": "Disables all first party cookies. Existing Piwik cookies for this website will be deleted on the next page view.", "JSTracking_EnableDoNotTrack": "Enable client side DoNotTrack detection", "JSTracking_EnableDoNotTrack_AlreadyEnabled": "Note: Server side DoNotTrack support has been enabled, so this option will have no effect.", "JSTracking_EnableDoNotTrackDesc": "So tracking requests will not be sent if visitors do not wish to be tracked.", @@ -83,4 +85,4 @@ "YouMayOptOut": "You may choose not to have a unique web analytics cookie identification number assigned to your computer to avoid the aggregation and analysis of data collected on this website.", "YouMayOptOutBis": "To make that choice, please click below to receive an opt-out cookie." } -} \ No newline at end of file +} diff --git a/plugins/CoreAdminHome/templates/trackingCodeGenerator.twig b/plugins/CoreAdminHome/templates/trackingCodeGenerator.twig index 2666ec62ac7e3927aa6e71dd6b9011ebdbcdb9f7..b3bfbf8d6b4aaafce7bdb7e8da3d322d8b032a7b 100644 --- a/plugins/CoreAdminHome/templates/trackingCodeGenerator.twig +++ b/plugins/CoreAdminHome/templates/trackingCodeGenerator.twig @@ -150,6 +150,16 @@ </div> </div> + {# disable all cookies options #} + <div class="tracking-option-section"> + <input type="checkbox" id="javascript-tracking-disable-cookies"/> + <label for="javascript-tracking-disable-cookies">{{ 'CoreAdminHome_JSTracking_DisableCookies'|translate }}</label> + + <div class="small-form-description"> + {{ 'CoreAdminHome_JSTracking_DisableCookiesDesc'|translate }} + </div> + </div> + {# custom campaign name/keyword query params #} <div class="tracking-option-section"> <input class="section-toggler-link" type="checkbox" id="custom-campaign-query-params-check" diff --git a/plugins/CoreConsole/Commands/TestsRunUI.php b/plugins/CoreConsole/Commands/TestsRunUI.php index 4cce1e6446d2e2ccd59acdcd6d98ab300b1784ad..c3859579edeaed0f479d9d10c4e4391b4aaf0205 100644 --- a/plugins/CoreConsole/Commands/TestsRunUI.php +++ b/plugins/CoreConsole/Commands/TestsRunUI.php @@ -7,6 +7,7 @@ */ namespace Piwik\Plugins\CoreConsole\Commands; +use Piwik\AssetManager; use Piwik\Plugin\ConsoleCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -26,6 +27,7 @@ class TestsRunUI extends ConsoleCommand $this->addOption('drop', null, InputOption::VALUE_NONE, "Drop the existing database and re-setup a persisted fixture."); $this->addOption('assume-artifacts', null, InputOption::VALUE_NONE, "Assume the diffviewer and processed screenshots will be stored on the builds artifacts server. For use with travis build."); $this->addOption('plugin', null, InputOption::VALUE_REQUIRED, "Execute all tests for a plugin."); + $this->addOption('skip-delete-assets', null, InputOption::VALUE_NONE, "Skip deleting of merged assets (will speed up a test run, but not by a lot)."); } protected function execute(InputInterface $input, OutputInterface $output) @@ -37,6 +39,11 @@ class TestsRunUI extends ConsoleCommand $drop = $input->getOption('drop'); $assumeArtifacts = $input->getOption('assume-artifacts'); $plugin = $input->getOption('plugin'); + $skipDeleteAssets = $input->getOption('skip-delete-assets'); + + if (!$skipDeleteAssets) { + AssetManager::getInstance()->removeMergedAssets(); + } $options = array(); if ($persistFixtureData) { @@ -73,4 +80,4 @@ class TestsRunUI extends ConsoleCommand passthru($cmd); } -} \ No newline at end of file +} diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php index f45695e650e65fdb98638b98f5515829e7896988..e9b4781259d505d058c00f6b312c38cda719c377 100644 --- a/plugins/CoreHome/CoreHome.php +++ b/plugins/CoreHome/CoreHome.php @@ -49,6 +49,8 @@ class CoreHome extends \Piwik\Plugin $stylesheets[] = "libs/jquery/themes/base/jquery-ui.css"; $stylesheets[] = "libs/jquery/stylesheets/jquery.jscrollpane.css"; $stylesheets[] = "libs/jquery/stylesheets/scroll.less"; + $stylesheets[] = "libs/angularjs/ngDialog/css/ngDialog.min.css"; + $stylesheets[] = "libs/angularjs/ngDialog/css/ngDialog-theme-default.min.css"; $stylesheets[] = "plugins/Morpheus/stylesheets/base.less"; $stylesheets[] = "plugins/Morpheus/stylesheets/theme.less"; $stylesheets[] = "plugins/CoreHome/stylesheets/coreHome.less"; @@ -80,10 +82,11 @@ class CoreHome extends \Piwik\Plugin $jsFiles[] = "libs/jquery/mwheelIntent.js"; $jsFiles[] = "libs/javascript/sprintf.js"; $jsFiles[] = "libs/mousetrap/mousetrap.min.js"; - $jsFiles[] = "libs/angularjs/angular.js"; + $jsFiles[] = "libs/angularjs/angular.min.js"; $jsFiles[] = "libs/angularjs/angular-sanitize.min.js"; $jsFiles[] = "libs/angularjs/angular-animate.min.js"; $jsFiles[] = "libs/angularjs/angular-cookies.min.js"; + $jsFiles[] = "libs/angularjs/ngDialog/js/ngDialog.min.js"; $jsFiles[] = "plugins/Morpheus/javascripts/piwikHelper.js"; $jsFiles[] = "plugins/Morpheus/javascripts/ajaxHelper.js"; $jsFiles[] = "plugins/Morpheus/javascripts/jquery.icheck.min.js"; @@ -139,6 +142,10 @@ class CoreHome extends \Piwik\Plugin $jsFiles[] = "plugins/CoreHome/angularjs/menudropdown/menudropdown-directive.js"; $jsFiles[] = "plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js"; + + $jsFiles[] = "plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-directive.js"; + $jsFiles[] = "plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-controller.js"; + $jsFiles[] = "plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-urllistener-service.js"; } public function getClientSideTranslationKeys(&$translationKeys) diff --git a/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-controller.js b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-controller.js new file mode 100644 index 0000000000000000000000000000000000000000..5a99d7baa88112125a2a4e5fe1ba14d6becc7721 --- /dev/null +++ b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-controller.js @@ -0,0 +1,62 @@ +/*! + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/** + * Controller for the piwikDialogToggler directive. Adds a couple methods to the + * scope allowing elements to open and close dialogs. + */ +angular.module('piwikApp').controller('DialogTogglerController', function ($scope, piwik, ngDialog, piwikDialogtogglerUrllistener) { + /** + * Open a new dialog window using ngDialog. + * + * @param {object|string} contentsInfo If an object, it is assumed to be ngDialog open(...) config and is + * passed to ngDialog.open unaltered. + * If a string that beings with '#', we assume it is an ID of an element + * with the dialog contents. (Note: ngDialog doesn't appear to support arbitrary + * selectors). + * If a string that ends with .html, we assume it is a link to a an angular + * template. + * Otherwise we assume it is a raw angular + * @return {object} Returns the result of ngDialog.open. Can be used to close the dialog or listen for + * when the dialog is closed. + */ + $scope.open = function (contentsInfo) { + var ngDialogInfo; + if (typeof(contentsInfo) == 'object') { // is info to pass directly to ngDialog + ngDialogInfo = contentsInfo; + } else if (contentsInfo.substr(0, 1) == '#') { // is ID of an element + ngDialogInfo = {template: contentsInfo.substr(1), className: 'ngdialog-theme-default'}; + } else if (contentsInfo.substr(-4) == '.html') { // is a link to an .html file + ngDialogInfo = {template: contentsInfo, className: 'ngdialog-theme-default'}; + } else { // is a raw HTML string + ngDialogInfo = {template: contentsInfo, plain: true, className: 'ngdialog-theme-default'}; + } + + return ngDialog.open(ngDialogInfo); + }; + + /** + * Opens a persisted dialog. Persisted dialogs are dialogs that will be launched on reload + * of the current URL. They are accomplished by modifying the URL and adding a 'popover' + * query parameter. + * + * @param {string} directive The denormalized name of an angularjs directive. An element with + * this directive will be the contents of the dialog. + * @param {object} attributes Key value mapping of the HTML attributes to add to the dialog's + * contents element. + */ + $scope.persist = function (directive, attributes) { + piwikDialogtogglerUrllistener.propagatePersistedDialog(directive, attributes); + }; + + /** + * Closes the currently open dialog window. + */ + $scope.close = function () { + ngDialog.close(); + }; +}); \ No newline at end of file diff --git a/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-directive.js b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-directive.js new file mode 100644 index 0000000000000000000000000000000000000000..4b7859fe1f5c80b3575b22c3eedb1fd0b0d51b22 --- /dev/null +++ b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-directive.js @@ -0,0 +1,26 @@ +/*! + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/** + * Directive for an element (such as a link) that creates and/or closes dialogs. + * + * Usage: + * <a piwik-dialogtoggler href="#" ng-click="open(...)" /> + * + * or: + * + * <div piwik-dialogtoggler> + * <a href="#" ng-click="open(...)">Open</a> + * <a href="#" ng-click="close()">Close</a> + * </div> + */ +angular.module('piwikApp').directive('piwikDialogtoggler', function () { + return { + restrict: 'A', + controller: 'DialogTogglerController' + }; +}); \ No newline at end of file diff --git a/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-urllistener-service.js b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-urllistener-service.js new file mode 100644 index 0000000000000000000000000000000000000000..5da8820f422d422cb6326b8df575e8fab8f96512 --- /dev/null +++ b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-urllistener-service.js @@ -0,0 +1,84 @@ +/*! + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/** + * AngularJS service that handles the popover query parameter for Piwik's angular code. + * + * If the popover parameter's first part is the name of an existing AngularJS directive, + * a dialog is created using ngDialog with the contents being an element with that directive. + * The other parts of the parameter are treated as attributes for the element, eg, + * `"mydirective:myparam=val:myotherparam=val2"`. + * + * It should not be necessary to use this service directly, instead the piwik-dialogtoggler + * directive should be used. + * + * TODO: popover as a query parameter refers less to dialogs and more to any popup window + * (ie, not necessarily modal). should replace it w/ 'dialog' or maybe 'modal'. + */ +angular.module('piwikApp').factory('piwikDialogtogglerUrllistener', function ($rootScope, $location, $injector, $rootElement, ngDialog) { + var service = {}, + dialogQueryParamName = 'popover'; + + function getHtmlFromDialogQueryParam(paramValue) { + var info = paramValue.split(':'), + directiveName = info.shift(), + dialogContent = ''; + + dialogContent += '<div ' + directiveName; + angular.forEach(info, function (argumentAssignment) { + var pair = argumentAssignment.split('='), + key = pair[0], + value = pair[1]; + dialogContent += ' ' + key + '="' + decodeURIComponent(value) + '"'; + }); + dialogContent += '/>'; + + return dialogContent; + } + + function directiveExists(directiveAttributeString) { + // NOTE: directiveNormalize is not exposed by angularjs and the devs don't seem to want to expose it: + // https://github.com/angular/angular.js/issues/7955 + // so logic is duplicated here. + var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i, + directiveName = angular.element.camelCase(directiveAttributeString.replace(PREFIX_REGEXP, '')); + + return $injector.has(directiveName + 'Directive'); + } + + service.checkUrlForDialog = function () { + var dialogParamValue = $location.search()[dialogQueryParamName]; + if (dialogParamValue + && directiveExists(dialogParamValue) + ) { + var dialog = ngDialog.open({ + template: getHtmlFromDialogQueryParam(dialogParamValue), + plain: true, + className: 'ngdialog-theme-default' + }); + + dialog.closePromise.then(function () { + $location.search(dialogQueryParamName, null); + }); + } + }; + + service.propagatePersistedDialog = function (directive, attributes) { + var paramValue = directive; + angular.forEach(attributes, function (value, name) { + paramValue += ':' + name + '=' + encodeURIComponent(value); + }); + + $location.search(dialogQueryParamName, paramValue); + }; + + $rootScope.$on('$locationChangeSuccess', function () { + service.checkUrlForDialog(); + }); + + return service; +}); \ No newline at end of file diff --git a/plugins/CoreHome/angularjs/piwikApp.js b/plugins/CoreHome/angularjs/piwikApp.js index b2942a10026206e2988fad5bc2d4bd3786e1bead..3aafe9b87cf315152c03d78243e7f895550ac319 100644 --- a/plugins/CoreHome/angularjs/piwikApp.js +++ b/plugins/CoreHome/angularjs/piwikApp.js @@ -9,6 +9,7 @@ angular.module('piwikApp', [ 'ngSanitize', 'ngAnimate', 'ngCookies', + 'ngDialog', 'piwikApp.config', 'piwikApp.service', 'piwikApp.directive', diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector-directive.js b/plugins/CoreHome/angularjs/siteselector/siteselector-directive.js index a5ebd0f06182cfd2616cf96ec9f91f3eedd362eb..2f76b86d55a52881821a35ae810087b4574a2f36 100644 --- a/plugins/CoreHome/angularjs/siteselector/siteselector-directive.js +++ b/plugins/CoreHome/angularjs/siteselector/siteselector-directive.js @@ -45,18 +45,24 @@ angular.module('piwikApp').directive('piwikSiteselector', function($document, pi allSitesText: '@', allSitesLocation: '@' }, + require: "?ngModel", templateUrl: 'plugins/CoreHome/angularjs/siteselector/siteselector.html?cb=' + piwik.cacheBuster, controller: 'SiteSelectorController', compile: function (element, attrs) { for (var index in defaults) { - if (!attrs[index]) { attrs[index] = defaults[index]; } + if (attrs[index] === undefined) { + attrs[index] = defaults[index]; + } } - return function (scope, element, attrs) { + return function (scope, element, attrs, ngModel) { + if (ngModel) { + scope.selectedSite.id = ngModel.$viewValue; + } // selectedSite.id|.name + model is hard-coded but actually the directive should not know about this - scope.selectedSite.id = attrs.siteid; + scope.selectedSite.id = scope.selectedSite.id || attrs.siteid; scope.selectedSite.name = attrs.sitename; if (!attrs.siteid || !attrs.sitename) { @@ -67,9 +73,17 @@ angular.module('piwikApp').directive('piwikSiteselector', function($document, pi if (newValue != oldValue) { element.attr('siteid', newValue); element.trigger('change', scope.selectedSite); + + if (ngModel) { + ngModel.$setViewValue(newValue); + } } }); + scope.$watch('view.showSitesList', function (newValue) { + element.toggleClass('expanded', !! newValue); + }); + /** use observe to monitor attribute changes attrs.$observe('maxsitenamewidth', function(val) { // for instance trigger a function or whatever diff --git a/plugins/CoreHome/stylesheets/dataTable/_dataTable.less b/plugins/CoreHome/stylesheets/dataTable/_dataTable.less index 1cc9bf18721f130cce9d4929bedb1188b6a04899..dfc76620d93d14f4b56a5428e90bb44e2618cc2f 100644 --- a/plugins/CoreHome/stylesheets/dataTable/_dataTable.less +++ b/plugins/CoreHome/stylesheets/dataTable/_dataTable.less @@ -170,6 +170,11 @@ table.dataTable img { width: 450px; } +div.dataTable, div.dataTable > .dataTableWrapper { + margin-bottom: 9px; // same height as expand/contract button (so datatable height will encompass the + // expand/contract button) +} + .subDataTable > .dataTableWrapper { width: 95%; } @@ -285,103 +290,147 @@ table.dataTable img { padding-bottom: 4px; } -#content { - - .dataTableFeatures { - &.expanded { - .dataTableFooterIcons { - display: block; - } - - .expandDataTableFooterDrawer { - display: none; - } +.dataTableFeatures { + &.expanded { + .dataTableFooterIcons { + display: block; } - &.hasEvolution { - .dataTableFooterIcons { - margin-top: 17px; - } - .expandDataTableFooterDrawer { - margin-top: 20px; - } + .expandDataTableFooterDrawer { + display: none; } + } + &.hasEvolution { + .dataTableFooterIcons { + margin-top: 17px; + } .expandDataTableFooterDrawer { - display: block; - margin-top: 5px; + margin-top: 20px; + } + } + + .expandDataTableFooterDrawer { + display: block; + margin-top: 5px; + margin-bottom: -1px; + margin-left: auto; + margin-right: auto; + background-color: @theme-color-background-base; + border: 1px solid @theme-color-background-tinyContrast; + height: 7px; + width: 70px; + -webkit-border-bottom-left-radius: 10px; + -webkit-border-bottom-right-radius: 10px; + -moz-border-radius-bottomleft: 10px; + -moz-border-radius-bottomright: 10px; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; + line-height: 0px; + + img { margin-bottom: 0px; - margin-left: auto; - margin-right: auto; - background-color: #D9D9D9; - height: 7px; - width: 70px; - -webkit-border-top-left-radius: 10px; - -webkit-border-top-right-radius: 10px; - -moz-border-radius-topleft: 10px; - -moz-border-radius-topright: 10px; - border-top-left-radius: 10px; - border-top-right-radius: 10px; line-height: 0px; - - img { - margin-bottom: 0px; - line-height: 0px; - } } } +} - .dataTableFooterIcons { +.dataTableFeatures { + border-bottom: 1px solid @theme-color-background-tinyContrast; +} - display: none; - margin-top: 5px; - height: auto; +.widget .dataTableFeatures { + border-bottom-style: none !important; +} - div { - padding-bottom: 2px; - } +.dataTableFooterIcons { - .foldDataTableFooterDrawer { - display: block; - padding-bottom: 0px; - margin-top: 0px; - margin-left: auto; - margin-right: auto; - background-color: #D9D9D9; - -webkit-border-top-left-radius: 10px; - -webkit-border-top-right-radius: 10px; - -moz-border-radius-topleft: 10px; - -moz-border-radius-topright: 10px; - border-top-left-radius: 10px; - border-top-right-radius: 10px; + display: none; + margin-top: 5px; + height: auto; + + div { + padding-bottom: 2px; + } + + .foldDataTableFooterDrawer { + display: block; + padding-bottom: 0px; + margin-bottom: -1px; + margin-top: 0px; + margin-left: auto; + margin-right: auto; + background-color: @theme-color-background-base; + border: 1px solid @theme-color-background-tinyContrast; + -webkit-border-top-left-radius: 10px; + -webkit-border-top-right-radius: 10px; + -moz-border-radius-topleft: 10px; + -moz-border-radius-topright: 10px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + line-height: 0px; + height: 7px; + width: 70px; + clear: both; + + img { + margin-top: 2px; + margin-bottom: 0px; line-height: 0px; - height: 7px; - width: 70px; - clear: both; - - img { - margin-top: 2px; - margin-bottom: 0px; - line-height: 0px; - } } + } - .controls { - clear: left; - padding: 0px 0px 15px; - text-align: left; - color: #333; - } + .controls { + clear: left; + padding: 0px 0px 15px; + text-align: left; + color: #333; } +} +#dashboard .dataTableFeatures,.widget .dataTableFeatures { + .expandDataTableFooterDrawer { + -webkit-border-top-left-radius: 10px; + -webkit-border-top-right-radius: 10px; + -moz-border-radius-topleft: 10px; + -moz-border-radius-topright: 10px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + + -webkit-border-bottom-left-radius: 0px; + -webkit-border-bottom-right-radius: 0px; + -moz-border-radius-bottomleft: 0px; + -moz-border-radius-bottomright: 0px; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + } } .dataTableFooterIcons .foldDataTableFooterDrawer, .dataTableFeatures .expandDataTableFooterDrawer { - display: none; cursor: pointer; } +.widget .foldDataTableFooterDrawer { + margin-bottom: -9px; +} + +// customizing footer appearance for row evolution graph +.ui-dialog .dataTableVizEvolution { + .expandDataTableFooterDrawer,.foldDataTableFooterDrawer { + display: none !important; + } + + .dataTableFooterIcons { + display: block; + } + + .dataTableFeatures { + border-bottom-style: none !important; + margin-top: 0 !important; + } +} + @-moz-document url-prefix() { #dashboard .dataTableFeatures .expandDataTableFooterDrawer { @@ -395,10 +444,10 @@ table.dataTable img { } .dataTableFooterIcons { - height: 20px; + min-height: 20px; white-space: nowrap; font-size: 10px; - padding: 6px 5px; + padding: 6px 5px 0px; border-top: 1px solid #B6B0A6; } @@ -611,4 +660,4 @@ td.cellSubDataTable .loadingPiwik { cursor: pointer; display: inline; } -} \ No newline at end of file +} diff --git a/plugins/CoreHome/stylesheets/zen-mode.less b/plugins/CoreHome/stylesheets/zen-mode.less index 3aa99376cf217c89c1fdbb5f4d35441f581e8fac..54bbbe9bd128e0a5532bfd1e289f386c1dc44fbc 100644 --- a/plugins/CoreHome/stylesheets/zen-mode.less +++ b/plugins/CoreHome/stylesheets/zen-mode.less @@ -59,21 +59,6 @@ border-top: 0px; } - .foldDataTableFooterDrawer, - .dataTableFeatures .expandDataTableFooterDrawer { - opacity: 0; - -webkit-transition: all 300ms ease; - -moz-transition: all 300ms ease; - -ms-transition: all 300ms ease; - -o-transition: all 300ms ease; - transition: all 300ms ease; - } - - .dataTableFeatures:hover .foldDataTableFooterDrawer, - .dataTableFeatures:hover .expandDataTableFooterDrawer { - opacity: 1 !important; - } - h2:nth-of-type(n+2) { margin-top: 40px; } @@ -108,8 +93,6 @@ } } -#content:not(.admin){ - &> div:not(#dashboard) .dataTableFeatures .expandDataTableFooterDrawer { - margin-bottom: -20px; - } +.dataTableFeatures .expandDataTableFooterDrawer { + margin-bottom: -9px; } diff --git a/plugins/CoreUpdater/templates/layout.twig b/plugins/CoreUpdater/templates/layout.twig index 786efd4bac470c02e55c81ade8f249e8c7194345..913003619af857f09f121bfd8110949e86a618bd 100644 --- a/plugins/CoreUpdater/templates/layout.twig +++ b/plugins/CoreUpdater/templates/layout.twig @@ -24,6 +24,7 @@ <script type="text/javascript" src="libs/angularjs/angular-sanitize.min.js"></script> <script type="text/javascript" src="libs/angularjs/angular-animate.min.js"></script> <script type="text/javascript" src="libs/angularjs/angular-cookies.min.js"></script> + <script type="text/javascript" src="libs/angularjs/ngDialog/js/ngDialog.min.js"></script> <script type="text/javascript" src="plugins/CoreHome/angularjs/common/services/service.js"></script> <script type="text/javascript" src="plugins/CoreHome/angularjs/common/filters/filter.js"></script> <script type="text/javascript" src="plugins/CoreHome/angularjs/common/filters/translate.js"></script> diff --git a/plugins/Installation/templates/layout.twig b/plugins/Installation/templates/layout.twig index db6deaa1d537c2053af0752be8bc6f7259fd798b..012eca5fa40a03f662a87a5833a96a48b5008885 100644 --- a/plugins/Installation/templates/layout.twig +++ b/plugins/Installation/templates/layout.twig @@ -15,6 +15,7 @@ <script type="text/javascript" src="libs/angularjs/angular-sanitize.min.js"></script> <script type="text/javascript" src="libs/angularjs/angular-animate.min.js"></script> <script type="text/javascript" src="libs/angularjs/angular-cookies.min.js"></script> + <script type="text/javascript" src="libs/angularjs/ngDialog/js/ngDialog.min.js"></script> <script type="text/javascript" src="plugins/CoreHome/angularjs/common/services/service.js"></script> <script type="text/javascript" src="plugins/CoreHome/angularjs/common/filters/filter.js"></script> <script type="text/javascript" src="plugins/CoreHome/angularjs/common/filters/translate.js"></script> diff --git a/plugins/Morpheus/stylesheets/theme.less b/plugins/Morpheus/stylesheets/theme.less index 53743c3aa04e0fe09a7d26f343b9024b336ebf92..4b0b3d0020e79e66d0922a0d9300987c133d281c 100644 --- a/plugins/Morpheus/stylesheets/theme.less +++ b/plugins/Morpheus/stylesheets/theme.less @@ -497,14 +497,10 @@ table.dataTable .dataTableRowActions { } .dataTableFooterIcons { - padding: 6px 8px; + padding: 6px 8px 0px; border-top: 1px solid @color-silver-l80; } -#content .dataTableFooterIcons { - padding: 6px 8px 0px; -} - div.sparkline { display: block; width: 100%; diff --git a/plugins/PrivacyManager/Controller.php b/plugins/PrivacyManager/Controller.php index 6fed90a94fd7fef13d8455e143b4aea9b27d75ff..c950d789ed44814adc9b518473b3b6f250058aeb 100644 --- a/plugins/PrivacyManager/Controller.php +++ b/plugins/PrivacyManager/Controller.php @@ -150,6 +150,8 @@ class Controller extends \Piwik\Plugin\ControllerAdmin */ public function executeDataPurge() { + $this->checkDataPurgeAdminSettingsIsEnabled(); + Piwik::checkUserHasSuperUserAccess(); $this->checkTokenInUrl(); diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php index 8eca58f47bf2b057bf9194a51201b9b19a52c4b0..acdaadcb53fabf180cad217eacaeac2d5eb913d7 100644 --- a/plugins/SitesManager/API.php +++ b/plugins/SitesManager/API.php @@ -69,13 +69,13 @@ class API extends \Piwik\Plugin\API * @param bool $customCampaignNameQueryParam * @param bool $customCampaignKeywordParam * @param bool $doNotTrack - * @internal param $ + * @param bool $disableCookies * @return string The Javascript tag ready to be included on the HTML pages */ public function getJavascriptTag($idSite, $piwikUrl = '', $mergeSubdomains = false, $groupPageTitlesByDomain = false, $mergeAliasUrls = false, $visitorCustomVariables = false, $pageCustomVariables = false, $customCampaignNameQueryParam = false, $customCampaignKeywordParam = false, - $doNotTrack = false) + $doNotTrack = false, $disableCookies = false) { Piwik::checkUserHasViewAccess($idSite); @@ -87,7 +87,7 @@ class API extends \Piwik\Plugin\API $htmlEncoded = Piwik::getJavascriptCode($idSite, $piwikUrl, $mergeSubdomains, $groupPageTitlesByDomain, $mergeAliasUrls, $visitorCustomVariables, $pageCustomVariables, $customCampaignNameQueryParam, $customCampaignKeywordParam, - $doNotTrack); + $doNotTrack, $disableCookies); $htmlEncoded = str_replace(array('<br>', '<br />', '<br/>'), '', $htmlEncoded); return $htmlEncoded; } diff --git a/tests/PHPUnit/Fixtures/UITestFixture.php b/tests/PHPUnit/Fixtures/UITestFixture.php index a65b0bc1f06d3a910ff0e6b0f936f3a1ce566e3b..6f404adefd4214ed559e3263bff999def674c3e8 100644 --- a/tests/PHPUnit/Fixtures/UITestFixture.php +++ b/tests/PHPUnit/Fixtures/UITestFixture.php @@ -62,8 +62,6 @@ class UITestFixture extends SqlDump $this->createSegments(); $this->setupDashboards(); - AssetManager::getInstance()->removeMergedAssets(); - $visitorIdDeterministic = bin2hex(Db::fetchOne( "SELECT idvisitor FROM " . Common::prefixTable('log_visit') . " WHERE idsite = 2 AND location_latitude IS NOT NULL LIMIT 1")); @@ -301,4 +299,4 @@ class UITestFixture extends SqlDump Access::setSingletonInstance($access = new OverrideLogin()); \Piwik\Piwik::postEvent('Request.initAuthenticationObject'); } -} \ No newline at end of file +} diff --git a/tests/PHPUnit/Integration/MultipleSitesArchivingTest.php b/tests/PHPUnit/Integration/MultipleSitesArchivingTest.php index 06c366dbe52f23f72f77b62f7ad8455ccf399daa..67289069b3023779162c219c5457810de994f13e 100644 --- a/tests/PHPUnit/Integration/MultipleSitesArchivingTest.php +++ b/tests/PHPUnit/Integration/MultipleSitesArchivingTest.php @@ -33,7 +33,7 @@ class MultipleSitesArchivingTest extends IntegrationTestCase } }); - Config::getInstance()->General['enable_processing_unique_visitors_multiple_sites'] = 0; + Config::getInstance()->General['enable_processing_unique_visitors_multiple_sites'] = 1; } public function getApiForTesting() diff --git a/tests/PHPUnit/UI b/tests/PHPUnit/UI index beb61478b49c3cd67a7eb20038e36346f800ca63..ee77ac0d8067defcfff383772077ac7c2bca89da 160000 --- a/tests/PHPUnit/UI +++ b/tests/PHPUnit/UI @@ -1 +1 @@ -Subproject commit beb61478b49c3cd67a7eb20038e36346f800ca63 +Subproject commit ee77ac0d8067defcfff383772077ac7c2bca89da