├── CHANGELOG.md ├── CONTRIBUTING.md ├── CREDITS.md ├── LICENSE.md ├── Procfile ├── README.md ├── composer.json ├── composer.lock ├── heroku.md └── src ├── ActiveRecord.php ├── Bootstrap.php ├── Layout.php ├── Module.php ├── Panel.php ├── components ├── DashboardAccess.php └── DashboardPanelAccess.php ├── controllers ├── DashboardController.php └── DashboardPanelController.php ├── layouts └── DefaultLayout.php ├── migrations ├── m150705_000001_create_dashboard.php └── m150705_000002_create_dashboard_panel.php ├── models ├── Dashboard.php ├── DashboardPanel.php ├── query │ ├── DashboardPanelQuery.php │ └── DashboardQuery.php └── search │ └── DashboardSearch.php ├── panels └── TextPanel.php ├── views ├── dashboard-panel │ ├── create.php │ └── update.php ├── dashboard │ ├── create.php │ ├── empty.php │ ├── index.php │ ├── layouts │ │ ├── _buttons.php │ │ └── default │ │ │ ├── form.php │ │ │ ├── update.php │ │ │ └── view.php │ ├── panels │ │ ├── _buttons.php │ │ └── text │ │ │ ├── form.php │ │ │ ├── update.php │ │ │ └── view.php │ ├── update.php │ └── view.php └── layouts │ └── main.php ├── web ├── DashboardAsset.php └── assets │ ├── css │ └── dashboard.css │ └── js │ └── dashboard.js └── widgets ├── Alert.php └── AskToSaveWork.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.1.0 4 | 5 | * initial relase 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are **welcome** and will be fully **credited**. 4 | 5 | We accept contributions via Pull Requests on [Github](https://github.com/cornernote/yii2-dashboard). 6 | 7 | 8 | ## Pull Requests 9 | 10 | - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). 11 | 12 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests. 13 | 14 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. 15 | 16 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. 17 | 18 | - **Create feature branches** - Don't ask us to pull from your master branch. 19 | 20 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 21 | 22 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. 23 | 24 | 25 | ## Running Tests 26 | 27 | ``` bash 28 | $ cd tests 29 | $ codecept run 30 | ``` 31 | 32 | 33 | **Happy coding**! 34 | -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | ## Developers 4 | 5 | * [Brett O'Donnell (cornernote)](https://github.com/cornernote) 6 | 7 | ## Related Projects 8 | 9 | * [Krajee Yii2 Sortable](https://github.com/kartik-v/yii2-sortable) 10 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The BSD License (BSD) 2 | 3 | Copyright (c) 2013-2015, Mr PHP 4 | 5 | > Redistribution and use in source and binary forms, with or without modification, 6 | > are permitted provided that the following conditions are met: 7 | > 8 | > Redistributions of source code must retain the above copyright notice, this 9 | > list of conditions and the following disclaimer. 10 | > 11 | > Redistributions in binary form must reproduce the above copyright notice, this 12 | > list of conditions and the following disclaimer in the documentation and/or 13 | > other materials provided with the distribution. 14 | > 15 | > Neither the name of Mr PHP. nor the names of its 16 | > contributors may be used to endorse or promote products derived from 17 | > this software without specific prior written permission. 18 | > 19 | >THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | >ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | >WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | >DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 | >ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | >(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | >LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | >ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | >(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | >SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: vendor/bin/heroku-php-apache2 tests/codeception/_app/web/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yii2 Dashboard 2 | 3 | [![Latest Version](https://img.shields.io/github/tag/cornernote/yii2-dashboard.svg?style=flat-square&label=release)](https://github.com/cornernote/yii2-dashboard/tags) 4 | [![Software License](https://img.shields.io/badge/license-BSD-brightgreen.svg?style=flat-square)](LICENSE.md) 5 | [![Build Status](https://img.shields.io/travis/cornernote/yii2-dashboard/master.svg?style=flat-square)](https://travis-ci.org/cornernote/yii2-dashboard) 6 | [![HHVM](https://img.shields.io/hhvm/cornernote/yii2-dashboard.svg?style=flat-square)](http://hhvm.h4cc.de/package/cornernote/yii2-dashboard) 7 | [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/cornernote/yii2-dashboard.svg?style=flat-square)](https://scrutinizer-ci.com/g/cornernote/yii2-dashboard/code-structure) 8 | [![Quality Score](https://img.shields.io/scrutinizer/g/cornernote/yii2-dashboard.svg?style=flat-square)](https://scrutinizer-ci.com/g/cornernote/yii2-dashboard) 9 | [![Total Downloads](https://img.shields.io/packagist/dt/cornernote/yii2-dashboard.svg?style=flat-square)](https://packagist.org/packages/cornernote/yii2-dashboard) 10 | [![Yii2 Framework](https://img.shields.io/badge/extension-Yii2_Framework-green.svg?style=flat-square)](http://www.yiiframework.com/extension/yii2-dashboard) 11 | 12 | Yii2 Dashboard is a module that allows you to create and manage dashboards using custom layouts and panels. 13 | 14 | 15 | ## Features 16 | 17 | * Create custom [layouts](http://cornernote.github.io/yii2-dashboard/docs/layouts/) with regions where panels can be placed. 18 | * Create custom [panels](http://cornernote.github.io/yii2-dashboard/docs/panels/) to display your data inside a layout region. 19 | * Drag-and-drop interface to rearrange panels inside a layout. 20 | 21 | 22 | ## Documentation 23 | 24 | Getting started? Try the [Installation Guide](https://cornernote.github.io/yii2-dashboard/docs/installation/). You will find further information in the [Documentation](https://cornernote.github.io/yii2-dashboard/docs/). 25 | 26 | For changes since the last version see the [Changelog](https://github.com/cornernote/yii2-dashboard/blob/master/CHANGELOG.md). 27 | 28 | ## Config 29 | 30 | ```php 31 | [ 34 | 'dashboard' => [ 35 | 'class' => 'cornernote\dashboard\Module', 36 | 'layouts' => [ 37 | 'default' => 'cornernote\dashboard\layouts\DefaultLayout', 38 | 'example' => 'tests\app\dashboard\layouts\ExampleLayout', 39 | ], 40 | 'updateRoles' => ['dashboardAdmin'], 41 | 'panels' => [ 42 | 'example' => [ 43 | 'class' => 'app\dashboard\panels\ExamplePanel', 44 | 'allowRules => ['exampleRule'], 45 | ], 46 | ], 47 | 'dashboards' => [ 48 | 'dashboard first' => [ 49 | 'viewRoles => ['firstRule'], 50 | ], 51 | ], 52 | ], 53 | ], 54 | ]; 55 | ``` 56 | 57 | 58 | ## Screenshots 59 | 60 | ![Dashboard View](https://cloud.githubusercontent.com/assets/51875/8636670/21febed6-28ae-11e5-8fc7-dc57e5bbc422.png) 61 | 62 | More images are available from the [Screenshots](https://cornernote.github.io/yii2-dashboard/screenshots/) page. 63 | 64 | 65 | ## Contributing 66 | 67 | Contributions are welcome. Please refer to the [contributing guidelines](CONTRIBUTING.md). 68 | 69 | Thanks to [everyone who has contributed](CREDITS.md). 70 | 71 | 72 | ## Project Resources 73 | 74 | * [Project Homepage](https://cornernote.github.io/yii2-dashboard) 75 | * [Live Demo](http://yii2-dashboard.herokuapp.com/) 76 | * [GitHub Project](https://github.com/cornernote/yii2-dashboard) 77 | * [Yii2 Extension](http://www.yiiframework.com/extension/yii2-dashboard) 78 | * [Packagist Package](https://packagist.org/packages/cornernote/yii2-dashboard) 79 | * [Travis CI Testing](https://travis-ci.org/cornernote/yii2-dashboard) 80 | * [Scrutinizer CI Code Quality](https://scrutinizer-ci.com/g/cornernote/yii2-dashboard) 81 | 82 | 83 | ## License 84 | 85 | BSD-3 - Please refer to the [license](LICENSE.md). 86 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cornernote/yii2-dashboard", 3 | "description": "Dashboard manager for Yii2", 4 | "keywords": ["yii2", "dashboard"], 5 | "type": "yii2-extension", 6 | "license": "BSD 3-Clause", 7 | "authors": [ 8 | { 9 | "name": "Brett O'Donnell", 10 | "homepage": "https://mrphp.com.au/", 11 | "email": "cornernote@gmail.com" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=5.4.0", 16 | "yiisoft/yii2": "2.*", 17 | "yiisoft/yii2-bootstrap": "2.*", 18 | "kartik-v/yii2-sortable": "1.2.*" 19 | }, 20 | "require-dev": { 21 | "yiisoft/yii2-codeception": "2.*", 22 | "codeception/specify": "*", 23 | "codeception/verify": "*", 24 | "codeception/c3": "*", 25 | "scrutinizer/ocular": "~1.1", 26 | "heroku/heroku-buildpack-php": "*", 27 | "fxp/composer-asset-plugin": "1.*" 28 | }, 29 | "autoload": { 30 | "psr-4": {"cornernote\\dashboard\\": "src"} 31 | }, 32 | "extra": { 33 | "bootstrap": "cornernote\\dashboard\\Bootstrap" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "6d8f513b7359cc59ad20210d669530d5", 8 | "packages": [ 9 | { 10 | "name": "bower-asset/bootstrap", 11 | "version": "v3.3.5", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/twbs/bootstrap.git", 15 | "reference": "16b48259a62f576e52c903c476bd42b90ab22482" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/twbs/bootstrap/zipball/16b48259a62f576e52c903c476bd42b90ab22482", 20 | "reference": "16b48259a62f576e52c903c476bd42b90ab22482", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "bower-asset/jquery": ">=1.9.1" 25 | }, 26 | "type": "bower-asset-library", 27 | "extra": { 28 | "bower-asset-main": [ 29 | "less/bootstrap.less", 30 | "dist/js/bootstrap.js" 31 | ], 32 | "bower-asset-ignore": [ 33 | "/.*", 34 | "_config.yml", 35 | "CNAME", 36 | "composer.json", 37 | "CONTRIBUTING.md", 38 | "docs", 39 | "js/tests", 40 | "test-infra" 41 | ] 42 | }, 43 | "license": [ 44 | "MIT" 45 | ], 46 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 47 | "keywords": [ 48 | "css", 49 | "framework", 50 | "front-end", 51 | "js", 52 | "less", 53 | "mobile-first", 54 | "responsive", 55 | "web" 56 | ] 57 | }, 58 | { 59 | "name": "bower-asset/jquery", 60 | "version": "2.1.4", 61 | "source": { 62 | "type": "git", 63 | "url": "https://github.com/jquery/jquery.git", 64 | "reference": "7751e69b615c6eca6f783a81e292a55725af6b85" 65 | }, 66 | "dist": { 67 | "type": "zip", 68 | "url": "https://api.github.com/repos/jquery/jquery/zipball/7751e69b615c6eca6f783a81e292a55725af6b85", 69 | "reference": "7751e69b615c6eca6f783a81e292a55725af6b85", 70 | "shasum": "" 71 | }, 72 | "require-dev": { 73 | "bower-asset/qunit": "1.14.0", 74 | "bower-asset/requirejs": "2.1.10", 75 | "bower-asset/sinon": "1.8.1", 76 | "bower-asset/sizzle": "2.1.1-patch2" 77 | }, 78 | "type": "bower-asset-library", 79 | "extra": { 80 | "bower-asset-main": "dist/jquery.js", 81 | "bower-asset-ignore": [ 82 | "**/.*", 83 | "build", 84 | "dist/cdn", 85 | "speed", 86 | "test", 87 | "*.md", 88 | "AUTHORS.txt", 89 | "Gruntfile.js", 90 | "package.json" 91 | ] 92 | }, 93 | "license": [ 94 | "MIT" 95 | ], 96 | "keywords": [ 97 | "javascript", 98 | "jquery", 99 | "library" 100 | ] 101 | }, 102 | { 103 | "name": "bower-asset/jquery.inputmask", 104 | "version": "3.1.63", 105 | "source": { 106 | "type": "git", 107 | "url": "https://github.com/RobinHerbots/jquery.inputmask.git", 108 | "reference": "c40c7287eadc31e341ebbf0c02352eb55b9cbc48" 109 | }, 110 | "dist": { 111 | "type": "zip", 112 | "url": "https://api.github.com/repos/RobinHerbots/jquery.inputmask/zipball/c40c7287eadc31e341ebbf0c02352eb55b9cbc48", 113 | "reference": "c40c7287eadc31e341ebbf0c02352eb55b9cbc48", 114 | "shasum": "" 115 | }, 116 | "require": { 117 | "bower-asset/jquery": ">=1.7" 118 | }, 119 | "type": "bower-asset-library", 120 | "extra": { 121 | "bower-asset-main": [ 122 | "./dist/inputmask/jquery.inputmask.js", 123 | "./dist/inputmask/jquery.inputmask.extensions.js", 124 | "./dist/inputmask/jquery.inputmask.date.extensions.js", 125 | "./dist/inputmask/jquery.inputmask.numeric.extensions.js", 126 | "./dist/inputmask/jquery.inputmask.phone.extensions.js", 127 | "./dist/inputmask/jquery.inputmask.regex.extensions.js" 128 | ], 129 | "bower-asset-ignore": [ 130 | "**/.*", 131 | "qunit/", 132 | "nuget/", 133 | "tools/", 134 | "js/", 135 | "*.md", 136 | "build.properties", 137 | "build.xml", 138 | "jquery.inputmask.jquery.json" 139 | ] 140 | }, 141 | "license": [ 142 | "http://opensource.org/licenses/mit-license.php" 143 | ], 144 | "description": "jquery.inputmask is a jquery plugin which create an input mask.", 145 | "keywords": [ 146 | "form", 147 | "input", 148 | "inputmask", 149 | "jquery", 150 | "mask", 151 | "plugins" 152 | ] 153 | }, 154 | { 155 | "name": "bower-asset/punycode", 156 | "version": "v1.3.2", 157 | "source": { 158 | "type": "git", 159 | "url": "https://github.com/bestiejs/punycode.js.git", 160 | "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3" 161 | }, 162 | "dist": { 163 | "type": "zip", 164 | "url": "https://api.github.com/repos/bestiejs/punycode.js/zipball/38c8d3131a82567bfef18da09f7f4db68c84f8a3", 165 | "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3", 166 | "shasum": "" 167 | }, 168 | "type": "bower-asset-library", 169 | "extra": { 170 | "bower-asset-main": "punycode.js", 171 | "bower-asset-ignore": [ 172 | "coverage", 173 | "tests", 174 | ".*", 175 | "component.json", 176 | "Gruntfile.js", 177 | "node_modules", 178 | "package.json" 179 | ] 180 | } 181 | }, 182 | { 183 | "name": "bower-asset/yii2-pjax", 184 | "version": "v2.0.4", 185 | "source": { 186 | "type": "git", 187 | "url": "https://github.com/yiisoft/jquery-pjax.git", 188 | "reference": "3f20897307cca046fca5323b318475ae9dac0ca0" 189 | }, 190 | "dist": { 191 | "type": "zip", 192 | "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/3f20897307cca046fca5323b318475ae9dac0ca0", 193 | "reference": "3f20897307cca046fca5323b318475ae9dac0ca0", 194 | "shasum": "" 195 | }, 196 | "require": { 197 | "bower-asset/jquery": ">=1.8" 198 | }, 199 | "type": "bower-asset-library", 200 | "extra": { 201 | "bower-asset-main": "./jquery.pjax.js", 202 | "bower-asset-ignore": [ 203 | ".travis.yml", 204 | "Gemfile", 205 | "Gemfile.lock", 206 | "vendor/", 207 | "script/", 208 | "test/" 209 | ] 210 | }, 211 | "license": [ 212 | "MIT" 213 | ] 214 | }, 215 | { 216 | "name": "cebe/markdown", 217 | "version": "1.1.0", 218 | "source": { 219 | "type": "git", 220 | "url": "https://github.com/cebe/markdown.git", 221 | "reference": "54a2c49de31cc44e864ebf0500a35ef21d0010b2" 222 | }, 223 | "dist": { 224 | "type": "zip", 225 | "url": "https://api.github.com/repos/cebe/markdown/zipball/54a2c49de31cc44e864ebf0500a35ef21d0010b2", 226 | "reference": "54a2c49de31cc44e864ebf0500a35ef21d0010b2", 227 | "shasum": "" 228 | }, 229 | "require": { 230 | "lib-pcre": "*", 231 | "php": ">=5.4.0" 232 | }, 233 | "require-dev": { 234 | "cebe/indent": "*", 235 | "facebook/xhprof": "*@dev", 236 | "phpunit/phpunit": "4.1.*" 237 | }, 238 | "bin": [ 239 | "bin/markdown" 240 | ], 241 | "type": "library", 242 | "extra": { 243 | "branch-alias": { 244 | "dev-master": "1.1.x-dev" 245 | } 246 | }, 247 | "autoload": { 248 | "psr-4": { 249 | "cebe\\markdown\\": "" 250 | } 251 | }, 252 | "notification-url": "https://packagist.org/downloads/", 253 | "license": [ 254 | "MIT" 255 | ], 256 | "authors": [ 257 | { 258 | "name": "Carsten Brandt", 259 | "email": "mail@cebe.cc", 260 | "homepage": "http://cebe.cc/", 261 | "role": "Creator" 262 | } 263 | ], 264 | "description": "A super fast, highly extensible markdown parser for PHP", 265 | "homepage": "https://github.com/cebe/markdown#readme", 266 | "keywords": [ 267 | "extensible", 268 | "fast", 269 | "gfm", 270 | "markdown", 271 | "markdown-extra" 272 | ], 273 | "time": "2015-03-06 05:28:07" 274 | }, 275 | { 276 | "name": "ezyang/htmlpurifier", 277 | "version": "v4.6.0", 278 | "source": { 279 | "type": "git", 280 | "url": "https://github.com/ezyang/htmlpurifier.git", 281 | "reference": "6f389f0f25b90d0b495308efcfa073981177f0fd" 282 | }, 283 | "dist": { 284 | "type": "zip", 285 | "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/6f389f0f25b90d0b495308efcfa073981177f0fd", 286 | "reference": "6f389f0f25b90d0b495308efcfa073981177f0fd", 287 | "shasum": "" 288 | }, 289 | "require": { 290 | "php": ">=5.2" 291 | }, 292 | "type": "library", 293 | "autoload": { 294 | "psr-0": { 295 | "HTMLPurifier": "library/" 296 | }, 297 | "files": [ 298 | "library/HTMLPurifier.composer.php" 299 | ] 300 | }, 301 | "notification-url": "https://packagist.org/downloads/", 302 | "license": [ 303 | "LGPL" 304 | ], 305 | "authors": [ 306 | { 307 | "name": "Edward Z. Yang", 308 | "email": "admin@htmlpurifier.org", 309 | "homepage": "http://ezyang.com" 310 | } 311 | ], 312 | "description": "Standards compliant HTML filter written in PHP", 313 | "homepage": "http://htmlpurifier.org/", 314 | "keywords": [ 315 | "html" 316 | ], 317 | "time": "2013-11-30 08:25:19" 318 | }, 319 | { 320 | "name": "kartik-v/yii2-krajee-base", 321 | "version": "v1.7.7", 322 | "source": { 323 | "type": "git", 324 | "url": "https://github.com/kartik-v/yii2-krajee-base.git", 325 | "reference": "c0adff9d9762f4fd3bf0e7cd0000fcab0bf00f19" 326 | }, 327 | "dist": { 328 | "type": "zip", 329 | "url": "https://api.github.com/repos/kartik-v/yii2-krajee-base/zipball/c0adff9d9762f4fd3bf0e7cd0000fcab0bf00f19", 330 | "reference": "c0adff9d9762f4fd3bf0e7cd0000fcab0bf00f19", 331 | "shasum": "" 332 | }, 333 | "require": { 334 | "yiisoft/yii2-bootstrap": "@dev" 335 | }, 336 | "type": "yii2-extension", 337 | "autoload": { 338 | "psr-4": { 339 | "kartik\\base\\": "" 340 | } 341 | }, 342 | "notification-url": "https://packagist.org/downloads/", 343 | "license": [ 344 | "BSD-3-Clause" 345 | ], 346 | "authors": [ 347 | { 348 | "name": "Kartik Visweswaran", 349 | "email": "kartikv2@gmail.com", 350 | "homepage": "http://www.krajee.com/" 351 | } 352 | ], 353 | "description": "Base library and foundation components for all Yii2 Krajee extensions.", 354 | "homepage": "https://github.com/kartik-v/yii2-krajee-base", 355 | "keywords": [ 356 | "base", 357 | "extension", 358 | "foundation", 359 | "krajee", 360 | "widget", 361 | "yii2" 362 | ], 363 | "time": "2015-06-16 05:19:57" 364 | }, 365 | { 366 | "name": "kartik-v/yii2-sortable", 367 | "version": "v1.2.0", 368 | "source": { 369 | "type": "git", 370 | "url": "https://github.com/kartik-v/yii2-sortable.git", 371 | "reference": "650dfd6876115fbb996eb6eb8f1d5d13ddb69285" 372 | }, 373 | "dist": { 374 | "type": "zip", 375 | "url": "https://api.github.com/repos/kartik-v/yii2-sortable/zipball/650dfd6876115fbb996eb6eb8f1d5d13ddb69285", 376 | "reference": "650dfd6876115fbb996eb6eb8f1d5d13ddb69285", 377 | "shasum": "" 378 | }, 379 | "require": { 380 | "kartik-v/yii2-krajee-base": "~1.7" 381 | }, 382 | "type": "yii2-extension", 383 | "autoload": { 384 | "psr-4": { 385 | "kartik\\sortable\\": "" 386 | } 387 | }, 388 | "notification-url": "https://packagist.org/downloads/", 389 | "license": [ 390 | "BSD-3-Clause" 391 | ], 392 | "authors": [ 393 | { 394 | "name": "Kartik Visweswaran", 395 | "email": "kartikv2@gmail.com", 396 | "homepage": "http://www.krajee.com/" 397 | } 398 | ], 399 | "description": "Create sortable lists and grids using HTML5 drag and drop API for Yii 2.0.", 400 | "homepage": "https://github.com/kartik-v/yii2-sortable", 401 | "keywords": [ 402 | "bootstrap", 403 | "extension", 404 | "jquery", 405 | "range", 406 | "sortable", 407 | "widget", 408 | "yii2" 409 | ], 410 | "time": "2015-06-17 17:34:48" 411 | }, 412 | { 413 | "name": "yiisoft/yii2", 414 | "version": "2.0.5", 415 | "source": { 416 | "type": "git", 417 | "url": "https://github.com/yiisoft/yii2-framework.git", 418 | "reference": "ea8c13b9f5cd437bd7bf73cad8a3457a155f3727" 419 | }, 420 | "dist": { 421 | "type": "zip", 422 | "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/ea8c13b9f5cd437bd7bf73cad8a3457a155f3727", 423 | "reference": "ea8c13b9f5cd437bd7bf73cad8a3457a155f3727", 424 | "shasum": "" 425 | }, 426 | "require": { 427 | "bower-asset/jquery": "2.1.*@stable | 1.11.*@stable", 428 | "bower-asset/jquery.inputmask": "3.1.*", 429 | "bower-asset/punycode": "1.3.*", 430 | "bower-asset/yii2-pjax": ">=2.0.1", 431 | "cebe/markdown": "~1.0.0 | ~1.1.0", 432 | "ext-mbstring": "*", 433 | "ezyang/htmlpurifier": "4.6.*", 434 | "lib-pcre": "*", 435 | "php": ">=5.4.0", 436 | "yiisoft/yii2-composer": "*" 437 | }, 438 | "bin": [ 439 | "yii" 440 | ], 441 | "type": "library", 442 | "extra": { 443 | "branch-alias": { 444 | "dev-master": "2.0.x-dev" 445 | } 446 | }, 447 | "autoload": { 448 | "psr-4": { 449 | "yii\\": "" 450 | } 451 | }, 452 | "notification-url": "https://packagist.org/downloads/", 453 | "license": [ 454 | "BSD-3-Clause" 455 | ], 456 | "authors": [ 457 | { 458 | "name": "Qiang Xue", 459 | "email": "qiang.xue@gmail.com", 460 | "homepage": "http://www.yiiframework.com/", 461 | "role": "Founder and project lead" 462 | }, 463 | { 464 | "name": "Alexander Makarov", 465 | "email": "sam@rmcreative.ru", 466 | "homepage": "http://rmcreative.ru/", 467 | "role": "Core framework development" 468 | }, 469 | { 470 | "name": "Maurizio Domba", 471 | "homepage": "http://mdomba.info/", 472 | "role": "Core framework development" 473 | }, 474 | { 475 | "name": "Carsten Brandt", 476 | "email": "mail@cebe.cc", 477 | "homepage": "http://cebe.cc/", 478 | "role": "Core framework development" 479 | }, 480 | { 481 | "name": "Timur Ruziev", 482 | "email": "resurtm@gmail.com", 483 | "homepage": "http://resurtm.com/", 484 | "role": "Core framework development" 485 | }, 486 | { 487 | "name": "Paul Klimov", 488 | "email": "klimov.paul@gmail.com", 489 | "role": "Core framework development" 490 | } 491 | ], 492 | "description": "Yii PHP Framework Version 2", 493 | "homepage": "http://www.yiiframework.com/", 494 | "keywords": [ 495 | "framework", 496 | "yii2" 497 | ], 498 | "time": "2015-07-11 02:37:59" 499 | }, 500 | { 501 | "name": "yiisoft/yii2-bootstrap", 502 | "version": "2.0.4", 503 | "source": { 504 | "type": "git", 505 | "url": "https://github.com/yiisoft/yii2-bootstrap.git", 506 | "reference": "1b6b1e61cf91c3cdd517d6a7e71d30bb212e4af0" 507 | }, 508 | "dist": { 509 | "type": "zip", 510 | "url": "https://api.github.com/repos/yiisoft/yii2-bootstrap/zipball/1b6b1e61cf91c3cdd517d6a7e71d30bb212e4af0", 511 | "reference": "1b6b1e61cf91c3cdd517d6a7e71d30bb212e4af0", 512 | "shasum": "" 513 | }, 514 | "require": { 515 | "bower-asset/bootstrap": "3.3.* | 3.2.* | 3.1.*", 516 | "yiisoft/yii2": ">=2.0.4" 517 | }, 518 | "type": "yii2-extension", 519 | "extra": { 520 | "branch-alias": { 521 | "dev-master": "2.0.x-dev" 522 | }, 523 | "asset-installer-paths": { 524 | "npm-asset-library": "vendor/npm", 525 | "bower-asset-library": "vendor/bower" 526 | } 527 | }, 528 | "autoload": { 529 | "psr-4": { 530 | "yii\\bootstrap\\": "" 531 | } 532 | }, 533 | "notification-url": "https://packagist.org/downloads/", 534 | "license": [ 535 | "BSD-3-Clause" 536 | ], 537 | "authors": [ 538 | { 539 | "name": "Qiang Xue", 540 | "email": "qiang.xue@gmail.com" 541 | } 542 | ], 543 | "description": "The Twitter Bootstrap extension for the Yii framework", 544 | "keywords": [ 545 | "bootstrap", 546 | "yii2" 547 | ], 548 | "time": "2015-05-10 22:08:17" 549 | }, 550 | { 551 | "name": "yiisoft/yii2-composer", 552 | "version": "2.0.3", 553 | "source": { 554 | "type": "git", 555 | "url": "https://github.com/yiisoft/yii2-composer.git", 556 | "reference": "ca8d23707ae47d20b0454e4b135c156f6da6d7be" 557 | }, 558 | "dist": { 559 | "type": "zip", 560 | "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/ca8d23707ae47d20b0454e4b135c156f6da6d7be", 561 | "reference": "ca8d23707ae47d20b0454e4b135c156f6da6d7be", 562 | "shasum": "" 563 | }, 564 | "require": { 565 | "composer-plugin-api": "1.0.0" 566 | }, 567 | "type": "composer-plugin", 568 | "extra": { 569 | "class": "yii\\composer\\Plugin", 570 | "branch-alias": { 571 | "dev-master": "2.0.x-dev" 572 | } 573 | }, 574 | "autoload": { 575 | "psr-4": { 576 | "yii\\composer\\": "" 577 | } 578 | }, 579 | "notification-url": "https://packagist.org/downloads/", 580 | "license": [ 581 | "BSD-3-Clause" 582 | ], 583 | "authors": [ 584 | { 585 | "name": "Qiang Xue", 586 | "email": "qiang.xue@gmail.com" 587 | } 588 | ], 589 | "description": "The composer plugin for Yii extension installer", 590 | "keywords": [ 591 | "composer", 592 | "extension installer", 593 | "yii2" 594 | ], 595 | "time": "2015-03-01 06:22:44" 596 | } 597 | ], 598 | "packages-dev": [ 599 | { 600 | "name": "codeception/c3", 601 | "version": "2.0.3", 602 | "source": { 603 | "type": "git", 604 | "url": "https://github.com/Codeception/c3.git", 605 | "reference": "30321efb2421c5d201d02e2cb8da1a1ca96e4a38" 606 | }, 607 | "dist": { 608 | "type": "zip", 609 | "url": "https://api.github.com/repos/Codeception/c3/zipball/30321efb2421c5d201d02e2cb8da1a1ca96e4a38", 610 | "reference": "30321efb2421c5d201d02e2cb8da1a1ca96e4a38", 611 | "shasum": "" 612 | }, 613 | "require": { 614 | "php": ">=5.4.0" 615 | }, 616 | "type": "library", 617 | "autoload": { 618 | "psr-4": { 619 | "Codeception\\c3\\": "." 620 | } 621 | }, 622 | "notification-url": "https://packagist.org/downloads/", 623 | "license": [ 624 | "MIT" 625 | ], 626 | "authors": [ 627 | { 628 | "name": "Michael Bodnarchuk", 629 | "email": "davert.php@resend.cc", 630 | "homepage": "http://codegyre.com" 631 | } 632 | ], 633 | "description": "CodeCoverage collector for Codeception", 634 | "homepage": "http://codeception.com/", 635 | "keywords": [ 636 | "code coverage", 637 | "codecoverage" 638 | ], 639 | "time": "2014-11-18 22:06:45" 640 | }, 641 | { 642 | "name": "codeception/specify", 643 | "version": "0.4.1", 644 | "source": { 645 | "type": "git", 646 | "url": "https://github.com/Codeception/Specify.git", 647 | "reference": "0c0ae07adfc231115b3b72ade22f44c23c199ded" 648 | }, 649 | "dist": { 650 | "type": "zip", 651 | "url": "https://api.github.com/repos/Codeception/Specify/zipball/0c0ae07adfc231115b3b72ade22f44c23c199ded", 652 | "reference": "0c0ae07adfc231115b3b72ade22f44c23c199ded", 653 | "shasum": "" 654 | }, 655 | "require": { 656 | "myclabs/deep-copy": "~1.1", 657 | "php": ">=5.4.0" 658 | }, 659 | "require-dev": { 660 | "phpunit/phpunit": "~4.0" 661 | }, 662 | "type": "library", 663 | "autoload": { 664 | "psr-0": { 665 | "Codeception\\": "src/" 666 | } 667 | }, 668 | "notification-url": "https://packagist.org/downloads/", 669 | "authors": [ 670 | { 671 | "name": "Michael Bodnarchuk", 672 | "email": "davert.php@mailican.com" 673 | } 674 | ], 675 | "description": "BDD code blocks for PHPUnit and Codeception", 676 | "time": "2014-10-17 00:06:51" 677 | }, 678 | { 679 | "name": "codeception/verify", 680 | "version": "0.2.7", 681 | "source": { 682 | "type": "git", 683 | "url": "https://github.com/Codeception/Verify.git", 684 | "reference": "66e5074905f4d9590ddb805d123fe632f4baa488" 685 | }, 686 | "dist": { 687 | "type": "zip", 688 | "url": "https://api.github.com/repos/Codeception/Verify/zipball/66e5074905f4d9590ddb805d123fe632f4baa488", 689 | "reference": "66e5074905f4d9590ddb805d123fe632f4baa488", 690 | "shasum": "" 691 | }, 692 | "require-dev": { 693 | "phpunit/phpunit": "3.7.*" 694 | }, 695 | "type": "library", 696 | "autoload": { 697 | "files": [ 698 | "src/Codeception/function.php" 699 | ] 700 | }, 701 | "notification-url": "https://packagist.org/downloads/", 702 | "authors": [ 703 | { 704 | "name": "Michael Bodnarchuk", 705 | "email": "davert.php@mailican.com", 706 | "homepage": "http://codeception.com" 707 | } 708 | ], 709 | "description": "BDD assertion library for PHPUnit", 710 | "time": "2014-01-22 14:40:33" 711 | }, 712 | { 713 | "name": "doctrine/annotations", 714 | "version": "v1.2.6", 715 | "source": { 716 | "type": "git", 717 | "url": "https://github.com/doctrine/annotations.git", 718 | "reference": "f4a91702ca3cd2e568c3736aa031ed00c3752af4" 719 | }, 720 | "dist": { 721 | "type": "zip", 722 | "url": "https://api.github.com/repos/doctrine/annotations/zipball/f4a91702ca3cd2e568c3736aa031ed00c3752af4", 723 | "reference": "f4a91702ca3cd2e568c3736aa031ed00c3752af4", 724 | "shasum": "" 725 | }, 726 | "require": { 727 | "doctrine/lexer": "1.*", 728 | "php": ">=5.3.2" 729 | }, 730 | "require-dev": { 731 | "doctrine/cache": "1.*", 732 | "phpunit/phpunit": "4.*" 733 | }, 734 | "type": "library", 735 | "extra": { 736 | "branch-alias": { 737 | "dev-master": "1.3.x-dev" 738 | } 739 | }, 740 | "autoload": { 741 | "psr-0": { 742 | "Doctrine\\Common\\Annotations\\": "lib/" 743 | } 744 | }, 745 | "notification-url": "https://packagist.org/downloads/", 746 | "license": [ 747 | "MIT" 748 | ], 749 | "authors": [ 750 | { 751 | "name": "Roman Borschel", 752 | "email": "roman@code-factory.org" 753 | }, 754 | { 755 | "name": "Benjamin Eberlei", 756 | "email": "kontakt@beberlei.de" 757 | }, 758 | { 759 | "name": "Guilherme Blanco", 760 | "email": "guilhermeblanco@gmail.com" 761 | }, 762 | { 763 | "name": "Jonathan Wage", 764 | "email": "jonwage@gmail.com" 765 | }, 766 | { 767 | "name": "Johannes Schmitt", 768 | "email": "schmittjoh@gmail.com" 769 | } 770 | ], 771 | "description": "Docblock Annotations Parser", 772 | "homepage": "http://www.doctrine-project.org", 773 | "keywords": [ 774 | "annotations", 775 | "docblock", 776 | "parser" 777 | ], 778 | "time": "2015-06-17 12:21:22" 779 | }, 780 | { 781 | "name": "doctrine/lexer", 782 | "version": "v1.0.1", 783 | "source": { 784 | "type": "git", 785 | "url": "https://github.com/doctrine/lexer.git", 786 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" 787 | }, 788 | "dist": { 789 | "type": "zip", 790 | "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", 791 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", 792 | "shasum": "" 793 | }, 794 | "require": { 795 | "php": ">=5.3.2" 796 | }, 797 | "type": "library", 798 | "extra": { 799 | "branch-alias": { 800 | "dev-master": "1.0.x-dev" 801 | } 802 | }, 803 | "autoload": { 804 | "psr-0": { 805 | "Doctrine\\Common\\Lexer\\": "lib/" 806 | } 807 | }, 808 | "notification-url": "https://packagist.org/downloads/", 809 | "license": [ 810 | "MIT" 811 | ], 812 | "authors": [ 813 | { 814 | "name": "Roman Borschel", 815 | "email": "roman@code-factory.org" 816 | }, 817 | { 818 | "name": "Guilherme Blanco", 819 | "email": "guilhermeblanco@gmail.com" 820 | }, 821 | { 822 | "name": "Johannes Schmitt", 823 | "email": "schmittjoh@gmail.com" 824 | } 825 | ], 826 | "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", 827 | "homepage": "http://www.doctrine-project.org", 828 | "keywords": [ 829 | "lexer", 830 | "parser" 831 | ], 832 | "time": "2014-09-09 13:34:57" 833 | }, 834 | { 835 | "name": "fxp/composer-asset-plugin", 836 | "version": "v1.0.2", 837 | "source": { 838 | "type": "git", 839 | "url": "https://github.com/francoispluchino/composer-asset-plugin.git", 840 | "reference": "c37a7ef0e253633ae0bdf29643129add73dfae71" 841 | }, 842 | "dist": { 843 | "type": "zip", 844 | "url": "https://api.github.com/repos/francoispluchino/composer-asset-plugin/zipball/c37a7ef0e253633ae0bdf29643129add73dfae71", 845 | "reference": "c37a7ef0e253633ae0bdf29643129add73dfae71", 846 | "shasum": "" 847 | }, 848 | "require": { 849 | "composer-plugin-api": "1.0.0", 850 | "php": ">=5.3.3" 851 | }, 852 | "require-dev": { 853 | "composer/composer": "~1.0@dev" 854 | }, 855 | "type": "composer-plugin", 856 | "extra": { 857 | "class": "Fxp\\Composer\\AssetPlugin\\FxpAssetPlugin", 858 | "branch-alias": { 859 | "dev-master": "1.0-dev" 860 | } 861 | }, 862 | "autoload": { 863 | "psr-4": { 864 | "Fxp\\Composer\\AssetPlugin\\": "" 865 | } 866 | }, 867 | "notification-url": "https://packagist.org/downloads/", 868 | "license": [ 869 | "MIT" 870 | ], 871 | "authors": [ 872 | { 873 | "name": "François Pluchino", 874 | "email": "francois.pluchino@gmail.com" 875 | } 876 | ], 877 | "description": "NPM/Bower Dependency Manager for Composer", 878 | "homepage": "https://github.com/francoispluchino/composer-asset-plugin", 879 | "keywords": [ 880 | "asset", 881 | "bower", 882 | "composer", 883 | "dependency manager", 884 | "nodejs", 885 | "npm", 886 | "package" 887 | ], 888 | "time": "2015-06-04 10:37:32" 889 | }, 890 | { 891 | "name": "guzzle/guzzle", 892 | "version": "v3.9.3", 893 | "source": { 894 | "type": "git", 895 | "url": "https://github.com/guzzle/guzzle3.git", 896 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" 897 | }, 898 | "dist": { 899 | "type": "zip", 900 | "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", 901 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", 902 | "shasum": "" 903 | }, 904 | "require": { 905 | "ext-curl": "*", 906 | "php": ">=5.3.3", 907 | "symfony/event-dispatcher": "~2.1" 908 | }, 909 | "replace": { 910 | "guzzle/batch": "self.version", 911 | "guzzle/cache": "self.version", 912 | "guzzle/common": "self.version", 913 | "guzzle/http": "self.version", 914 | "guzzle/inflection": "self.version", 915 | "guzzle/iterator": "self.version", 916 | "guzzle/log": "self.version", 917 | "guzzle/parser": "self.version", 918 | "guzzle/plugin": "self.version", 919 | "guzzle/plugin-async": "self.version", 920 | "guzzle/plugin-backoff": "self.version", 921 | "guzzle/plugin-cache": "self.version", 922 | "guzzle/plugin-cookie": "self.version", 923 | "guzzle/plugin-curlauth": "self.version", 924 | "guzzle/plugin-error-response": "self.version", 925 | "guzzle/plugin-history": "self.version", 926 | "guzzle/plugin-log": "self.version", 927 | "guzzle/plugin-md5": "self.version", 928 | "guzzle/plugin-mock": "self.version", 929 | "guzzle/plugin-oauth": "self.version", 930 | "guzzle/service": "self.version", 931 | "guzzle/stream": "self.version" 932 | }, 933 | "require-dev": { 934 | "doctrine/cache": "~1.3", 935 | "monolog/monolog": "~1.0", 936 | "phpunit/phpunit": "3.7.*", 937 | "psr/log": "~1.0", 938 | "symfony/class-loader": "~2.1", 939 | "zendframework/zend-cache": "2.*,<2.3", 940 | "zendframework/zend-log": "2.*,<2.3" 941 | }, 942 | "suggest": { 943 | "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." 944 | }, 945 | "type": "library", 946 | "extra": { 947 | "branch-alias": { 948 | "dev-master": "3.9-dev" 949 | } 950 | }, 951 | "autoload": { 952 | "psr-0": { 953 | "Guzzle": "src/", 954 | "Guzzle\\Tests": "tests/" 955 | } 956 | }, 957 | "notification-url": "https://packagist.org/downloads/", 958 | "license": [ 959 | "MIT" 960 | ], 961 | "authors": [ 962 | { 963 | "name": "Michael Dowling", 964 | "email": "mtdowling@gmail.com", 965 | "homepage": "https://github.com/mtdowling" 966 | }, 967 | { 968 | "name": "Guzzle Community", 969 | "homepage": "https://github.com/guzzle/guzzle/contributors" 970 | } 971 | ], 972 | "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", 973 | "homepage": "http://guzzlephp.org/", 974 | "keywords": [ 975 | "client", 976 | "curl", 977 | "framework", 978 | "http", 979 | "http client", 980 | "rest", 981 | "web service" 982 | ], 983 | "time": "2015-03-18 18:23:50" 984 | }, 985 | { 986 | "name": "heroku/heroku-buildpack-php", 987 | "version": "v71", 988 | "source": { 989 | "type": "git", 990 | "url": "https://github.com/heroku/heroku-buildpack-php.git", 991 | "reference": "115ddf16d45cff621961d8dd57e14ba1ff1e41dd" 992 | }, 993 | "dist": { 994 | "type": "zip", 995 | "url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/115ddf16d45cff621961d8dd57e14ba1ff1e41dd", 996 | "reference": "115ddf16d45cff621961d8dd57e14ba1ff1e41dd", 997 | "shasum": "" 998 | }, 999 | "bin": [ 1000 | "bin/heroku-hhvm-apache2", 1001 | "bin/heroku-hhvm-nginx", 1002 | "bin/heroku-php-apache2", 1003 | "bin/heroku-php-nginx" 1004 | ], 1005 | "type": "library", 1006 | "notification-url": "https://packagist.org/downloads/", 1007 | "license": [ 1008 | "MIT" 1009 | ], 1010 | "authors": [ 1011 | { 1012 | "name": "David Zuelke", 1013 | "email": "dz@heroku.com" 1014 | } 1015 | ], 1016 | "description": "Toolkit for starting a PHP application locally, with or without foreman, using the same config for PHP/HHVM and Apache2/Nginx as on Heroku", 1017 | "homepage": "http://github.com/heroku/heroku-buildpack-php", 1018 | "keywords": [ 1019 | "apache", 1020 | "apache2", 1021 | "foreman", 1022 | "heroku", 1023 | "hhvm", 1024 | "nginx", 1025 | "php" 1026 | ], 1027 | "time": "2015-07-14 00:38:23" 1028 | }, 1029 | { 1030 | "name": "jms/metadata", 1031 | "version": "1.5.1", 1032 | "source": { 1033 | "type": "git", 1034 | "url": "https://github.com/schmittjoh/metadata.git", 1035 | "reference": "22b72455559a25777cfd28c4ffda81ff7639f353" 1036 | }, 1037 | "dist": { 1038 | "type": "zip", 1039 | "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/22b72455559a25777cfd28c4ffda81ff7639f353", 1040 | "reference": "22b72455559a25777cfd28c4ffda81ff7639f353", 1041 | "shasum": "" 1042 | }, 1043 | "require": { 1044 | "php": ">=5.3.0" 1045 | }, 1046 | "require-dev": { 1047 | "doctrine/cache": "~1.0" 1048 | }, 1049 | "type": "library", 1050 | "extra": { 1051 | "branch-alias": { 1052 | "dev-master": "1.5.x-dev" 1053 | } 1054 | }, 1055 | "autoload": { 1056 | "psr-0": { 1057 | "Metadata\\": "src/" 1058 | } 1059 | }, 1060 | "notification-url": "https://packagist.org/downloads/", 1061 | "license": [ 1062 | "Apache" 1063 | ], 1064 | "authors": [ 1065 | { 1066 | "name": "Johannes Schmitt", 1067 | "email": "schmittjoh@gmail.com", 1068 | "homepage": "https://github.com/schmittjoh", 1069 | "role": "Developer of wrapped JMSSerializerBundle" 1070 | } 1071 | ], 1072 | "description": "Class/method/property metadata management in PHP", 1073 | "keywords": [ 1074 | "annotations", 1075 | "metadata", 1076 | "xml", 1077 | "yaml" 1078 | ], 1079 | "time": "2014-07-12 07:13:19" 1080 | }, 1081 | { 1082 | "name": "jms/parser-lib", 1083 | "version": "1.0.0", 1084 | "source": { 1085 | "type": "git", 1086 | "url": "https://github.com/schmittjoh/parser-lib.git", 1087 | "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d" 1088 | }, 1089 | "dist": { 1090 | "type": "zip", 1091 | "url": "https://api.github.com/repos/schmittjoh/parser-lib/zipball/c509473bc1b4866415627af0e1c6cc8ac97fa51d", 1092 | "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d", 1093 | "shasum": "" 1094 | }, 1095 | "require": { 1096 | "phpoption/phpoption": ">=0.9,<2.0-dev" 1097 | }, 1098 | "type": "library", 1099 | "extra": { 1100 | "branch-alias": { 1101 | "dev-master": "1.0-dev" 1102 | } 1103 | }, 1104 | "autoload": { 1105 | "psr-0": { 1106 | "JMS\\": "src/" 1107 | } 1108 | }, 1109 | "notification-url": "https://packagist.org/downloads/", 1110 | "license": [ 1111 | "Apache2" 1112 | ], 1113 | "description": "A library for easily creating recursive-descent parsers.", 1114 | "time": "2012-11-18 18:08:43" 1115 | }, 1116 | { 1117 | "name": "jms/serializer", 1118 | "version": "0.16.0", 1119 | "source": { 1120 | "type": "git", 1121 | "url": "https://github.com/schmittjoh/serializer.git", 1122 | "reference": "c8a171357ca92b6706e395c757f334902d430ea9" 1123 | }, 1124 | "dist": { 1125 | "type": "zip", 1126 | "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/c8a171357ca92b6706e395c757f334902d430ea9", 1127 | "reference": "c8a171357ca92b6706e395c757f334902d430ea9", 1128 | "shasum": "" 1129 | }, 1130 | "require": { 1131 | "doctrine/annotations": "1.*", 1132 | "jms/metadata": "~1.1", 1133 | "jms/parser-lib": "1.*", 1134 | "php": ">=5.3.2", 1135 | "phpcollection/phpcollection": "~0.1" 1136 | }, 1137 | "require-dev": { 1138 | "doctrine/orm": "~2.1", 1139 | "doctrine/phpcr-odm": "~1.0.1", 1140 | "jackalope/jackalope-doctrine-dbal": "1.0.*", 1141 | "propel/propel1": "~1.7", 1142 | "symfony/filesystem": "2.*", 1143 | "symfony/form": "~2.1", 1144 | "symfony/translation": "~2.0", 1145 | "symfony/validator": "~2.0", 1146 | "symfony/yaml": "2.*", 1147 | "twig/twig": ">=1.8,<2.0-dev" 1148 | }, 1149 | "suggest": { 1150 | "symfony/yaml": "Required if you'd like to serialize data to YAML format." 1151 | }, 1152 | "type": "library", 1153 | "extra": { 1154 | "branch-alias": { 1155 | "dev-master": "0.15-dev" 1156 | } 1157 | }, 1158 | "autoload": { 1159 | "psr-0": { 1160 | "JMS\\Serializer": "src/" 1161 | } 1162 | }, 1163 | "notification-url": "https://packagist.org/downloads/", 1164 | "license": [ 1165 | "Apache2" 1166 | ], 1167 | "authors": [ 1168 | { 1169 | "name": "Johannes Schmitt", 1170 | "email": "schmittjoh@gmail.com", 1171 | "homepage": "https://github.com/schmittjoh", 1172 | "role": "Developer of wrapped JMSSerializerBundle" 1173 | } 1174 | ], 1175 | "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.", 1176 | "homepage": "http://jmsyst.com/libs/serializer", 1177 | "keywords": [ 1178 | "deserialization", 1179 | "jaxb", 1180 | "json", 1181 | "serialization", 1182 | "xml" 1183 | ], 1184 | "time": "2014-03-18 08:39:00" 1185 | }, 1186 | { 1187 | "name": "myclabs/deep-copy", 1188 | "version": "1.3.0", 1189 | "source": { 1190 | "type": "git", 1191 | "url": "https://github.com/myclabs/DeepCopy.git", 1192 | "reference": "96fbdc07635989c35c5a1912379f4c4b2ab15fd5" 1193 | }, 1194 | "dist": { 1195 | "type": "zip", 1196 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/96fbdc07635989c35c5a1912379f4c4b2ab15fd5", 1197 | "reference": "96fbdc07635989c35c5a1912379f4c4b2ab15fd5", 1198 | "shasum": "" 1199 | }, 1200 | "require": { 1201 | "php": ">=5.4.0" 1202 | }, 1203 | "require-dev": { 1204 | "doctrine/collections": "1.*", 1205 | "phpunit/phpunit": "~4.1" 1206 | }, 1207 | "type": "library", 1208 | "autoload": { 1209 | "psr-4": { 1210 | "DeepCopy\\": "src/DeepCopy/" 1211 | } 1212 | }, 1213 | "notification-url": "https://packagist.org/downloads/", 1214 | "license": [ 1215 | "MIT" 1216 | ], 1217 | "description": "Create deep copies (clones) of your objects", 1218 | "homepage": "https://github.com/myclabs/DeepCopy", 1219 | "keywords": [ 1220 | "clone", 1221 | "copy", 1222 | "duplicate", 1223 | "object", 1224 | "object graph" 1225 | ], 1226 | "time": "2015-03-21 22:40:23" 1227 | }, 1228 | { 1229 | "name": "phpcollection/phpcollection", 1230 | "version": "0.4.0", 1231 | "source": { 1232 | "type": "git", 1233 | "url": "https://github.com/schmittjoh/php-collection.git", 1234 | "reference": "b8bf55a0a929ca43b01232b36719f176f86c7e83" 1235 | }, 1236 | "dist": { 1237 | "type": "zip", 1238 | "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/b8bf55a0a929ca43b01232b36719f176f86c7e83", 1239 | "reference": "b8bf55a0a929ca43b01232b36719f176f86c7e83", 1240 | "shasum": "" 1241 | }, 1242 | "require": { 1243 | "phpoption/phpoption": "1.*" 1244 | }, 1245 | "type": "library", 1246 | "extra": { 1247 | "branch-alias": { 1248 | "dev-master": "0.3-dev" 1249 | } 1250 | }, 1251 | "autoload": { 1252 | "psr-0": { 1253 | "PhpCollection": "src/" 1254 | } 1255 | }, 1256 | "notification-url": "https://packagist.org/downloads/", 1257 | "license": [ 1258 | "Apache2" 1259 | ], 1260 | "authors": [ 1261 | { 1262 | "name": "Johannes Schmitt", 1263 | "email": "schmittjoh@gmail.com", 1264 | "homepage": "https://github.com/schmittjoh", 1265 | "role": "Developer of wrapped JMSSerializerBundle" 1266 | } 1267 | ], 1268 | "description": "General-Purpose Collection Library for PHP", 1269 | "keywords": [ 1270 | "collection", 1271 | "list", 1272 | "map", 1273 | "sequence", 1274 | "set" 1275 | ], 1276 | "time": "2014-03-11 13:46:42" 1277 | }, 1278 | { 1279 | "name": "phpoption/phpoption", 1280 | "version": "1.4.0", 1281 | "source": { 1282 | "type": "git", 1283 | "url": "https://github.com/schmittjoh/php-option.git", 1284 | "reference": "5d099bcf0393908bf4ad69cc47dafb785d51f7f5" 1285 | }, 1286 | "dist": { 1287 | "type": "zip", 1288 | "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/5d099bcf0393908bf4ad69cc47dafb785d51f7f5", 1289 | "reference": "5d099bcf0393908bf4ad69cc47dafb785d51f7f5", 1290 | "shasum": "" 1291 | }, 1292 | "require": { 1293 | "php": ">=5.3.0" 1294 | }, 1295 | "type": "library", 1296 | "extra": { 1297 | "branch-alias": { 1298 | "dev-master": "1.3-dev" 1299 | } 1300 | }, 1301 | "autoload": { 1302 | "psr-0": { 1303 | "PhpOption\\": "src/" 1304 | } 1305 | }, 1306 | "notification-url": "https://packagist.org/downloads/", 1307 | "license": [ 1308 | "Apache2" 1309 | ], 1310 | "authors": [ 1311 | { 1312 | "name": "Johannes Schmitt", 1313 | "email": "schmittjoh@gmail.com", 1314 | "homepage": "https://github.com/schmittjoh", 1315 | "role": "Developer of wrapped JMSSerializerBundle" 1316 | } 1317 | ], 1318 | "description": "Option Type for PHP", 1319 | "keywords": [ 1320 | "language", 1321 | "option", 1322 | "php", 1323 | "type" 1324 | ], 1325 | "time": "2014-01-09 22:37:17" 1326 | }, 1327 | { 1328 | "name": "scrutinizer/ocular", 1329 | "version": "1.1.1", 1330 | "source": { 1331 | "type": "git", 1332 | "url": "https://github.com/scrutinizer-ci/ocular.git", 1333 | "reference": "8e0a8c7f085bc4857bd52132833679dcfd504fc1" 1334 | }, 1335 | "dist": { 1336 | "type": "zip", 1337 | "url": "https://api.github.com/repos/scrutinizer-ci/ocular/zipball/8e0a8c7f085bc4857bd52132833679dcfd504fc1", 1338 | "reference": "8e0a8c7f085bc4857bd52132833679dcfd504fc1", 1339 | "shasum": "" 1340 | }, 1341 | "require": { 1342 | "guzzle/guzzle": "~3.0", 1343 | "jms/serializer": "~0.13", 1344 | "phpoption/phpoption": "~1.0", 1345 | "symfony/console": "~2.0", 1346 | "symfony/process": "~2.3" 1347 | }, 1348 | "require-dev": { 1349 | "symfony/filesystem": "~2.0" 1350 | }, 1351 | "bin": [ 1352 | "bin/ocular" 1353 | ], 1354 | "type": "library", 1355 | "autoload": { 1356 | "psr-0": { 1357 | "Scrutinizer\\Ocular\\": "src/" 1358 | } 1359 | }, 1360 | "notification-url": "https://packagist.org/downloads/", 1361 | "time": "2014-04-12 20:46:35" 1362 | }, 1363 | { 1364 | "name": "symfony/console", 1365 | "version": "v2.7.2", 1366 | "source": { 1367 | "type": "git", 1368 | "url": "https://github.com/symfony/Console.git", 1369 | "reference": "8cf484449130cabfd98dcb4694ca9945802a21ed" 1370 | }, 1371 | "dist": { 1372 | "type": "zip", 1373 | "url": "https://api.github.com/repos/symfony/Console/zipball/8cf484449130cabfd98dcb4694ca9945802a21ed", 1374 | "reference": "8cf484449130cabfd98dcb4694ca9945802a21ed", 1375 | "shasum": "" 1376 | }, 1377 | "require": { 1378 | "php": ">=5.3.9" 1379 | }, 1380 | "require-dev": { 1381 | "psr/log": "~1.0", 1382 | "symfony/event-dispatcher": "~2.1", 1383 | "symfony/phpunit-bridge": "~2.7", 1384 | "symfony/process": "~2.1" 1385 | }, 1386 | "suggest": { 1387 | "psr/log": "For using the console logger", 1388 | "symfony/event-dispatcher": "", 1389 | "symfony/process": "" 1390 | }, 1391 | "type": "library", 1392 | "extra": { 1393 | "branch-alias": { 1394 | "dev-master": "2.7-dev" 1395 | } 1396 | }, 1397 | "autoload": { 1398 | "psr-4": { 1399 | "Symfony\\Component\\Console\\": "" 1400 | } 1401 | }, 1402 | "notification-url": "https://packagist.org/downloads/", 1403 | "license": [ 1404 | "MIT" 1405 | ], 1406 | "authors": [ 1407 | { 1408 | "name": "Fabien Potencier", 1409 | "email": "fabien@symfony.com" 1410 | }, 1411 | { 1412 | "name": "Symfony Community", 1413 | "homepage": "https://symfony.com/contributors" 1414 | } 1415 | ], 1416 | "description": "Symfony Console Component", 1417 | "homepage": "https://symfony.com", 1418 | "time": "2015-07-09 16:07:40" 1419 | }, 1420 | { 1421 | "name": "symfony/event-dispatcher", 1422 | "version": "v2.7.2", 1423 | "source": { 1424 | "type": "git", 1425 | "url": "https://github.com/symfony/EventDispatcher.git", 1426 | "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3" 1427 | }, 1428 | "dist": { 1429 | "type": "zip", 1430 | "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/9310b5f9a87ec2ea75d20fec0b0017c77c66dac3", 1431 | "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3", 1432 | "shasum": "" 1433 | }, 1434 | "require": { 1435 | "php": ">=5.3.9" 1436 | }, 1437 | "require-dev": { 1438 | "psr/log": "~1.0", 1439 | "symfony/config": "~2.0,>=2.0.5", 1440 | "symfony/dependency-injection": "~2.6", 1441 | "symfony/expression-language": "~2.6", 1442 | "symfony/phpunit-bridge": "~2.7", 1443 | "symfony/stopwatch": "~2.3" 1444 | }, 1445 | "suggest": { 1446 | "symfony/dependency-injection": "", 1447 | "symfony/http-kernel": "" 1448 | }, 1449 | "type": "library", 1450 | "extra": { 1451 | "branch-alias": { 1452 | "dev-master": "2.7-dev" 1453 | } 1454 | }, 1455 | "autoload": { 1456 | "psr-4": { 1457 | "Symfony\\Component\\EventDispatcher\\": "" 1458 | } 1459 | }, 1460 | "notification-url": "https://packagist.org/downloads/", 1461 | "license": [ 1462 | "MIT" 1463 | ], 1464 | "authors": [ 1465 | { 1466 | "name": "Fabien Potencier", 1467 | "email": "fabien@symfony.com" 1468 | }, 1469 | { 1470 | "name": "Symfony Community", 1471 | "homepage": "https://symfony.com/contributors" 1472 | } 1473 | ], 1474 | "description": "Symfony EventDispatcher Component", 1475 | "homepage": "https://symfony.com", 1476 | "time": "2015-06-18 19:21:56" 1477 | }, 1478 | { 1479 | "name": "symfony/process", 1480 | "version": "v2.7.2", 1481 | "source": { 1482 | "type": "git", 1483 | "url": "https://github.com/symfony/Process.git", 1484 | "reference": "48aeb0e48600321c272955132d7606ab0a49adb3" 1485 | }, 1486 | "dist": { 1487 | "type": "zip", 1488 | "url": "https://api.github.com/repos/symfony/Process/zipball/48aeb0e48600321c272955132d7606ab0a49adb3", 1489 | "reference": "48aeb0e48600321c272955132d7606ab0a49adb3", 1490 | "shasum": "" 1491 | }, 1492 | "require": { 1493 | "php": ">=5.3.9" 1494 | }, 1495 | "require-dev": { 1496 | "symfony/phpunit-bridge": "~2.7" 1497 | }, 1498 | "type": "library", 1499 | "extra": { 1500 | "branch-alias": { 1501 | "dev-master": "2.7-dev" 1502 | } 1503 | }, 1504 | "autoload": { 1505 | "psr-4": { 1506 | "Symfony\\Component\\Process\\": "" 1507 | } 1508 | }, 1509 | "notification-url": "https://packagist.org/downloads/", 1510 | "license": [ 1511 | "MIT" 1512 | ], 1513 | "authors": [ 1514 | { 1515 | "name": "Fabien Potencier", 1516 | "email": "fabien@symfony.com" 1517 | }, 1518 | { 1519 | "name": "Symfony Community", 1520 | "homepage": "https://symfony.com/contributors" 1521 | } 1522 | ], 1523 | "description": "Symfony Process Component", 1524 | "homepage": "https://symfony.com", 1525 | "time": "2015-07-01 11:25:50" 1526 | }, 1527 | { 1528 | "name": "yiisoft/yii2-codeception", 1529 | "version": "2.0.4", 1530 | "source": { 1531 | "type": "git", 1532 | "url": "https://github.com/yiisoft/yii2-codeception.git", 1533 | "reference": "de5007e7a99359597abbfe1c88dca3ce620061c5" 1534 | }, 1535 | "dist": { 1536 | "type": "zip", 1537 | "url": "https://api.github.com/repos/yiisoft/yii2-codeception/zipball/de5007e7a99359597abbfe1c88dca3ce620061c5", 1538 | "reference": "de5007e7a99359597abbfe1c88dca3ce620061c5", 1539 | "shasum": "" 1540 | }, 1541 | "require": { 1542 | "yiisoft/yii2": ">=2.0.4" 1543 | }, 1544 | "type": "yii2-extension", 1545 | "extra": { 1546 | "branch-alias": { 1547 | "dev-master": "2.0.x-dev" 1548 | } 1549 | }, 1550 | "autoload": { 1551 | "psr-4": { 1552 | "yii\\codeception\\": "" 1553 | } 1554 | }, 1555 | "notification-url": "https://packagist.org/downloads/", 1556 | "license": [ 1557 | "BSD-3-Clause" 1558 | ], 1559 | "authors": [ 1560 | { 1561 | "name": "Mark Jebri", 1562 | "email": "mark.github@yandex.ru" 1563 | } 1564 | ], 1565 | "description": "The Codeception integration for the Yii framework", 1566 | "keywords": [ 1567 | "codeception", 1568 | "yii2" 1569 | ], 1570 | "time": "2015-05-10 22:08:30" 1571 | } 1572 | ], 1573 | "aliases": [], 1574 | "minimum-stability": "stable", 1575 | "stability-flags": [], 1576 | "prefer-stable": false, 1577 | "prefer-lowest": false, 1578 | "platform": { 1579 | "php": ">=5.4.0" 1580 | }, 1581 | "platform-dev": [] 1582 | } 1583 | -------------------------------------------------------------------------------- /heroku.md: -------------------------------------------------------------------------------- 1 | # Heroku 2 | 3 | ## Git 4 | 5 | Add remote: 6 | ``` 7 | git remote add heroku https://git.heroku.com/yii2-dashboard.git 8 | ``` 9 | 10 | Push changes: 11 | ``` 12 | git push heroku master 13 | ``` 14 | 15 | ## Migrate 16 | 17 | ``` 18 | heroku run php /app/tests/codeception/_app/yii migrate/up --interactive=0 19 | heroku run php /app/tests/codeception/_app/yii migrate/up --migrationPath=/app/src/migrations --interactive=0 20 | ``` 21 | 22 | ## Helpful Commands 23 | 24 | Interactive shell: 25 | ``` 26 | heroku run bash 27 | ``` 28 | 29 | Watch logs: 30 | ``` 31 | heroku logs --tail 32 | ``` 33 | 34 | Set and unset config var: 35 | ``` 36 | heroku config:set SOME_CONFIG=foobar 37 | heroku config:unset SOME_CONFIG 38 | ``` 39 | 40 | Get config vars: 41 | ``` 42 | heroku config 43 | ``` 44 | 45 | Database console: 46 | ``` 47 | apt-get install postgresql-client 48 | heroku pg:psql 49 | ``` 50 | 51 | Reset database: 52 | ``` 53 | heroku pg:reset DATABASE 54 | ``` 55 | 56 | ## Useful Links 57 | 58 | - https://devcenter.heroku.com/articles/getting-started-with-php -------------------------------------------------------------------------------- /src/ActiveRecord.php: -------------------------------------------------------------------------------- 1 | getDb(); 28 | } 29 | 30 | /** 31 | * @param bool $insert 32 | * @return bool 33 | */ 34 | public function beforeSave($insert) 35 | { 36 | if ($this->autoEncode) 37 | foreach ($this->encodeAttributes as $attribute) 38 | if ($this->hasAttribute($attribute)) 39 | $this->$attribute = json_encode($this->$attribute); 40 | 41 | return parent::beforeSave($insert); 42 | } 43 | 44 | /** 45 | * @param bool $insert 46 | * @param array $changedAttributes 47 | */ 48 | public function afterSave($insert, $changedAttributes) 49 | { 50 | parent::afterSave($insert, $changedAttributes); 51 | 52 | if ($this->autoEncode) 53 | foreach ($this->encodeAttributes as $attribute) 54 | if ($this->hasAttribute($attribute)) 55 | $this->$attribute = json_decode($this->$attribute, true); 56 | } 57 | 58 | /** 59 | * 60 | */ 61 | public function afterFind() 62 | { 63 | parent::afterFind(); 64 | 65 | if ($this->autoEncode) 66 | foreach ($this->encodeAttributes as $attribute) 67 | if ($this->hasAttribute($attribute)) 68 | $this->$attribute = json_decode($this->$attribute, true); 69 | } 70 | } -------------------------------------------------------------------------------- /src/Bootstrap.php: -------------------------------------------------------------------------------- 1 | has('i18n')) { 24 | $app->i18n->translations['dashboard'] = [ 25 | 'class' => 'yii\i18n\PhpMessageSource', 26 | 'sourceLanguage' => 'en', 27 | 'basePath' => '@cornernote/dashboard/messages', 28 | ]; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Layout.php: -------------------------------------------------------------------------------- 1 | dashboard->load($data); 38 | return parent::load($data, $formName); 39 | } 40 | 41 | /** 42 | * @inheritdoc 43 | */ 44 | public function afterValidate() 45 | { 46 | if (!$this->dashboard->validate()) { 47 | $this->addError(null); 48 | } 49 | parent::afterValidate(); 50 | } 51 | 52 | /** 53 | * @return array 54 | */ 55 | public function getOptions() 56 | { 57 | $attributes = []; 58 | foreach ($this->safeAttributes() as $attribute) { 59 | $attributes[$attribute] = $this->$attribute; 60 | } 61 | return $attributes; 62 | } 63 | 64 | /** 65 | * @return array 66 | */ 67 | public function getRegions() 68 | { 69 | return []; 70 | } 71 | 72 | /** 73 | * @param DashboardPanel[] $dashboardPanels 74 | * @param string $view 75 | * @return array 76 | */ 77 | public function regionPanels($dashboardPanels, $view = 'view') 78 | { 79 | $regionPanels = []; 80 | foreach (array_keys($this->getRegions()) as $region) { 81 | $regionPanels[$region] = []; 82 | } 83 | foreach ($dashboardPanels as $dashboardPanel) { 84 | $regionPanels[$dashboardPanel->region][] = [ 85 | 'options' => [ 86 | 'id' => 'dashboard-panel-' . $dashboardPanel->id, 87 | 'class' => 'dashboard-panel', 88 | ], 89 | 'content' => $dashboardPanel->panel->render($view), 90 | ]; 91 | } 92 | return $regionPanels; 93 | } 94 | 95 | /** 96 | * @param string $view 97 | * @param array $params 98 | * @return string 99 | */ 100 | public function render($view, $params = []) 101 | { 102 | $params['layout'] = $this; 103 | return \Yii::$app->view->render($this->viewPath . '/' . $view, $params); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/Module.php: -------------------------------------------------------------------------------- 1 | 'cornernote\dashboard\layouts\DefaultLayout', 40 | ]; 41 | 42 | 43 | public $viewPath; 44 | 45 | /** 46 | * @var array 47 | */ 48 | public $dashboards = []; 49 | 50 | /** 51 | * @var array 52 | */ 53 | public $panels = [ 54 | 'text' => 'cornernote\dashboard\panels\TextPanel', 55 | ]; 56 | 57 | /** 58 | * @var array 59 | */ 60 | public $updateRoles; 61 | 62 | /** 63 | * @return Connection the database connection. 64 | */ 65 | public function getDb() 66 | { 67 | return Yii::$app->{$this->db}; 68 | } 69 | 70 | public function panelsList() 71 | { 72 | $list = []; 73 | foreach ($this->panels as $name => $config) { 74 | if (is_array($config)) { 75 | $list[$config['class']] = $name; 76 | continue; 77 | } 78 | $list[$config] = $name; 79 | } 80 | 81 | return $list; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/Panel.php: -------------------------------------------------------------------------------- 1 | dashboardPanel->load($data); 37 | return parent::load($data, $formName); 38 | } 39 | 40 | /** 41 | * @inheritdoc 42 | */ 43 | public function afterValidate() 44 | { 45 | if (!$this->dashboardPanel->validate()) { 46 | $this->addError(null); 47 | } 48 | parent::afterValidate(); 49 | } 50 | 51 | /** 52 | * @return array 53 | */ 54 | public function getOptions() 55 | { 56 | $attributes = []; 57 | foreach($this->safeAttributes() as $attribute){ 58 | $attributes[$attribute] = $this->$attribute; 59 | } 60 | return $attributes; 61 | } 62 | 63 | /** 64 | * @param string $view 65 | * @param array $params 66 | * @return string 67 | */ 68 | public function render($view, $params = []) 69 | { 70 | $params['panel'] = $this; 71 | return \Yii::$app->view->render($this->viewPath . '/' . $view, $params); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/components/DashboardAccess.php: -------------------------------------------------------------------------------- 1 | user->can($role)) { 36 | return true; 37 | } 38 | } 39 | 40 | return false; 41 | } 42 | 43 | /** 44 | * 45 | * @param string $dashboardName 46 | * @return array 47 | */ 48 | private static function loadAllowRoles($dashboardName) 49 | { 50 | 51 | if (!$panels = Module::getInstance()->dashboards) { 52 | return []; 53 | } 54 | if (!isset($panels[$dashboardName])) { 55 | return []; 56 | } 57 | if (!is_array($panels[$dashboardName])) { 58 | return []; 59 | } 60 | if (!isset($panels[$dashboardName]['allowRoles'])) { 61 | return []; 62 | } 63 | 64 | $viewRoles = $panels[$dashboardName]['allowRoles']; 65 | 66 | if ($updateRoles = Module::getInstance()->updateRoles) { 67 | $viewRoles = array_merge($updateRoles, $viewRoles); 68 | } 69 | 70 | return $viewRoles; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/components/DashboardPanelAccess.php: -------------------------------------------------------------------------------- 1 | user->can($role)) { 36 | return true; 37 | } 38 | } 39 | 40 | return false; 41 | } 42 | 43 | /** 44 | * 45 | * @param string $panelName 46 | * @return array 47 | */ 48 | private static function loadAllowRoles($panelName) 49 | { 50 | 51 | if (!$panels = Module::getInstance()->panels) { 52 | return []; 53 | } 54 | if (!isset($panels[$panelName])) { 55 | return []; 56 | } 57 | if (!is_array($panels[$panelName])) { 58 | return []; 59 | } 60 | if (!isset($panels[$panelName]['allowRoles'])) { 61 | return []; 62 | } 63 | 64 | $viewRoles = $panels[$panelName]['allowRoles']; 65 | 66 | if ($updateRoles = Module::getInstance()->updateRoles) { 67 | $viewRoles = array_merge($updateRoles, $viewRoles); 68 | } 69 | 70 | return $viewRoles; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/controllers/DashboardController.php: -------------------------------------------------------------------------------- 1 | viewPath = Module::getInstance()->viewPath; 24 | 25 | // custom initialization code goes here 26 | } 27 | 28 | /** 29 | * @inheritdoc 30 | */ 31 | public function behaviors() 32 | { 33 | if (!$updateRoles = Module::getInstance()->updateRoles) { 34 | return []; 35 | } 36 | return [ 37 | 'access' => [ 38 | 'class' => AccessControl::className(), 39 | 'rules' => [ 40 | [ 41 | 'allow' => true, 42 | 'actions' => ['view'], 43 | 'roles' => ['@'] 44 | ], 45 | [ 46 | 'allow' => true, 47 | 'actions' => ['index', 'create', 'update', 'delete'], 48 | 'roles' => $updateRoles 49 | ] 50 | ] 51 | ] 52 | ]; 53 | } 54 | 55 | /** 56 | * Lists all Dashboard models. 57 | * @return mixed 58 | */ 59 | public function actionIndex() 60 | { 61 | $searchModel = new DashboardSearch; 62 | $dataProvider = $searchModel->search(Yii::$app->request->get()); 63 | 64 | return $this->render('index', [ 65 | 'dataProvider' => $dataProvider, 66 | 'searchModel' => $searchModel, 67 | ]); 68 | } 69 | 70 | /** 71 | * Displays a single Dashboard model. 72 | * @param string $id 73 | * 74 | * @return mixed 75 | */ 76 | public function actionView($id) 77 | { 78 | if(!$model = $this->findModel($id)){ 79 | return $this->render('empty'); 80 | } 81 | return $this->render('view', compact('model')); 82 | } 83 | 84 | /** 85 | * Creates a new Dashboard model. 86 | * If creation is successful, the browser will be redirected to the 'view' page. 87 | * @return mixed 88 | */ 89 | public function actionCreate() 90 | { 91 | $model = new Dashboard; 92 | //$model->scenario = 'create'; 93 | 94 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 95 | Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Dashboard has been created.')); 96 | return $this->redirect(['update', 'id' => $model->id]); 97 | } 98 | 99 | if (!\Yii::$app->request->isPost) { 100 | $model->load(Yii::$app->request->get()); 101 | } 102 | 103 | return $this->render('create', compact('model')); 104 | } 105 | 106 | /** 107 | * Updates an existing Dashboard model. 108 | * If update is successful, the browser will be redirected to the 'view' page. 109 | * @param string $id 110 | * @return mixed 111 | */ 112 | public function actionUpdate($id) 113 | { 114 | $model = $this->findModel($id); 115 | //$model->scenario = 'update'; 116 | 117 | $data = Yii::$app->request->post(); 118 | if ($data && $model->layout->load($data) && $model->layout->validate()) { 119 | $model->options = $model->layout->getOptions(); 120 | if ($model->save(false)) { 121 | $model->sortPanels($data['DashboardPanelSort']); 122 | Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Dashboard has been updated.')); 123 | return $this->redirect(['dashboard/view', 'id' => $model->id]); 124 | } 125 | } 126 | 127 | 128 | return $this->render('update', compact('model')); 129 | } 130 | 131 | 132 | /** 133 | * Deletes an existing Dashboard model. 134 | * If deletion is successful, the browser will be redirected to the 'index' page. 135 | * @param string $id 136 | * @return mixed 137 | */ 138 | public function actionDelete($id) 139 | { 140 | $this->findModel($id)->delete(); 141 | Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Dashboard has been deleted.')); 142 | 143 | return $this->redirect(['index']); 144 | } 145 | 146 | /** 147 | * 148 | */ 149 | public function actionSort() 150 | { 151 | $sort = Yii::$app->request->post('sort'); 152 | if (!empty($sort)) { 153 | foreach ($sort as $k => $dashboardId) { 154 | $dashboardId = str_replace('dashboard-', '', $dashboardId); 155 | $dashboard = Dashboard::findOne($dashboardId); 156 | if ($dashboard) { 157 | $dashboard->sort = $k; 158 | $dashboard->save(false); 159 | } 160 | } 161 | } 162 | } 163 | 164 | /** 165 | * Finds the Dashboard model based on its primary key value. 166 | * If the model is not found, a 404 HTTP exception will be thrown. 167 | * If defined for dashboard allowRoles, check user access 168 | * @param string $id 169 | * @return Dashboard|false the loaded model 170 | * @throws HttpException if the model cannot be found 171 | */ 172 | protected function findModel($id) 173 | { 174 | if (($model = Dashboard::findOne($id)) !== null) { 175 | 176 | if (!DashboardAccess::userHasAccess($model->name)) { 177 | return false; 178 | } 179 | 180 | return $model; 181 | } 182 | throw new HttpException(404, 'The requested page does not exist.'); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/controllers/DashboardPanelController.php: -------------------------------------------------------------------------------- 1 | updateRoles) { 26 | return []; 27 | } 28 | return [ 29 | 'access' => [ 30 | 'class' => AccessControl::className(), 31 | 'rules' => [ 32 | [ 33 | 'allow' => true, 34 | 'actions' => ['view'], 35 | 'roles' => ['@'] 36 | ], 37 | [ 38 | 'allow' => true, 39 | 'actions' => ['index', 'create', 'update', 'delete'], 40 | 'roles' => $updateRoles 41 | ] 42 | ] 43 | ] 44 | ]; 45 | } 46 | 47 | /** 48 | * Creates a new DashboardPanel model. 49 | * If creation is successful, the browser will be redirected to the 'view' page. 50 | * @return mixed 51 | */ 52 | public function actionCreate() 53 | { 54 | $model = new DashboardPanel; 55 | //$model->scenario = 'create'; 56 | 57 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 58 | Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Dashboard Panel has been created.')); 59 | return $this->redirect(['update', 'id' => $model->id]); 60 | } elseif (!\Yii::$app->request->isPost) { 61 | $model->load(Yii::$app->request->get()); 62 | } 63 | 64 | return $this->render('create', compact('model')); 65 | } 66 | 67 | /** 68 | * Updates an existing DashboardPanel model. 69 | * If update is successful, the browser will be redirected to the 'view' page. 70 | * @param string $id 71 | * @return mixed 72 | */ 73 | public function actionUpdate($id) 74 | { 75 | $model = $this->findModel($id); 76 | //$model->scenario = 'update'; 77 | 78 | $data = Yii::$app->request->post(); 79 | if ($data && $model->panel->load($data) && $model->panel->validate()) { 80 | $model->options = $model->panel->getOptions(); 81 | if ($model->save(false)) { 82 | Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Dashboard Panel has been updated.')); 83 | return $this->redirect(['dashboard/view', 'id' => $model->dashboard->id]); 84 | } 85 | } 86 | 87 | return $this->render('update', compact('model')); 88 | } 89 | 90 | 91 | /** 92 | * Deletes an existing DashboardPanel model. 93 | * If deletion is successful, the browser will be redirected to the 'index' page. 94 | * @param string $id 95 | * @return mixed 96 | */ 97 | public function actionDelete($id) 98 | { 99 | $model = $this->findModel($id); 100 | $model->delete(); 101 | Yii::$app->getSession()->setFlash('success', Yii::t('app', 'Dashboard Panel has been deleted.')); 102 | 103 | return $this->redirect(['dashboard/view', 'id' => $model->dashboard_id]); 104 | } 105 | 106 | /** 107 | * Finds the DashboardPanel model based on its primary key value. 108 | * If the model is not found, a 404 HTTP exception will be thrown. 109 | * If defined for panel allowRoles, check user access 110 | * @param string $id 111 | * @return DashboardPanel the loaded model 112 | * @throws HttpException if the model cannot be found 113 | */ 114 | protected function findModel($id) 115 | { 116 | 117 | if (($model = DashboardPanel::findOne($id)) !== null) { 118 | 119 | if (!DashboardPanelAccess::userHasAccess($model->name)) { 120 | throw new HttpException(401, 'You are not allowed to access this page.'); 121 | } 122 | return $model; 123 | } 124 | 125 | throw new HttpException(404, 'The requested page does not exist.'); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/layouts/DefaultLayout.php: -------------------------------------------------------------------------------- 1 | 1, 44 | '2' => 2, 45 | '3' => 3, 46 | '4' => 4, 47 | '6' => 6, 48 | '12' => 12, 49 | ]; 50 | } 51 | 52 | /** 53 | * @return array 54 | */ 55 | public function getRegions() 56 | { 57 | $regions = []; 58 | for ($i = 1; $i <= $this->columns; $i++) { 59 | $regions['column-' . $i] = Yii::t('dashboard', 'Column {i}', ['i' => $i]); 60 | } 61 | return $regions; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /src/migrations/m150705_000001_create_dashboard.php: -------------------------------------------------------------------------------- 1 | createTable(self::TABLE, [ 12 | 'id' => Schema::TYPE_PK, 13 | 'name' => Schema::TYPE_STRING . ' NOT NULL', 14 | 'layout_class' => Schema::TYPE_STRING . ' NOT NULL', 15 | 'sort' => Schema::TYPE_INTEGER . ' NOT NULL', 16 | 'options' => Schema::TYPE_TEXT, 17 | 'enabled' => Schema::TYPE_INTEGER . '(1) DEFAULT 0 NOT NULL', 18 | ], ($this->db->driverName === 'mysql' ? 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB' : null)); 19 | } 20 | 21 | public function down() 22 | { 23 | $this->dropTable(self::TABLE); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/migrations/m150705_000002_create_dashboard_panel.php: -------------------------------------------------------------------------------- 1 | createTable(self::TABLE, [ 12 | 'id' => Schema::TYPE_PK, 13 | 'name' => Schema::TYPE_STRING . ' NOT NULL', 14 | 'panel_class' => Schema::TYPE_STRING . ' NOT NULL', 15 | 'options' => Schema::TYPE_TEXT, 16 | 'dashboard_id' => Schema::TYPE_INTEGER . ' NOT NULL', 17 | 'region' => Schema::TYPE_STRING . ' NOT NULL', 18 | 'sort' => Schema::TYPE_INTEGER . ' NOT NULL', 19 | 'enabled' => Schema::TYPE_INTEGER . '(1) DEFAULT 0 NOT NULL', 20 | ], ($this->db->driverName === 'mysql' ? 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB' : null)); 21 | $this->addForeignKey('fk_dashboard_panel_dashboard_id', self::TABLE, ['dashboard_id'], '{{%dashboard}}', 'id', 'CASCADE'); 22 | } 23 | 24 | public function down() 25 | { 26 | $this->dropForeignKey('fk_dashboard_panel_dashboard_id', self::TABLE); 27 | $this->dropTable(self::TABLE); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/models/Dashboard.php: -------------------------------------------------------------------------------- 1 | 255] 46 | ]; 47 | } 48 | 49 | /** 50 | * @inheritdoc 51 | */ 52 | public function attributeLabels() 53 | { 54 | return [ 55 | 'id' => Yii::t('dashboard', 'ID'), 56 | 'name' => Yii::t('dashboard', 'Name'), 57 | 'layout_class' => Yii::t('dashboard', 'Layout Class'), 58 | 'enabled' => Yii::t('dashboard', 'Enabled'), 59 | 'sort' => Yii::t('dashboard', 'Sort'), 60 | 'options' => Yii::t('dashboard', 'Options'), 61 | ]; 62 | } 63 | 64 | 65 | /** 66 | * @inheritdoc 67 | * @return DashboardQuery the active query used by this AR class. 68 | */ 69 | public static function find() 70 | { 71 | return new DashboardQuery(get_called_class()); 72 | } 73 | 74 | /** 75 | * @return DashboardQuery 76 | */ 77 | public function getDashboardPanels() 78 | { 79 | return $this->hasMany(DashboardPanel::className(), ['dashboard_id' => 'id']) 80 | ->orderBy(['sort' => SORT_ASC]); 81 | } 82 | 83 | 84 | /** 85 | * @return Layout 86 | */ 87 | public function getLayout() 88 | { 89 | if (!$this->_layout) { 90 | $config = $this->options; 91 | $config['dashboard'] = $this; 92 | $config['class'] = $this->layout_class; 93 | $config['id'] = 'dashboard-' . $this->id; 94 | $this->_layout = Yii::createObject($config); 95 | } 96 | return $this->_layout; 97 | } 98 | 99 | /** 100 | * @param array $dashboardPanelSorts 101 | */ 102 | public function sortPanels($dashboardPanelSorts) 103 | { 104 | foreach ($dashboardPanelSorts as $region => $dashboardPanelSort) { 105 | foreach (explode(',', $dashboardPanelSort) as $k => $v) { 106 | $dashboardPanelId = str_replace('dashboard-panel-', '', $v); 107 | if ($dashboardPanelId) { 108 | $dashboardPanel = DashboardPanel::findOne($dashboardPanelId); 109 | if ($dashboardPanel) { 110 | $dashboardPanel->region = $region; 111 | $dashboardPanel->sort = $k; 112 | $dashboardPanel->save(false); 113 | } 114 | } 115 | } 116 | } 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/models/DashboardPanel.php: -------------------------------------------------------------------------------- 1 | 255] 48 | ]; 49 | } 50 | 51 | /** 52 | * @inheritdoc 53 | */ 54 | public function attributeLabels() 55 | { 56 | return [ 57 | 'id' => Yii::t('dashboard', 'ID'), 58 | 'dashboard_id' => Yii::t('dashboard', 'Dashboard ID'), 59 | 'region' => Yii::t('dashboard', 'Region'), 60 | 'name' => Yii::t('dashboard', 'Name'), 61 | 'options' => Yii::t('dashboard', 'Options'), 62 | 'panel_class' => Yii::t('dashboard', 'Panel Class'), 63 | 'enabled' => Yii::t('dashboard', 'Enabled'), 64 | 'sort' => Yii::t('dashboard', 'Sort'), 65 | ]; 66 | } 67 | 68 | 69 | /** 70 | * @inheritdoc 71 | * @return DashboardPanelQuery the active query used by this AR class. 72 | */ 73 | public static function find() 74 | { 75 | return new DashboardPanelQuery(get_called_class()); 76 | } 77 | 78 | /** 79 | * @return \yii\db\ActiveQuery 80 | */ 81 | public function getDashboard() 82 | { 83 | return $this->hasOne(Dashboard::className(), ['id' => 'dashboard_id']); 84 | } 85 | 86 | /** 87 | * @return Panel 88 | */ 89 | public function getPanel() 90 | { 91 | if (!$this->_panel) { 92 | $config = $this->options; 93 | $config['dashboardPanel'] = $this; 94 | $config['class'] = $this->panel_class; 95 | $config['id'] = 'dashboard-panel-' . $this->id; 96 | $this->_panel = Yii::createObject($config); 97 | } 98 | return $this->_panel; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/models/query/DashboardPanelQuery.php: -------------------------------------------------------------------------------- 1 | andWhere(['enabled' => 1]); 22 | } 23 | 24 | /** 25 | * @return static 26 | */ 27 | public function orderBySort() 28 | { 29 | return $this->orderBy(['sort' => SORT_ASC]); 30 | } 31 | 32 | /** 33 | * @inheritdoc 34 | * @return DashboardPanel[]|array 35 | */ 36 | public function all($db = null) 37 | { 38 | return parent::all($db); 39 | } 40 | 41 | /** 42 | * @return DashboardPanel[]|array 43 | */ 44 | public function allCanView($db = null) 45 | { 46 | $models = parent::all($db); 47 | foreach ($models as $k => $model) { 48 | if (!components\DashboardPanelAccess::userHasAccess($model->name)) { 49 | unset($models[$k]); 50 | } 51 | } 52 | 53 | return $models; 54 | } 55 | 56 | /** 57 | * @inheritdoc 58 | * @return DashboardPanel|array|null 59 | */ 60 | public function one($db = null) 61 | { 62 | return parent::one($db); 63 | } 64 | } -------------------------------------------------------------------------------- /src/models/query/DashboardQuery.php: -------------------------------------------------------------------------------- 1 | andWhere(['enabled' => 1]); 21 | } 22 | 23 | /** 24 | * @return static 25 | */ 26 | public function orderBySort() 27 | { 28 | return $this->orderBy(['sort' => SORT_ASC]); 29 | } 30 | 31 | /** 32 | * @inheritdoc 33 | * @return Dashboard[]|array 34 | */ 35 | public function all($db = null) 36 | { 37 | return parent::all($db); 38 | } 39 | 40 | /** 41 | * @inheritdoc 42 | * @return Dashboard|null 43 | */ 44 | public function one($db = null) 45 | { 46 | return parent::one($db); 47 | } 48 | } -------------------------------------------------------------------------------- /src/models/search/DashboardSearch.php: -------------------------------------------------------------------------------- 1 | $query, 49 | 'sort' => ['defaultOrder' => ['sort' => SORT_ASC]], 50 | ]); 51 | 52 | $this->load($params); 53 | 54 | if (!$this->validate()) { 55 | return $dataProvider; 56 | } 57 | 58 | $query->andFilterWhere([ 59 | 'id' => $this->id, 60 | 'enabled' => $this->enabled, 61 | 'sort' => $this->sort, 62 | ]); 63 | 64 | $query->andFilterWhere(['like', 'name', $this->name]) 65 | ->andFilterWhere(['like', 'layout_class', $this->layout_class]); 66 | 67 | return $dataProvider; 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /src/panels/TextPanel.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('dashboard', 'Create Dashboard Panel'); 13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('dashboard', 'Dashboards'), 'url' => ['dashboard/index']]; 14 | $this->params['breadcrumbs'][] = ['label' => $model->dashboard->name, 'url' => ['dashboard/view', 'id' => $model->dashboard_id]]; 15 | $this->params['breadcrumbs'][] = $this->title; 16 | ?> 17 |
18 | 19 | 'dashboardPanel-form', 21 | 'enableClientValidation' => false, 22 | 'errorSummaryCssClass' => 'alert alert-danger error-summary', 23 | ]); ?> 24 | 25 | dashboard_id); ?> 26 | 27 | errorSummary($model) ?> 28 | 29 | field($model, 'name')->textInput(['maxlength' => true]) ?> 30 | 31 | field($model, 'panel_class')->dropDownList(Module::getInstance()->panelsList(), ['prompt' => '']) ?> 32 | 33 | field($model, 'region')->dropDownList($model->dashboard->layout->getRegions(), ['prompt' => '']) ?> 34 | 35 | field($model, 'sort')->textInput(['maxlength' => true]) ?> 36 | 37 | field($model, 'enabled')->checkbox() ?> 38 | 39 | ' . Yii::t('dashboard', 'Create'), [ 40 | 'id' => 'save-' . $model->formName(), 41 | 'class' => 'btn btn-success' 42 | ]); ?> 43 | 44 | 45 | 46 | 47 |
48 | -------------------------------------------------------------------------------- /src/views/dashboard-panel/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('dashboard', 'Update') . ' ' . Yii::t('dashboard', 'Dashboard Panel') . ' ' . $model->name; 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('dashboard', 'Dashboards'), 'url' => ['dashboard/index']]; 13 | $this->params['breadcrumbs'][] = ['label' => $model->dashboard->name, 'url' => ['dashboard/view', 'id' => $model->dashboard_id]]; 14 | $this->params['breadcrumbs'][] = $model->name ? $model->name : Yii::t('dashboard', 'Dashboard Panel') . ' #' . $model->id; 15 | ?> 16 |
17 | 18 | 'dashboardPanel-form', 20 | 'enableClientValidation' => false, 21 | 'errorSummaryCssClass' => 'alert alert-danger error-summary', 22 | ]); ?> 23 | 24 | ', '', $form->errorSummary([$model, $model->panel])); ?> 25 | 26 | field($model, 'name')->textInput(['maxlength' => true]) ?> 27 | 28 | field($model, 'enabled')->checkbox() ?> 29 | 30 | panel->render('form', ['form' => $form]); ?> 31 | 32 | ' . Yii::t('dashboard', 'Save'), [ 33 | 'id' => 'save-' . $model->formName(), 34 | 'class' => 'btn btn-success' 35 | ]); ?> 36 | 37 | 38 | 39 |
40 | -------------------------------------------------------------------------------- /src/views/dashboard/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('dashboard', 'Create Dashboard'); 13 | $this->params['breadcrumbs'][] = ['label' => Yii::t('dashboard', 'Dashboards'), 'url' => ['index']]; 14 | $this->params['breadcrumbs'][] = $this->title; 15 | ?> 16 |
17 | 18 | 'dashboard-form', 20 | 'enableClientValidation' => false, 21 | 'errorSummaryCssClass' => 'alert alert-danger error-summary', 22 | ]); ?> 23 | 24 | errorSummary($model); ?> 25 | 26 | field($model, 'name')->textInput(['maxlength' => true]) ?> 27 | 28 | field($model, 'layout_class')->dropDownList(array_flip(Module::getInstance()->layouts), ['prompt' => '']) ?> 29 | 30 | field($model, 'sort')->textInput() ?> 31 | 32 | field($model, 'enabled')->checkbox() ?> 33 | 34 | ' . Yii::t('dashboard', 'Create'), [ 35 | 'id' => 'save-' . $model->formName(), 36 | 'class' => 'btn btn-success' 37 | ]); ?> 38 | 39 | 40 | 41 |
42 | -------------------------------------------------------------------------------- /src/views/dashboard/empty.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('dashboard', 'Dashboard'); 8 | $this->params['breadcrumbs'][] = ['label' => Yii::t('dashboard', 'Dashboards'), 'url' => ['index']]; 9 | ?> 10 | 11 |
12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /src/views/dashboard/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('dashboard', 'Dashboards'); 18 | $this->params['breadcrumbs'][] = $this->title; 19 | ?> 20 | 21 |
22 | 23 |
24 |

25 | ' . Yii::t('dashboard', 'Create') . ' ' . Yii::t('dashboard', 'Dashboard'), [ 26 | 'create', 27 | 'Dashboard' => [ 28 | 'enabled' => 1, 29 | 'sort' => 0, 30 | ], 31 | ], ['class' => 'btn btn-success']) ?> 32 |

33 |
34 | 35 | orderBySort()->all() as $dashboard) { 38 | $dashboardDisplay = implode(' ', [ 39 | Html::a('', ['dashboard/view', 'id' => $dashboard->id], [ 40 | 'data-toggle' => 'tooltip', 41 | 'title' => Yii::t('dashboard', 'View Dashboard'), 42 | ]), 43 | Html::a('', ['dashboard/update', 'id' => $dashboard->id], [ 44 | 'data-toggle' => 'tooltip', 45 | 'title' => Yii::t('dashboard', 'Update Dashboard'), 46 | ]), 47 | Html::a('', ['dashboard/delete', 'id' => $dashboard->id], [ 48 | 'data-confirm' => Yii::t('dashboard', 'Are you sure to delete this dashboard?'), 49 | 'data-method' => 'post', 50 | 'data-toggle' => 'tooltip', 51 | 'title' => Yii::t('dashboard', 'Delete Dashboard'), 52 | ]), 53 | '  ' . Html::tag('span', $dashboard->name, ['style' => !$dashboard->enabled ? 'text-decoration:line-through' : '']), 54 | ]); 55 | $items[] = [ 56 | 'options' => [ 57 | 'id' => 'dashboard-' . $dashboard->id, 58 | 'class' => 'dashboard', 59 | ], 60 | 'content' => $dashboardDisplay, 61 | ]; 62 | } 63 | echo Sortable::widget([ 64 | 'id' => 'dashboard-sortable', 65 | 'items' => $items, 66 | 'pluginEvents' => [ 67 | 'sortupdate' => 'dashboardSort', 68 | ], 69 | ]); 70 | $this->registerJs('var dashboardSortUrl = "' . Url::to(['dashboard/sort']) . '"', View::POS_END); 71 | ?> 72 | 73 |
-------------------------------------------------------------------------------- /src/views/dashboard/layouts/_buttons.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | ', [ 14 | 'dashboard-panel/create', 15 | 'DashboardPanel' => [ 16 | 'dashboard_id' => $layout->dashboard->id, 17 | 'enabled' => 1, 18 | ], 19 | ], [ 20 | 'data-toggle' => 'tooltip', 21 | 'title' => Yii::t('dashboard', 'Create Dashboard Panel'), 22 | ]) ?> 23 | 24 | ', ['update', 'id' => $layout->dashboard->id], [ 25 | 'data-toggle' => 'tooltip', 26 | 'title' => Yii::t('dashboard', 'Update Dashboard'), 27 | ]) ?> 28 | 29 | ', ['delete', 'id' => $layout->dashboard->id], [ 30 | 'data-confirm' => Yii::t('dashboard', 'Are you sure to delete this dashboard?'), 31 | 'data-method' => 'post', 32 | 'data-toggle' => 'tooltip', 33 | 'title' => Yii::t('dashboard', 'Delete Dashboard'), 34 | ]); ?> 35 | -------------------------------------------------------------------------------- /src/views/dashboard/layouts/default/form.php: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | field($layout, 'columns')->dropDownList($layout->getColumnOpts(), ['prompt' => '']) ?> 17 | -------------------------------------------------------------------------------- /src/views/dashboard/layouts/default/update.php: -------------------------------------------------------------------------------- 1 | dashboard->options['columns']) ? $layout->dashboard->options['columns'] : 1; 15 | if (!in_array($columns, array(1, 2, 3, 4, 6))) $columns = 1; 16 | $span = round(12 / $columns); 17 | 18 | $regionPanels = $layout->regionPanels($layout->dashboard->getDashboardPanels()->all(), 'update'); 19 | 20 | if (isset($regionPanels['none'])) { 21 | $overflow = $regionPanels['none']; 22 | unset($regionPanels['none']); 23 | } 24 | 25 | echo '
'; 26 | echo '
'; 27 | foreach ($regionPanels as $region => $items) { 28 | echo '
'; 29 | 30 | // sortable widget to enable drag-and-drop 31 | echo Sortable::widget([ 32 | 'id' => 'dashboard-region-' . $region, 33 | 'connected' => true, 34 | 'items' => $items, 35 | 'pluginEvents' => [ 36 | 'sortupdate' => 'dashboardPanelSort', 37 | ], 38 | ]); 39 | 40 | // hidden element to store the sort order 41 | echo Html::hiddenInput('DashboardPanelSort[' . $region . ']', implode(',', ArrayHelper::map($items, 'options.id', 'options.id')), [ 42 | 'id' => 'input-dashboard-region-' . $region, 43 | ]); 44 | 45 | // create dashboard panel button 46 | echo '
'; 47 | echo Html::a(Yii::t('dashboard', 'Create Dashboard Panel'), [ 48 | 'dashboard-panel/create', 49 | 'DashboardPanel' => [ 50 | 'dashboard_id' => $layout->dashboard->id, 51 | 'region' => $region, 52 | 'sort' => count($items), 53 | 'enabled' => 1, 54 | ] 55 | ], ['class' => 'btn btn-default btn-sm']); 56 | echo '
'; 57 | 58 | echo '
'; 59 | } 60 | echo '
'; 61 | if (isset($overflow)) { 62 | echo '
'; 63 | echo Html::hiddenInput('DashboardPanelSort[overflow]', implode(',', ArrayHelper::map($overflow, 'options.id', 'options.id')), [ 64 | 'id' => 'input-dashboard-region-overflow', 65 | ]); 66 | echo Sortable::widget([ 67 | 'id' => 'dashboard-region-overflow', 68 | 'connected' => true, 69 | 'items' => $overflow, 70 | 'pluginEvents' => [ 71 | 'sortupdate' => 'dashboardPanelSort', 72 | ], 73 | ]); 74 | } -------------------------------------------------------------------------------- /src/views/dashboard/layouts/default/view.php: -------------------------------------------------------------------------------- 1 | dashboard->options['columns']) ? $layout->dashboard->options['columns'] : 1; 13 | if (!in_array($columns, array(1, 2, 3, 4, 6))) $columns = 1; 14 | $span = round(12 / $columns); 15 | 16 | $regionPanels = $layout->regionPanels($layout->dashboard->getDashboardPanels()->enabled()->allCanView(), 'view'); 17 | 18 | if (isset($regionPanels['none'])) { 19 | $overflow = $regionPanels['none']; 20 | unset($regionPanels['none']); 21 | } 22 | ?> 23 |
24 |
25 |

26 | dashboard->name ?> 27 |
28 | render('@cornernote/dashboard/views/dashboard/layouts/_buttons', ['layout' => $layout]) ?> 29 |
30 |

31 |
32 |
33 | '; 35 | foreach ($regionPanels as $region => $items) { 36 | echo '
'; 37 | foreach ($items as $item) { 38 | echo Html::tag('div', $item['content'], $item['options']); 39 | } 40 | echo '
'; 41 | } 42 | echo '
'; 43 | if (isset($overflow)) { 44 | echo '
'; 45 | foreach ($overflow as $item) { 46 | echo Html::tag('div', $item['content'], $item['options']); 47 | } 48 | } 49 | ?> 50 |
51 | 52 | -------------------------------------------------------------------------------- /src/views/dashboard/panels/_buttons.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | ', ['dashboard-panel/update', 'id' => $panel->dashboardPanel->id], [ 14 | 'data-toggle' => 'tooltip', 15 | 'title' => Yii::t('dashboard', 'Update Dashboard Panel'), 16 | ]) ?> 17 | 18 | ', ['dashboard-panel/delete', 'id' => $panel->dashboardPanel->id], [ 19 | 'data-confirm' => Yii::t('dashboard', 'Are you sure to delete this dashboard panel?'), 20 | //'data-method' => 'post', 21 | 'data-toggle' => 'tooltip', 22 | 'title' => Yii::t('dashboard', 'Delete Dashboard Panel'), 23 | ]) ?> 24 | -------------------------------------------------------------------------------- /src/views/dashboard/panels/text/form.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | field($panel, 'text')->textarea(['rows' => 6]) ?> 15 | 16 | -------------------------------------------------------------------------------- /src/views/dashboard/panels/text/update.php: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 |
16 |

17 | dashboardPanel->name ?> 18 |
19 | render('@cornernote/dashboard/views/dashboard/panels/_buttons', ['panel' => $panel]) ?> 20 |
21 |

22 |
23 |
24 | dashboardPanel->options); ?> 25 |
26 |
-------------------------------------------------------------------------------- /src/views/dashboard/panels/text/view.php: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 |
15 |

16 | dashboardPanel->name ?> 17 |
18 | render('@cornernote/dashboard/views/dashboard/panels/_buttons', ['panel' => $panel]) ?> 19 |
20 |

21 |
22 |
23 | formatter->asNtext($panel->text); ?> 24 |
25 |
26 | -------------------------------------------------------------------------------- /src/views/dashboard/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('dashboard', 'Update') . ' ' . Yii::t('dashboard', 'Dashboard') . ' ' . $model->name; 15 | $this->params['breadcrumbs'][] = ['label' => Yii::t('dashboard', 'Dashboards'), 'url' => ['index']]; 16 | $this->params['breadcrumbs'][] = ['label' => $model->name ? $model->name : Yii::t('dashboard', 'Dashboard') . ' #' . $model->id, 'url' => ['view', 'id' => $model->id]]; 17 | $this->params['breadcrumbs'][] = Yii::t('dashboard', 'Update'); 18 | ?> 19 |
20 | 21 |

22 | name; ?> 23 |

24 | 25 | 'dashboard-form', 27 | 'enableClientValidation' => false, 28 | 'errorSummaryCssClass' => 'alert alert-danger error-summary', 29 | ]); ?> 30 | 31 | ', '', $form->errorSummary([$model, $model->layout])); ?> 32 | 33 | field($model, 'name')->textInput(['maxlength' => true]) ?> 34 | 35 | field($model, 'enabled')->checkbox() ?> 36 | 37 | layout->render('form', ['form' => $form]); ?> 38 | 39 | layout->render('update'); ?> 40 | 41 |
42 | ' . Yii::t('dashboard', 'Save'), [ 43 | 'id' => 'save-' . $model->formName(), 44 | 'class' => 'btn btn-success' 45 | ]); ?> 46 |
47 | 48 | 49 | 50 |
51 | -------------------------------------------------------------------------------- /src/views/dashboard/view.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('dashboard', 'Dashboard') . ' ' . $model->name; 11 | $this->params['breadcrumbs'][] = ['label' => Yii::t('dashboard', 'Dashboards'), 'url' => ['index']]; 12 | $this->params['breadcrumbs'][] = $model->name ? $model->name : Yii::t('dashboard', 'Dashboard') . ' #' . $model->id; 13 | ?> 14 | 15 |
16 | 17 | layout->render('view'); ?> 18 | 19 |
20 | -------------------------------------------------------------------------------- /src/views/layouts/main.php: -------------------------------------------------------------------------------- 1 | 16 | beginPage() ?> 17 | 18 | 19 | 20 | 21 | 22 | 23 | <?= Html::encode($this->title) ?> 24 | registerCss('body{padding-top: 60px;}'); ?> 25 | head() ?> 26 | 27 | 28 | beginBody() ?> 29 | 30 | Yii::t('dashboard', 'Dashboards'), 33 | 'brandUrl' => ['dashboard/index'], 34 | 'options' => ['class' => 'navbar-default navbar-fixed-top navbar-fluid'], 35 | 'innerContainerOptions' => ['class' => 'container-fluid'], 36 | ]); 37 | $items = []; 38 | foreach (Dashboard::find()->enabled()->orderBySort()->all() as $dashboard) { 39 | $items[] = [ 40 | 'label' => $dashboard->name, 41 | 'url' => ['dashboard/view', 'id' => $dashboard->id], 42 | ]; 43 | } 44 | echo Nav::widget([ 45 | 'items' => $items, 46 | 'options' => ['class' => 'navbar-nav'], 47 | ]); 48 | echo Nav::widget([ 49 | 'items' => [ 50 | ['label' => Yii::$app->name, 'url' => Yii::$app->getHomeUrl()], 51 | ], 52 | 'options' => ['class' => 'navbar-nav navbar-right'], 53 | ]); 54 | NavBar::end(); 55 | ?> 56 | 57 |
58 | params['breadcrumbs'])) { ?> 59 | 64 | 65 | 66 | 67 |
68 | 69 | endBody() ?> 70 | 71 | 72 | endPage() ?> 73 | -------------------------------------------------------------------------------- /src/web/DashboardAsset.php: -------------------------------------------------------------------------------- 1 | getSession()->setFlash('error', 'Alert! Danger alert preview. This alert is dismissable.'); 14 | * ``` 15 | * 16 | * Multiple messages could be set as follows: 17 | * 18 | * ```php 19 | * \Yii::$app->getSession()->setFlash('error', ['Error 1', 'Error 2']); 20 | * ``` 21 | * 22 | * @author Evgeniy Tkachenko 23 | */ 24 | class Alert extends Widget 25 | { 26 | /** 27 | * @var array the alert types configuration for the flash messages. 28 | * This array is setup as $key => $value, where: 29 | * - $key is the name of the session flash variable 30 | * - $value is the array: 31 | * - class of alert type (i.e. danger, success, info, warning) 32 | * - icon for alert AdminLTE 33 | */ 34 | public $alertTypes = [ 35 | 'error' => [ 36 | 'class' => 'alert-danger', 37 | 'icon' => '', 38 | ], 39 | 'danger' => [ 40 | 'class' => 'alert-danger', 41 | 'icon' => '', 42 | ], 43 | 'success' => [ 44 | 'class' => 'alert-success', 45 | 'icon' => '', 46 | ], 47 | 'info' => [ 48 | 'class' => 'alert-info', 49 | 'icon' => '', 50 | ], 51 | 'warning' => [ 52 | 'class' => 'alert-warning', 53 | 'icon' => '', 54 | ], 55 | ]; 56 | 57 | /** 58 | * @var array the options for rendering the close button tag. 59 | */ 60 | public $closeButton = [ 61 | 'label' => '', 62 | ]; 63 | 64 | /** 65 | * Initializes the widget. 66 | * This method will register the bootstrap asset bundle. If you override this method, 67 | * make sure you call the parent implementation first. 68 | */ 69 | public function init() 70 | { 71 | parent::init(); 72 | 73 | $session = \Yii::$app->getSession(); 74 | $flashes = $session->getAllFlashes(); 75 | $appendCss = isset($this->options['class']) ? ' ' . $this->options['class'] : ''; 76 | 77 | foreach ($flashes as $type => $data) { 78 | if (isset($this->alertTypes[$type])) { 79 | $data = (array)$data; 80 | foreach ($data as $message) { 81 | 82 | $this->options['class'] = $this->alertTypes[$type]['class'] . $appendCss; 83 | $this->options['id'] = $this->getId() . '-' . $type; 84 | 85 | echo BootstrapAlert::widget([ 86 | 'body' => $this->alertTypes[$type]['icon'] . ' ' . $message, 87 | 'closeButton' => $this->closeButton, 88 | 'options' => $this->options, 89 | ]); 90 | } 91 | 92 | $session->removeFlash($type); 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/widgets/AskToSaveWork.php: -------------------------------------------------------------------------------- 1 | Yii::t('app', 'Please save before leaving this page.'), 18 | * ]); 19 | * ``` 20 | */ 21 | class AskToSaveWork extends Widget 22 | { 23 | /** 24 | * @var String Message to show to user preventing exit the page 25 | */ 26 | public $message; 27 | 28 | /** 29 | * @inheritdoc 30 | */ 31 | public function init() 32 | { 33 | parent::init(); 34 | $this->message = isset($this->message) ? $this->message : Yii::t('dashboard', 'Please save before leaving this page.'); 35 | $this->registerAssets(); 36 | } 37 | 38 | /** 39 | * @inheritdoc 40 | */ 41 | public function registerAssets() 42 | { 43 | $js = "var formModified = false;"; 44 | $this->getView()->registerJs($js, View::POS_END); 45 | 46 | $js = "$('form :input').change(function(){ formModified=true; });"; 47 | $js .= "$(window).bind('beforeunload', function() { if (formModified) { return \"" . $this->message . "\"; } });"; 48 | $js .= "$(':submit').bind('click', function(){ formModified=false; });"; 49 | $this->getView()->registerJs($js); 50 | } 51 | } --------------------------------------------------------------------------------