Web notifications. Issue #156.

This commit is contained in:
Mark Amoin 2018-04-03 15:43:11 +08:00 committed by Dmitry Khomutov
parent bf9c6fca27
commit 3f56e4cc54
No known key found for this signature in database
GPG key ID: EC19426474B37AAC
10 changed files with 512 additions and 135 deletions

2
.gitignore vendored
View file

@ -16,4 +16,4 @@
/public/assets/vendor
/public/artifacts
!/public/artifacts/.gitkeep
!/public/artifacts/.gitkeep

View file

@ -92,6 +92,7 @@
"npm-asset/sprintf-js": "~1.0.0",
"npm-asset/codemirror": "~5.23.0",
"npm-asset/notifyjs": "~3.0.0",
"bower-asset/admin-lte": "~2.3.0",
"bower-asset/font-awesome": "~4.7.0",
"bower-asset/ionicons": "~2.0.0",

279
composer.lock generated
View file

@ -4,7 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "8c2289ac491f1f1019f88be4f375b8a9",
"hash": "c36664adbc6a11c510a1a2ca21370a2a",
"content-hash": "dff41335ce906ddb872e66114ace5e50",
"packages": [
{
"name": "behat/gherkin",
@ -63,7 +64,7 @@
"gherkin",
"parser"
],
"time": "2016-10-30T11:50:56+00:00"
"time": "2016-10-30 11:50:56"
},
{
"name": "block8/php-docblock-checker",
@ -116,7 +117,7 @@
"phpci",
"testing"
],
"time": "2017-02-15T17:31:26+00:00"
"time": "2017-02-15 17:31:26"
},
{
"name": "bower-asset/admin-lte",
@ -310,7 +311,7 @@
"functional testing",
"unit testing"
],
"time": "2018-02-26T23:29:41+00:00"
"time": "2018-02-26 23:29:41"
},
{
"name": "codeception/stub",
@ -343,20 +344,20 @@
"MIT"
],
"description": "Flexible Stub wrapper for PHPUnit's Mock Builder",
"time": "2018-02-18T13:56:56+00:00"
"time": "2018-02-18 13:56:56"
},
{
"name": "composer/ca-bundle",
"version": "1.1.0",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
"reference": "943b2c4fcad1ef178d16a713c2468bf7e579c288"
"reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/943b2c4fcad1ef178d16a713c2468bf7e579c288",
"reference": "943b2c4fcad1ef178d16a713c2468bf7e579c288",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/d2c0a83b7533d6912e8d516756ebd34f893e9169",
"reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169",
"shasum": ""
},
"require": {
@ -365,7 +366,7 @@
"php": "^5.3.2 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
"psr/log": "^1.0",
"symfony/process": "^2.5 || ^3.0 || ^4.0"
},
@ -399,7 +400,7 @@
"ssl",
"tls"
],
"time": "2017-11-29T09:37:33+00:00"
"time": "2018-03-29 19:57:20"
},
{
"name": "composer/installers",
@ -519,7 +520,7 @@
"zend",
"zikula"
],
"time": "2017-12-29T09:13:20+00:00"
"time": "2017-12-29 09:13:20"
},
{
"name": "doctrine/instantiator",
@ -573,7 +574,7 @@
"constructor",
"instantiate"
],
"time": "2015-06-14T21:17:01+00:00"
"time": "2015-06-14 21:17:01"
},
{
"name": "facebook/webdriver",
@ -628,7 +629,7 @@
"selenium",
"webdriver"
],
"time": "2017-11-15T11:08:09+00:00"
"time": "2017-11-15 11:08:09"
},
{
"name": "guzzlehttp/guzzle",
@ -690,7 +691,7 @@
"rest",
"web service"
],
"time": "2017-02-28T22:50:30+00:00"
"time": "2017-02-28 22:50:30"
},
{
"name": "guzzlehttp/promises",
@ -741,7 +742,7 @@
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
"time": "2016-12-20 10:07:11"
},
{
"name": "guzzlehttp/psr7",
@ -806,7 +807,7 @@
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
"time": "2017-03-20 17:10:46"
},
{
"name": "jakub-onderka/php-parallel-lint",
@ -853,7 +854,7 @@
],
"description": "This tool check syntax of PHP files about 20x faster than serial check.",
"homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint",
"time": "2015-12-15T10:42:16+00:00"
"time": "2015-12-15 10:42:16"
},
{
"name": "jasongrimes/paginator",
@ -898,7 +899,7 @@
"pagination",
"paginator"
],
"time": "2015-10-15T09:42:44+00:00"
"time": "2015-10-15 09:42:44"
},
{
"name": "monolog/monolog",
@ -976,7 +977,7 @@
"logging",
"psr-3"
],
"time": "2017-03-13T07:08:03+00:00"
"time": "2017-03-13 07:08:03"
},
{
"name": "myclabs/deep-copy",
@ -1021,7 +1022,7 @@
"object",
"object graph"
],
"time": "2017-10-19T19:58:43+00:00"
"time": "2017-10-19 19:58:43"
},
{
"name": "nikic/php-parser",
@ -1072,7 +1073,7 @@
"parser",
"php"
],
"time": "2018-02-28T20:30:58+00:00"
"time": "2018-02-28 20:30:58"
},
{
"name": "npm-asset/codemirror",
@ -1088,6 +1089,20 @@
"MIT"
]
},
{
"name": "npm-asset/notifyjs",
"version": "3.0.0",
"dist": {
"type": "tar",
"url": "https://registry.npmjs.org/notifyjs/-/notifyjs-3.0.0.tgz",
"reference": null,
"shasum": null
},
"type": "npm-asset",
"license": [
"MIT"
]
},
{
"name": "npm-asset/sprintf-js",
"version": "1.0.3",
@ -1142,20 +1157,20 @@
],
"description": "Extend the composer/installers plugin to accept any arbitrary package type.",
"homepage": "http://www.oomphinc.com/",
"time": "2017-03-31T16:57:39+00:00"
"time": "2017-03-31 16:57:39"
},
{
"name": "paragonie/random_compat",
"version": "v2.0.11",
"version": "v2.0.12",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8"
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8",
"reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"shasum": ""
},
"require": {
@ -1190,7 +1205,7 @@
"pseudorandom",
"random"
],
"time": "2017-09-27T21:40:39+00:00"
"time": "2018-04-04 21:24:14"
},
{
"name": "pda/pheanstalk",
@ -1240,7 +1255,7 @@
"keywords": [
"beanstalkd"
],
"time": "2015-08-07T21:42:41+00:00"
"time": "2015-08-07 21:42:41"
},
{
"name": "pdepend/pdepend",
@ -1280,7 +1295,7 @@
"BSD-3-Clause"
],
"description": "Official version of pdepend to be handled with Composer",
"time": "2017-12-13T13:21:38+00:00"
"time": "2017-12-13 13:21:38"
},
{
"name": "phpdocumentor/reflection-docblock",
@ -1329,7 +1344,7 @@
"email": "mike.vanriel@naenius.com"
}
],
"time": "2016-01-25T08:17:30+00:00"
"time": "2016-01-25 08:17:30"
},
{
"name": "phploc/phploc",
@ -1378,7 +1393,7 @@
],
"description": "A tool for quickly measuring the size of a PHP project.",
"homepage": "https://github.com/sebastianbergmann/phploc",
"time": "2017-11-18T17:35:43+00:00"
"time": "2017-11-18 17:35:43"
},
{
"name": "phpmd/phpmd",
@ -1444,7 +1459,7 @@
"phpmd",
"pmd"
],
"time": "2017-01-20T14:41:10+00:00"
"time": "2017-01-20 14:41:10"
},
{
"name": "phpspec/prophecy",
@ -1507,7 +1522,7 @@
"spy",
"stub"
],
"time": "2018-02-19T10:16:54+00:00"
"time": "2018-02-19 10:16:54"
},
{
"name": "phpunit/php-code-coverage",
@ -1570,7 +1585,7 @@
"testing",
"xunit"
],
"time": "2017-04-02T07:44:40+00:00"
"time": "2017-04-02 07:44:40"
},
{
"name": "phpunit/php-file-iterator",
@ -1617,7 +1632,7 @@
"filesystem",
"iterator"
],
"time": "2017-11-27T13:52:08+00:00"
"time": "2017-11-27 13:52:08"
},
{
"name": "phpunit/php-text-template",
@ -1658,7 +1673,7 @@
"keywords": [
"template"
],
"time": "2015-06-21T13:50:34+00:00"
"time": "2015-06-21 13:50:34"
},
{
"name": "phpunit/php-timer",
@ -1707,7 +1722,7 @@
"keywords": [
"timer"
],
"time": "2017-02-26T11:10:40+00:00"
"time": "2017-02-26 11:10:40"
},
{
"name": "phpunit/php-token-stream",
@ -1756,7 +1771,7 @@
"keywords": [
"tokenizer"
],
"time": "2017-12-04T08:55:13+00:00"
"time": "2017-12-04 08:55:13"
},
{
"name": "phpunit/phpunit",
@ -1838,7 +1853,7 @@
"testing",
"xunit"
],
"time": "2018-02-01T05:50:59+00:00"
"time": "2018-02-01 05:50:59"
},
{
"name": "phpunit/phpunit-mock-objects",
@ -1897,7 +1912,7 @@
"mock",
"xunit"
],
"time": "2017-06-30T09:13:00+00:00"
"time": "2017-06-30 09:13:00"
},
{
"name": "pimple/pimple",
@ -1943,7 +1958,7 @@
"container",
"dependency injection"
],
"time": "2015-09-11T15:10:35+00:00"
"time": "2015-09-11 15:10:35"
},
{
"name": "psr/cache",
@ -1989,7 +2004,7 @@
"psr",
"psr-6"
],
"time": "2016-08-06T20:24:11+00:00"
"time": "2016-08-06 20:24:11"
},
{
"name": "psr/container",
@ -2038,7 +2053,7 @@
"container-interop",
"psr"
],
"time": "2017-02-14T16:28:37+00:00"
"time": "2017-02-14 16:28:37"
},
{
"name": "psr/http-message",
@ -2088,7 +2103,7 @@
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
"time": "2016-08-06 14:39:51"
},
{
"name": "psr/log",
@ -2135,7 +2150,7 @@
"psr",
"psr-3"
],
"time": "2016-10-10T12:19:37+00:00"
"time": "2016-10-10 12:19:37"
},
{
"name": "psr/simple-cache",
@ -2183,7 +2198,7 @@
"psr-16",
"simple-cache"
],
"time": "2017-10-23T01:57:42+00:00"
"time": "2017-10-23 01:57:42"
},
{
"name": "robmorgan/phinx",
@ -2249,7 +2264,7 @@
"migrations",
"phinx"
],
"time": "2017-06-05T13:30:19+00:00"
"time": "2017-06-05 13:30:19"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@ -2294,7 +2309,7 @@
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"time": "2017-03-04T06:30:41+00:00"
"time": "2017-03-04 06:30:41"
},
{
"name": "sebastian/comparator",
@ -2358,7 +2373,7 @@
"compare",
"equality"
],
"time": "2017-01-29T09:50:25+00:00"
"time": "2017-01-29 09:50:25"
},
{
"name": "sebastian/diff",
@ -2410,7 +2425,7 @@
"keywords": [
"diff"
],
"time": "2017-05-22T07:24:03+00:00"
"time": "2017-05-22 07:24:03"
},
{
"name": "sebastian/environment",
@ -2460,7 +2475,7 @@
"environment",
"hhvm"
],
"time": "2016-11-26T07:53:53+00:00"
"time": "2016-11-26 07:53:53"
},
{
"name": "sebastian/exporter",
@ -2527,7 +2542,7 @@
"export",
"exporter"
],
"time": "2016-11-19T08:54:04+00:00"
"time": "2016-11-19 08:54:04"
},
{
"name": "sebastian/finder-facade",
@ -2566,7 +2581,7 @@
],
"description": "FinderFacade is a convenience wrapper for Symfony's Finder component.",
"homepage": "https://github.com/sebastianbergmann/finder-facade",
"time": "2017-11-18T17:31:49+00:00"
"time": "2017-11-18 17:31:49"
},
{
"name": "sebastian/global-state",
@ -2617,7 +2632,7 @@
"keywords": [
"global state"
],
"time": "2015-10-12T03:26:01+00:00"
"time": "2015-10-12 03:26:01"
},
{
"name": "sebastian/object-enumerator",
@ -2663,7 +2678,7 @@
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"time": "2017-02-18T15:18:39+00:00"
"time": "2017-02-18 15:18:39"
},
{
"name": "sebastian/phpcpd",
@ -2714,7 +2729,7 @@
],
"description": "Copy/Paste Detector (CPD) for PHP code.",
"homepage": "https://github.com/sebastianbergmann/phpcpd",
"time": "2016-04-17T19:32:49+00:00"
"time": "2016-04-17 19:32:49"
},
{
"name": "sebastian/recursion-context",
@ -2767,7 +2782,7 @@
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2016-11-19T07:33:16+00:00"
"time": "2016-11-19 07:33:16"
},
{
"name": "sebastian/resource-operations",
@ -2809,7 +2824,7 @@
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"time": "2015-07-28T20:34:47+00:00"
"time": "2015-07-28 20:34:47"
},
{
"name": "sebastian/version",
@ -2852,7 +2867,7 @@
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2016-10-03T07:35:21+00:00"
"time": "2016-10-03 07:35:21"
},
{
"name": "sensiolabs/ansi-to-html",
@ -2896,7 +2911,7 @@
}
],
"description": "A library to convert a text with ANSI codes to HTML",
"time": "2017-05-02T00:53:29+00:00"
"time": "2017-05-02 00:53:29"
},
{
"name": "sensiolabs/security-checker",
@ -2941,7 +2956,7 @@
}
],
"description": "A security checker for your composer.lock",
"time": "2017-07-24T11:42:56+00:00"
"time": "2017-07-24 11:42:56"
},
{
"name": "squizlabs/php_codesniffer",
@ -3019,7 +3034,7 @@
"phpcs",
"standards"
],
"time": "2017-03-01T22:17:45+00:00"
"time": "2017-03-01 22:17:45"
},
{
"name": "swiftmailer/swiftmailer",
@ -3073,20 +3088,20 @@
"mail",
"mailer"
],
"time": "2018-01-23T07:37:21+00:00"
"time": "2018-01-23 07:37:21"
},
{
"name": "symfony/browser-kit",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
"reference": "490f27762705c8489bd042fe3e9377a191dba9b4"
"reference": "840bb6f0d5b3701fd768b68adf7193c2d0f98f79"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/490f27762705c8489bd042fe3e9377a191dba9b4",
"reference": "490f27762705c8489bd042fe3e9377a191dba9b4",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/840bb6f0d5b3701fd768b68adf7193c2d0f98f79",
"reference": "840bb6f0d5b3701fd768b68adf7193c2d0f98f79",
"shasum": ""
},
"require": {
@ -3130,20 +3145,20 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
"time": "2018-01-03T07:37:34+00:00"
"time": "2018-03-19 22:32:39"
},
{
"name": "symfony/cache",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache.git",
"reference": "cce49c7aa2fc82077355c8a6dfcd9e619abe6e98"
"reference": "13255ddd056e49f3154747943f8ee175d555d394"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/cache/zipball/cce49c7aa2fc82077355c8a6dfcd9e619abe6e98",
"reference": "cce49c7aa2fc82077355c8a6dfcd9e619abe6e98",
"url": "https://api.github.com/repos/symfony/cache/zipball/13255ddd056e49f3154747943f8ee175d555d394",
"reference": "13255ddd056e49f3154747943f8ee175d555d394",
"shasum": ""
},
"require": {
@ -3200,20 +3215,20 @@
"caching",
"psr6"
],
"time": "2018-02-11T14:42:07+00:00"
"time": "2018-04-02 14:35:16"
},
{
"name": "symfony/config",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "05e10567b529476a006b00746c5f538f1636810e"
"reference": "7c2a9d44f4433863e9bca682e7f03609234657f9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/05e10567b529476a006b00746c5f538f1636810e",
"reference": "05e10567b529476a006b00746c5f538f1636810e",
"url": "https://api.github.com/repos/symfony/config/zipball/7c2a9d44f4433863e9bca682e7f03609234657f9",
"reference": "7c2a9d44f4433863e9bca682e7f03609234657f9",
"shasum": ""
},
"require": {
@ -3263,20 +3278,20 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2018-02-14T10:03:57+00:00"
"time": "2018-03-19 22:32:39"
},
{
"name": "symfony/console",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "067339e9b8ec30d5f19f5950208893ff026b94f7"
"reference": "d4bb70fa24d540c309d88a9d6e43fb2d339b1fbf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/067339e9b8ec30d5f19f5950208893ff026b94f7",
"reference": "067339e9b8ec30d5f19f5950208893ff026b94f7",
"url": "https://api.github.com/repos/symfony/console/zipball/d4bb70fa24d540c309d88a9d6e43fb2d339b1fbf",
"reference": "d4bb70fa24d540c309d88a9d6e43fb2d339b1fbf",
"shasum": ""
},
"require": {
@ -3332,20 +3347,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2018-02-26T15:46:28+00:00"
"time": "2018-04-03 05:22:50"
},
{
"name": "symfony/css-selector",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "544655f1fc078a9cd839fdda2b7b1e64627c826a"
"reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/544655f1fc078a9cd839fdda2b7b1e64627c826a",
"reference": "544655f1fc078a9cd839fdda2b7b1e64627c826a",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/519a80d7c1d95c6cc0b67f686d15fe27c6910de0",
"reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0",
"shasum": ""
},
"require": {
@ -3385,20 +3400,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"time": "2018-02-03T14:55:07+00:00"
"time": "2018-03-19 22:32:39"
},
{
"name": "symfony/debug",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "9b1071f86e79e1999b3d3675d2e0e7684268b9bc"
"reference": "9cf7c2271cfb89ef9727db1b740ca77be57bf9d7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/9b1071f86e79e1999b3d3675d2e0e7684268b9bc",
"reference": "9b1071f86e79e1999b3d3675d2e0e7684268b9bc",
"url": "https://api.github.com/repos/symfony/debug/zipball/9cf7c2271cfb89ef9727db1b740ca77be57bf9d7",
"reference": "9cf7c2271cfb89ef9727db1b740ca77be57bf9d7",
"shasum": ""
},
"require": {
@ -3441,20 +3456,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2018-02-28T21:49:22+00:00"
"time": "2018-04-03 05:22:50"
},
{
"name": "symfony/dependency-injection",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
"reference": "12e901abc1cb0d637a0e5abe9923471361d96b07"
"reference": "24a68710c6ddc1e3d159a110cef94cedfcf3c611"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/12e901abc1cb0d637a0e5abe9923471361d96b07",
"reference": "12e901abc1cb0d637a0e5abe9923471361d96b07",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/24a68710c6ddc1e3d159a110cef94cedfcf3c611",
"reference": "24a68710c6ddc1e3d159a110cef94cedfcf3c611",
"shasum": ""
},
"require": {
@ -3512,20 +3527,20 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
"time": "2018-03-04T03:54:53+00:00"
"time": "2018-03-29 11:25:31"
},
{
"name": "symfony/dom-crawler",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "2bb5d3101cc01f4fe580e536daf4f1959bc2d24d"
"reference": "1a4cffeb059226ff6bee9f48acb388faf674afff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2bb5d3101cc01f4fe580e536daf4f1959bc2d24d",
"reference": "2bb5d3101cc01f4fe580e536daf4f1959bc2d24d",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/1a4cffeb059226ff6bee9f48acb388faf674afff",
"reference": "1a4cffeb059226ff6bee9f48acb388faf674afff",
"shasum": ""
},
"require": {
@ -3568,11 +3583,11 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
"time": "2018-02-22T10:48:49+00:00"
"time": "2018-03-19 22:32:39"
},
{
"name": "symfony/event-dispatcher",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
@ -3631,11 +3646,11 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2018-02-14T10:03:57+00:00"
"time": "2018-02-14 10:03:57"
},
{
"name": "symfony/filesystem",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
@ -3680,20 +3695,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2018-02-22T10:48:49+00:00"
"time": "2018-02-22 10:48:49"
},
{
"name": "symfony/finder",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "a479817ce0a9e4adfd7d39c6407c95d97c254625"
"reference": "7a2e1299cc0c4162996f18e347b6356729a55317"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/a479817ce0a9e4adfd7d39c6407c95d97c254625",
"reference": "a479817ce0a9e4adfd7d39c6407c95d97c254625",
"url": "https://api.github.com/repos/symfony/finder/zipball/7a2e1299cc0c4162996f18e347b6356729a55317",
"reference": "7a2e1299cc0c4162996f18e347b6356729a55317",
"shasum": ""
},
"require": {
@ -3729,7 +3744,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2018-03-05T18:28:11+00:00"
"time": "2018-03-28 18:23:39"
},
{
"name": "symfony/polyfill-apcu",
@ -3785,7 +3800,7 @@
"portable",
"shim"
],
"time": "2018-01-30T19:27:44+00:00"
"time": "2018-01-30 19:27:44"
},
{
"name": "symfony/polyfill-mbstring",
@ -3844,20 +3859,20 @@
"portable",
"shim"
],
"time": "2018-01-30T19:27:44+00:00"
"time": "2018-01-30 19:27:44"
},
{
"name": "symfony/process",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "cc4aea21f619116aaf1c58016a944e4821c8e8af"
"reference": "4b7d64e852886319e93ddfdecff0d744ab87658b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/cc4aea21f619116aaf1c58016a944e4821c8e8af",
"reference": "cc4aea21f619116aaf1c58016a944e4821c8e8af",
"url": "https://api.github.com/repos/symfony/process/zipball/4b7d64e852886319e93ddfdecff0d744ab87658b",
"reference": "4b7d64e852886319e93ddfdecff0d744ab87658b",
"shasum": ""
},
"require": {
@ -3893,20 +3908,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2018-02-12T17:55:00+00:00"
"time": "2018-04-03 05:22:50"
},
{
"name": "symfony/yaml",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "6af42631dcf89e9c616242c900d6c52bd53bd1bb"
"reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/6af42631dcf89e9c616242c900d6c52bd53bd1bb",
"reference": "6af42631dcf89e9c616242c900d6c52bd53bd1bb",
"url": "https://api.github.com/repos/symfony/yaml/zipball/a42f9da85c7c38d59f5e53f076fe81a091f894d0",
"reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0",
"shasum": ""
},
"require": {
@ -3951,7 +3966,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2018-02-16T09:50:28+00:00"
"time": "2018-04-03 05:14:20"
},
{
"name": "theseer/fdomdocument",
@ -3991,7 +4006,7 @@
],
"description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.",
"homepage": "https://github.com/theseer/fDOMDocument",
"time": "2017-06-30T11:53:12+00:00"
"time": "2017-06-30 11:53:12"
}
],
"packages-dev": [
@ -4048,20 +4063,20 @@
"testing",
"xunit"
],
"time": "2016-12-02T14:39:14+00:00"
"time": "2016-12-02 14:39:14"
},
{
"name": "symfony/var-dumper",
"version": "v3.4.6",
"version": "v3.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "80964679d81da3d5618519e0e4be488c3d7ecd7d"
"reference": "6f502127b1bb85f7f30f8bc1fb60570a10431863"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/80964679d81da3d5618519e0e4be488c3d7ecd7d",
"reference": "80964679d81da3d5618519e0e4be488c3d7ecd7d",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/6f502127b1bb85f7f30f8bc1fb60570a10431863",
"reference": "6f502127b1bb85f7f30f8bc1fb60570a10431863",
"shasum": ""
},
"require": {
@ -4117,7 +4132,7 @@
"debug",
"dump"
],
"time": "2018-02-22T17:29:24+00:00"
"time": "2018-04-03 05:22:50"
}
],
"aliases": [],

View file

@ -1,6 +1,18 @@
var PHPCensor = {
intervals: {},
widgets: {},
webNotifiedBuilds: [],
/*
@var STATUS Refer to \PHPCensor\Model\Build.php constants.
TODO: Transfer this variable to Build JS class so
Build JS itself can use it as well.
*/
STATUS: [
'Pending',
'Running',
'Success',
'Failed'
],
init: function () {
$(document).ready(function () {
@ -19,6 +31,128 @@ var PHPCensor = {
});
},
/**
* Shallow comparison that determines that the build
* has been shown as at least once as a web notification.
* Also adds the build to a list of shown web notifications
* if it's not found in the list.
* @param object build
* @return boolean
*/
isWebNotifiedBuild: function (build) {
var o = PHPCensor.webNotifiedBuilds;
for (var i = 0; i < o.length; i++) {
var webNotifiedBuild = o[i];
var b =
webNotifiedBuild.projectTitle === build.projectTitle &&
webNotifiedBuild.branch === build.branch &&
webNotifiedBuild.status === build.status &&
webNotifiedBuild.datePerformed === build.datePerformed &&
webNotifiedBuild.dateFinished === build.dateFinished;
if (b) {
return true;
}
}
/*
It's impossible to remember or use all previously shown
builds. So let's clear them out once they reach 1000.
@var 1000 Estimated.
*/
if (PHPCensor.webNotifiedBuilds.length > 1000) {
PHPCensor.webNotifiedBuilds = [];
}
PHPCensor.webNotifiedBuilds.push(build);
return false;
},
/**
* Web notification.
* Chrome doesn't allow insecure protocols.
* Enable HTTPS even on localhost in order for
* web notifications to work properly.
* @param object data Contains an array of builds.
* @return void
*/
showWebNotification: function (data) {
var pending = data.pending;
var running = data.running;
var success = data.success;
var failed = data.failed;
var notification = null;
//Determine which notification to show.
//TODO: Refactor. Use foreach.
if (pending && pending.count > 0) {
notification = pending;
}
else if (running && running.count > 0) {
notification = running;
}
else if (success && success.count > 0) {
notification = success;
}
else if (failed && failed.count > 0) {
notification = failed;
}
if (notification) {
var msg = '';
if (!Notify.needsPermission) {
var items = notification.items;
for (var item in items) {
var build = items[item].build;
var projTitle = build.project_title;
var branch = build.branch;
var status = PHPCensor.STATUS[build.status];
var datePerformed = build.date_performed;
var dateFinished = build.date_finished;
var rn = "\r\n";
var build = {
projectTitle: projTitle,
branch: branch,
status: status,
datePerformed: datePerformed,
dateFinished: dateFinished
};
//Ignore if the last displayed notification is
//similar to what we're again about to display.
if (!PHPCensor.isWebNotifiedBuild(build)) {
msg +=
'Project title: ' + projTitle + rn +
'Git branch: ' + branch + rn +
'Status: ' + status + rn;
//Build details is empty during
//widget-all-projects-update.
if (datePerformed.length > 0) {
msg += datePerformed + rn;
}
if (dateFinished.length > 0) {
msg += dateFinished;
}
new Notify(
'PHP Censor Web Notification',
{body: msg}
).show();
}
}
}
else if (Notify.isSupported()) {
Notify.requestPermission(null, function(){
msg = 'Web notifications permission ' +
'has been denied by the user.'
console.warn(msg);
});
}
}
},
getBuilds: function () {
$.ajax({
url: APP_URL + 'build/ajax-queue',
@ -29,6 +163,14 @@ var PHPCensor = {
error: PHPCensor.handleFailedAjax
});
$.ajax({
url: APP_URL + 'web-notifications/builds-updated',
success: function (data) {
PHPCensor.showWebNotification(data);
},
error: PHPCensor.handleFailedAjax
});
},
getProjectBuilds: function () {

View file

@ -33,6 +33,18 @@ PHPCensor.widgets.allProjects = {
error: PHPCensor.handleFailedAjax
});
//Let's build another mechanism for web notification
//since the above feature is tightly coupled to the view.
$.ajax({
url: APP_URL +
'web-notifications/widgets-all-projects-update/' +
projectId,
success: function (data) {
PHPCensor.showWebNotification(data);
},
error: PHPCensor.handleFailedAjax
});
});
}
};

View file

@ -365,9 +365,17 @@ class BuildController extends WebController
public function ajaxQueue()
{
$sPending = 'pending';
$sRunning = 'running';
$pending = $this->buildStore->getByStatus(Build::STATUS_PENDING);
$running = $this->buildStore->getByStatus(Build::STATUS_RUNNING);
$rtn = [
'pending' => $this->formatBuilds($this->buildStore->getByStatus(Build::STATUS_PENDING)),
'running' => $this->formatBuilds($this->buildStore->getByStatus(Build::STATUS_RUNNING)),
$sPending => $this->formatBuilds($pending),
$sRunning => $this->formatBuilds($running),
];
$response = new JsonResponse();

View file

@ -0,0 +1,114 @@
<?php
namespace PHPCensor\Controller;
use PHPCensor\Model\Build;
use PHPCensor\WebController;
use PHPCensor\Store\Factory;
//use PHPCensor\View;
//use PHPCensor\Model\Project;
//use PHPCensor\Http\Response;
//use PHPCensor\Store\BuildStore;
//use PHPCensor\Store\ProjectStore;
//use PHPCensor\Store\ProjectGroupStore;
//use PHPCensor\Service\BuildService;
//use b8\Http\Response\JsonResponse;
use PHPCensor\Http\Response\JsonResponse;
use PHPCensor\Service\WebNotificationService;
/**
* Web Notifications Controller
*/
class WebNotificationsController extends WebController
{
/**
* @var BuildStore
*/
protected $buildStore;
/**
* @var ProjectStore
*/
protected $projectStore;
/**
* @var ProjectGroupStore
*/
protected $groupStore;
/**
* Initialise the controller, set up stores and services.
*/
public function init()
{
parent::init();
$this->buildStore = Factory::getStore('Build');
$this->projectStore = Factory::getStore('Project');
$this->groupStore = Factory::getStore('ProjectGroup');
}
/**
* Provides JSON format for web notification UI of all last
* builds that have success and failed status.
* This is similar to WidgetAllProjectsController::update()
* but instead, this only returns JSON.
* @param int $projectId
* @return \PHPCensor\Http\Response\JsonResponse
* @see \PHPCensor\Controller\WidgetAllProjectsController
*/
public function widgetsAllProjectsUpdate($projectId)
{
$success = $this->buildStore->getLastBuildByStatus($projectId, Build::STATUS_SUCCESS);
$failed = $this->buildStore->getLastBuildByStatus($projectId, Build::STATUS_FAILED);
$oSuccess = WebNotificationService::formatBuild($success);
$oFailed = WebNotificationService::formatBuild($failed);
//@keys count and items Follow the for-loop structure
//found in
//\PHPCensor\Service\WebNotificationService::formatBuilds()
$aSuccess = [
'count' => count($oSuccess),
'items' => [$projectId => ['build' => $oSuccess]]
];
$aFailed = [
'count' => count($oFailed),
'items' => [$projectId => ['build' => $oFailed]]
];
$builds = [
'success' => $aSuccess,
'failed' => $aFailed
];
$response = new JsonResponse();
$response->setContent($builds);
return $response;
}
/**
* Provides JSON format for web notification UI of all last
* builds that have pending and running status.
* This is similar to WidgetAllProjectsController::update()
* but instead, this only returns JSON.
* @return \PHPCensor\Http\Response\JsonResponse
*/
public function buildsUpdated()
{
$pending = $this->buildStore->getByStatus(Build::STATUS_PENDING);
$running = $this->buildStore->getByStatus(Build::STATUS_RUNNING);
$rtn = [
'pending' => WebNotificationService::formatBuilds($pending),
'running' => WebNotificationService::formatBuilds($running)
];
$response = new JsonResponse();
$response->setContent($rtn);
return $response;
}
}

View file

@ -11,6 +11,8 @@ use PHPCensor\Http\Response;
use PHPCensor\Store\BuildStore;
use PHPCensor\Store\ProjectStore;
use PHPCensor\Store\ProjectGroupStore;
use PHPCensor\Service\BuildService;
use b8\Http\Response\JsonResponse;
/**
* Widget All Projects Controller

View file

@ -0,0 +1,82 @@
<?php
namespace PHPCensor\Service;
use PHPCensor\Config;
use Pheanstalk\Pheanstalk;
use Pheanstalk\PheanstalkInterface;
use PHPCensor\BuildFactory;
use PHPCensor\Model\Build;
use PHPCensor\Model\Project;
use PHPCensor\Store\BuildStore;
/**
* A service that listens for creation, duplication and deletion of builds for web notification UI.
*/
class WebNotificationService
{
/**
* Similar to BuildController::formatBuilds() but uses
* pure object to be used for rendering web notifications.
* @param array $builds
* @return array Formatted builds
* @see \PHPCensor\Controller\WidgetLastBuildsController::webNotificationUpdate().
*/
public static function formatBuilds($builds)
{
$rtn = ['count' => $builds['count'], 'items' => []];
foreach ($builds['items'] as $buildItem) {
$build = self::formatBuild($buildItem);
$rtn['items'][$buildItem->getId()]['build'] = $build;
}
ksort($rtn['items']);
return $rtn;
}
/**
* Provides structured keys for web notification.
* @param Build $build
* @return array
*/
public static function formatBuild($build)
{
if (empty($build) || is_null($build)) {
return [];
}
$status = $build->getStatus();
$datePerformed = '';
$dateFinished = '';
/*
BUG: Lang::out() automatically renders the values for
either 'created_x' or 'started_x' instead of just
returning them.
*/
if ($status === Build::STATUS_PENDING) {
$datePerformed = 'Created: ' . $build->getCreateDate()->format('H:i');
} elseif ($status === Build::STATUS_RUNNING) {
$datePerformed = 'Started: ' . $build->getStartDate()->format('H:i');
}
if (!is_null($build->getFinishDate())) {
$dateFinished = 'Finished: ' . $build->getFinishDate()->format('H:i');
}
return [
'branch' => $build->getBranch(),
'url' => APP_URL .
'build/view/' .
$build->getId(),
'committer_email' => $build->getCommitterEmail(),
'img_src' => 'https://www.gravatar.com/avatar/' .
md5($build->getCommitterEmail()) .
'?d=mm&s=40',
'project_title' => $build->getProject()->getTitle(),
'status' => $status,
'date_performed' => $datePerformed,
'date_finished' => $dateFinished
];
}
}

View file

@ -32,6 +32,7 @@ $user = $this->getUser();
<script src="<?= APP_URL; ?>assets/vendor/sprintf-js/dist/sprintf.min.js"></script>
<script src="<?= APP_URL; ?>assets/js/app.js?v2" type="text/javascript"></script>
<script src="<?= APP_URL; ?>assets/vendor/notifyjs/dist/notify.js" type="text/javascript"></script>
<script>
var APP_URL = '<?= APP_URL; ?>';