Merge branch 'material-deisgn'

# Conflicts:
#	models/Item.php
#	servers/CoreServer.php
#	views/panel/_variable.php
#	views/panel/index.php
#	web/js/wsclient.js
This commit is contained in:
Alex Solomaha
2017-05-07 00:24:11 +03:00
116 changed files with 10848 additions and 4109 deletions

View File

@@ -17,9 +17,12 @@ class AppAsset extends AssetBundle
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
'yii\bootstrap\BootstrapPluginAsset',
'rmrevin\yii\fontawesome\AssetBundle',
'dmstr\web\AdminLteAsset',
'shifrin\noty\NotyAsset',
// 'dmstr\web\AdminLteAsset',
// 'shifrin\noty\NotyAsset',
'app\assets\MDThemeAsset',
// 'app\assets\JSCookieAsset',
// 'app\assets\ChartjsAsset',
];
}

18
assets/ChartjsAsset.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
namespace app\assets;
use yii\web\AssetBundle;
class ChartjsAsset extends AssetBundle
{
public $sourcePath = '@bower/chart.js/dist';
public $js = [
'Chart.min.js',
];
public $publishOptions = [
'only' => [
'*.js',
]
];
}

View File

@@ -0,0 +1,19 @@
<?php
namespace app\assets;
use yii\web\AssetBundle;
class FontawesomeIconpickerAsset extends AssetBundle
{
public $sourcePath = '@bower/fontawesome-iconpicker/dist';
public $js = [
'js/fontawesome-iconpicker.min.js',
];
public $css = [
'css/fontawesome-iconpicker.min.css',
];
public $depends = [
'yii\web\JqueryAsset',
];
}

18
assets/JSCookieAsset.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
namespace app\assets;
use yii\web\AssetBundle;
class JSCookieAsset extends AssetBundle
{
public $sourcePath = '@bower/js-cookie';
public $js = [
'src/js.cookie.js',
];
public $publishOptions = [
'only' => [
'*.js',
]
];
}

26
assets/MDThemeAsset.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
namespace app\assets;
use yii\web\AssetBundle;
class MDThemeAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/theme.css',
'css/ripples.css',
'css/md.theme.css',
];
public $js = [
'js/ripples.js',
'js/md.theme.js',
];
public $depends = [
'yii\web\JqueryAsset',
'yii\bootstrap\BootstrapPluginAsset',
'app\assets\SnackbarjsAsset',
'app\assets\SpectrumAsset',
];
}

View File

@@ -3,21 +3,22 @@
namespace app\assets;
use yii\web\AssetBundle;
use yii\web\JqueryAsset;
class WSClientAsset extends AssetBundle
class PanelAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/wsclient.css',
'css/panel.css',
];
public $js = [
'js/wsclient.js',
'js/panel.js',
];
public $depends = [
'app\assets\SpectrumAsset',
'app\assets\AppAsset',
'app\assets\HandlebarsAsset',
'app\assets\SpectrumAsset',
'app\assets\ChartjsAsset',
'yii\web\JqueryAsset',
];
}

View File

@@ -0,0 +1,25 @@
<?php
namespace app\assets;
use yii\web\AssetBundle;
class SnackbarjsAsset extends AssetBundle
{
public $sourcePath = '@bower/snackbarjs';
public $js = [
'dist/snackbar.min.js',
];
public $css = [
'dist/snackbar.css',
'themes-css/material.css',
];
public $publishOptions = [
'only' => [
'*.js',
'*.css',
'*.js.*',
'*.css.*',
]
];
}

View File

@@ -8,14 +8,13 @@ use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\Factory;
use React\Socket\Server;
use Yii;
use yii\console\Controller;
class PanelController extends Controller
class StartCoreServerController extends Controller
{
public function actionIndex($port = 8081)
{
echo "Starting server on port $port..." . PHP_EOL;
echo "Starting Core WS Server on port $port..." . PHP_EOL;
$loop = Factory::create();

View File

@@ -37,7 +37,7 @@ class ActionButtonColumn extends ActionColumn
$this->buttons['view'] = function ($url, $model, $key) {
return Html::a(FA::i('eye'), $url, array_merge([
'title' => Yii::t('yii', 'View'),
'class' => 'btn btn-ar btn-default btn-xs',
'class' => 'btn btn-flat btn-xs btn-default',
], $this->buttonOptions));
};
}
@@ -45,7 +45,7 @@ class ActionButtonColumn extends ActionColumn
$this->buttons['update'] = function ($url, $model, $key) {
return Html::a(FA::i('pencil'), $url, array_merge([
'title' => Yii::t('yii', 'Update'),
'class' => 'btn btn-ar btn-primary btn-xs',
'class' => 'btn btn-flat btn-xs btn-default',
], $this->buttonOptions));
};
}
@@ -53,7 +53,7 @@ class ActionButtonColumn extends ActionColumn
$this->buttons['delete'] = function ($url, $model, $key) {
return Html::a(FA::i('trash'), $url, array_merge([
'title' => Yii::t('yii', 'Delete'),
'class' => 'btn btn-ar btn-danger btn-xs',
'class' => 'btn btn-flat btn-xs btn-default',
'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
'data-method' => 'post',
], $this->buttonOptions));

View File

@@ -11,20 +11,22 @@
"cboden/ratchet": "^0.3.4",
"bower-asset/handlebars": "^4.0",
"bower-asset/spectrum": "^1.8",
"bower-asset/snackbarjs": "dev-fixes",
"rmrevin/yii2-fontawesome": "~2.12",
"dmstr/yii2-adminlte-asset": "2.*",
"linslin/yii2-curl": "1.0.8",
"shifrin/yii2-noty": "^1.0",
"ratchet/pawl": "^0.2.2",
"voskobovich/yii2-many-many-behavior": "^3.2",
"kartik-v/yii2-widgets": "^3.4",
"kartik-v/yii2-datecontrol": "^1.9",
"voskobovich/yii2-linker-behavior": "4.0.1-rc"
"voskobovich/yii2-linker-behavior": "4.0.1-rc",
"bower-asset/js-cookie": "^2.1",
"bower-asset/chart.js": ">=2.5",
"bower-asset/fontawesome-iconpicker": "^1.3"
},
"require-dev": {
"yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*",
"yiisoft/yii2-faker": "*"
"yiisoft/yii2-gii": "*"
},
"config": {
"process-timeout": 1800
@@ -33,6 +35,16 @@
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
},
"asset-repositories": [
{
"type": "bower-github",
"url": "https://github.com/CyanoFresh/snackbarjs",
"name": "bower-asset/snackbarjs"
}
]
},
"scripts": {
"post-install-cmd": "php init --env=Development --overwrite=n"
}
}

458
composer.lock generated
View File

@@ -4,49 +4,9 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "87c8d87131a5bfba1bfd212e32223bc6",
"content-hash": "662fe9c5133c13341bcddbe8b1f55bfc",
"hash": "d72e15d1c94855a26467586b784ffcb8",
"content-hash": "50f7bcdee8e1349910fd57865528edf4",
"packages": [
{
"name": "almasaeed2010/adminlte",
"version": "v2.3.11",
"source": {
"type": "git",
"url": "https://github.com/almasaeed2010/AdminLTE.git",
"reference": "2be703222af2edcb87e562d3da2299e4352bff8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/almasaeed2010/AdminLTE/zipball/2be703222af2edcb87e562d3da2299e4352bff8a",
"reference": "2be703222af2edcb87e562d3da2299e4352bff8a",
"shasum": ""
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Abdullah Almsaeed",
"email": "abdullah@almsaeedstudio.com"
}
],
"description": "AdminLTE - admin control panel and dashboard that's based on Bootstrap 3",
"homepage": "http://almsaeedstudio.com/",
"keywords": [
"JS",
"admin",
"back-end",
"css",
"less",
"responsive",
"template",
"theme",
"web"
],
"time": "2017-01-08 21:03:57"
},
{
"name": "bower-asset/bootstrap",
"version": "v3.3.7",
@@ -96,6 +56,73 @@
"web"
]
},
{
"name": "bower-asset/chart.js",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/chartjs/Chart.js.git",
"reference": "c867d3f728d595eafc017f4d4136128824d1db25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/chartjs/Chart.js/zipball/c867d3f728d595eafc017f4d4136128824d1db25",
"reference": "c867d3f728d595eafc017f4d4136128824d1db25",
"shasum": ""
},
"type": "bower-asset-library",
"extra": {
"bower-asset-main": "./dist/Chart.js",
"bower-asset-ignore": [
".github",
".codeclimate.yml",
".gitignore",
".npmignore",
".travis.yml",
"scripts"
]
},
"license": [
"MIT"
],
"description": "Simple HTML5 charts using the canvas element."
},
{
"name": "bower-asset/fontawesome-iconpicker",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/itsjavi/fontawesome-iconpicker.git",
"reference": "6087c66a7395738f59cab3887221bb75cd0e08f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/itsjavi/fontawesome-iconpicker/zipball/6087c66a7395738f59cab3887221bb75cd0e08f7",
"reference": "6087c66a7395738f59cab3887221bb75cd0e08f7",
"shasum": ""
},
"require": {
"bower-asset/bootstrap": ">=3.0.0,<4.0.0",
"bower-asset/jquery": ">=1.10"
},
"type": "bower-asset-library",
"extra": {
"bower-asset-main": [
"dist/css/fontawesome-iconpicker.css",
"dist/css/fontawesome-iconpicker.min.css",
"dist/js/fontawesome-iconpicker.js",
"dist/js/fontawesome-iconpicker.min.js"
],
"bower-asset-ignore": [
"\\.*",
"/extension",
"/src",
"index.html",
"/package.json",
"/Gruntfile.js"
]
}
},
{
"name": "bower-asset/handlebars",
"version": "v4.0.5",
@@ -151,16 +178,16 @@
},
{
"name": "bower-asset/jquery.inputmask",
"version": "3.2.7",
"version": "3.3.4",
"source": {
"type": "git",
"url": "https://github.com/RobinHerbots/jquery.inputmask.git",
"reference": "5a72c563b502b8e05958a524cdfffafe9987be38"
"url": "https://github.com/RobinHerbots/Inputmask.git",
"reference": "8a882bc471ba4077c4f8ecbe3d9d61c7558f3ef2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/RobinHerbots/jquery.inputmask/zipball/5a72c563b502b8e05958a524cdfffafe9987be38",
"reference": "5a72c563b502b8e05958a524cdfffafe9987be38",
"url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/8a882bc471ba4077c4f8ecbe3d9d61c7558f3ef2",
"reference": "8a882bc471ba4077c4f8ecbe3d9d61c7558f3ef2",
"shasum": ""
},
"require": {
@@ -169,7 +196,14 @@
"type": "bower-asset-library",
"extra": {
"bower-asset-main": [
"./dist/inputmask/inputmask.js"
"./dist/inputmask/inputmask.dependencyLib",
"./dist/inputmask/inputmask",
"./dist/inputmask/inputmask.extensions",
"./dist/inputmask/inputmask.date.extensions",
"./dist/inputmask/inputmask.numeric.extensions",
"./dist/inputmask/inputmask.phone.extensions",
"./dist/inputmask/inputmask.regex.extensions",
"./dist/inputmask/jquery.inputmask"
],
"bower-asset-ignore": [
"**/*",
@@ -195,6 +229,41 @@
"plugins"
]
},
{
"name": "bower-asset/js-cookie",
"version": "v2.1.3",
"source": {
"type": "git",
"url": "https://github.com/js-cookie/js-cookie.git",
"reference": "68acf18560eb7a5d21db7197ae24d975971d1ae0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/js-cookie/js-cookie/zipball/68acf18560eb7a5d21db7197ae24d975971d1ae0",
"reference": "68acf18560eb7a5d21db7197ae24d975971d1ae0",
"shasum": ""
},
"type": "bower-asset-library",
"extra": {
"bower-asset-main": [
"src/js.cookie.js"
],
"bower-asset-ignore": [
"travis.sh",
"test",
"Gruntfile.js",
"package.json",
".gitignore",
".jshintignore",
".jshintrc",
".tm_properties",
".travis.yml"
]
},
"license": [
"MIT"
]
},
{
"name": "bower-asset/noty",
"version": "v2.4.0",
@@ -244,6 +313,36 @@
]
}
},
{
"name": "bower-asset/snackbarjs",
"version": "dev-fixes",
"source": {
"type": "git",
"url": "https://github.com/CyanoFresh/snackbarjs.git",
"reference": "18df00bca47dea8421922b37db2ebd798cadd0fa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CyanoFresh/snackbarjs/zipball/18df00bca47dea8421922b37db2ebd798cadd0fa",
"reference": "18df00bca47dea8421922b37db2ebd798cadd0fa",
"shasum": ""
},
"require": {
"bower-asset/jquery": ">=2.0.0,<3.0.0"
},
"type": "bower-asset-library",
"extra": {
"bower-asset-main": [
"dist/snackbar.min.js",
"dist/snackbar.min.css"
],
"bower-asset-ignore": [
".jshintrc",
"**/*.txt"
]
},
"time": "2017-02-08 21:57:42"
},
{
"name": "bower-asset/spectrum",
"version": "1.8.0",
@@ -422,109 +521,6 @@
],
"time": "2016-09-14 20:40:20"
},
{
"name": "cebe/yii2-gravatar",
"version": "1.1",
"target-dir": "cebe/gravatar",
"source": {
"type": "git",
"url": "https://github.com/cebe/yii2-gravatar.git",
"reference": "c9c01bd14c9bdee9e5ae1ef1aad23f80c182c057"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cebe/yii2-gravatar/zipball/c9c01bd14c9bdee9e5ae1ef1aad23f80c182c057",
"reference": "c9c01bd14c9bdee9e5ae1ef1aad23f80c182c057",
"shasum": ""
},
"require": {
"yiisoft/yii2": "*"
},
"type": "yii2-extension",
"autoload": {
"psr-0": {
"cebe\\gravatar\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Carsten Brandt",
"email": "mail@cebe.cc",
"homepage": "http://cebe.cc/",
"role": "Core framework development"
}
],
"description": "Gravatar Widget for Yii 2",
"keywords": [
"gravatar",
"yii"
],
"time": "2013-12-10 17:49:58"
},
{
"name": "dmstr/yii2-adminlte-asset",
"version": "2.3.4",
"source": {
"type": "git",
"url": "https://github.com/dmstr/yii2-adminlte-asset.git",
"reference": "32fdb7378f3f4bcc5fb35db5e17a2dd11f9e2b57"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dmstr/yii2-adminlte-asset/zipball/32fdb7378f3f4bcc5fb35db5e17a2dd11f9e2b57",
"reference": "32fdb7378f3f4bcc5fb35db5e17a2dd11f9e2b57",
"shasum": ""
},
"require": {
"almasaeed2010/adminlte": "~2.0",
"cebe/yii2-gravatar": "1.*",
"rmrevin/yii2-fontawesome": "~2.9",
"yiisoft/yii2": "2.*",
"yiisoft/yii2-bootstrap": "2.*"
},
"type": "yii2-extension",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"dmstr\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Tobias Munk",
"email": "tobias@diemeisterei.de"
},
{
"name": "Evgeniy Tkachenko",
"email": "et.coder@gmail.com"
}
],
"description": "AdminLTE backend theme asset bundle for Yii 2.0 Framework",
"keywords": [
"AdminLTE",
"admin",
"asset",
"backend",
"css",
"extension",
"less",
"theme",
"yii2"
],
"time": "2016-10-21 02:03:45"
},
{
"name": "evenement/evenement",
"version": "v2.0.0",
@@ -2693,16 +2689,16 @@
},
{
"name": "react/socket",
"version": "v0.4.5",
"version": "v0.4.6",
"source": {
"type": "git",
"url": "https://github.com/reactphp/socket.git",
"reference": "32385d71f84c4a26ea577cb91f1220decb440dce"
"reference": "cf074e53c974df52388ebd09710a9018894745d2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/socket/zipball/32385d71f84c4a26ea577cb91f1220decb440dce",
"reference": "32385d71f84c4a26ea577cb91f1220decb440dce",
"url": "https://api.github.com/repos/reactphp/socket/zipball/cf074e53c974df52388ebd09710a9018894745d2",
"reference": "cf074e53c974df52388ebd09710a9018894745d2",
"shasum": ""
},
"require": {
@@ -2714,6 +2710,7 @@
},
"require-dev": {
"clue/block-react": "^1.1",
"phpunit/phpunit": "~4.8",
"react/socket-client": "^0.5.1"
},
"type": "library",
@@ -2730,7 +2727,7 @@
"keywords": [
"Socket"
],
"time": "2017-01-08 11:36:16"
"time": "2017-01-26 09:23:38"
},
{
"name": "react/socket-client",
@@ -2775,16 +2772,16 @@
},
{
"name": "react/stream",
"version": "v0.4.5",
"version": "v0.4.6",
"source": {
"type": "git",
"url": "https://github.com/reactphp/stream.git",
"reference": "23389503012e1ab721ad498a5a1f4b39f7a43c00"
"reference": "44dc7f51ea48624110136b535b9ba44fd7d0c1ee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/stream/zipball/23389503012e1ab721ad498a5a1f4b39f7a43c00",
"reference": "23389503012e1ab721ad498a5a1f4b39f7a43c00",
"url": "https://api.github.com/repos/reactphp/stream/zipball/44dc7f51ea48624110136b535b9ba44fd7d0c1ee",
"reference": "44dc7f51ea48624110136b535b9ba44fd7d0c1ee",
"shasum": ""
},
"require": {
@@ -2815,7 +2812,7 @@
"pipe",
"stream"
],
"time": "2016-11-13 17:06:02"
"time": "2017-01-25 14:44:14"
},
{
"name": "rmrevin/yii2-fontawesome",
@@ -3015,7 +3012,7 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v3.2.2",
"version": "v3.2.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
@@ -3075,16 +3072,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v3.2.2",
"version": "v3.2.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "33eb76bf1d833c705433e5361a646c164696394b"
"reference": "e192b04de44aa1ed0e39d6793f7e06f5e0b672a0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/33eb76bf1d833c705433e5361a646c164696394b",
"reference": "33eb76bf1d833c705433e5361a646c164696394b",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/e192b04de44aa1ed0e39d6793f7e06f5e0b672a0",
"reference": "e192b04de44aa1ed0e39d6793f7e06f5e0b672a0",
"shasum": ""
},
"require": {
@@ -3124,7 +3121,7 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
"time": "2017-01-08 20:47:33"
"time": "2017-02-02 13:47:35"
},
{
"name": "symfony/polyfill-mbstring",
@@ -3187,16 +3184,16 @@
},
{
"name": "symfony/routing",
"version": "v3.2.2",
"version": "v3.2.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
"reference": "fda2c67d47ec801726ca888c95d701d31b27b444"
"reference": "af464432c177dbcdbb32295113b7627500331f2d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/fda2c67d47ec801726ca888c95d701d31b27b444",
"reference": "fda2c67d47ec801726ca888c95d701d31b27b444",
"url": "https://api.github.com/repos/symfony/routing/zipball/af464432c177dbcdbb32295113b7627500331f2d",
"reference": "af464432c177dbcdbb32295113b7627500331f2d",
"shasum": ""
},
"require": {
@@ -3258,7 +3255,7 @@
"uri",
"url"
],
"time": "2017-01-02 20:32:22"
"time": "2017-01-28 02:37:08"
},
{
"name": "voskobovich/yii2-linker-behavior",
@@ -3371,21 +3368,21 @@
},
{
"name": "yiisoft/yii2",
"version": "2.0.10",
"version": "2.0.11.1",
"source": {
"type": "git",
"url": "https://github.com/yiisoft/yii2-framework.git",
"reference": "5bfcb7a6dfa9771e2248eb8c4448613330f343ff"
"reference": "5c9c894b1d20bc1a39814063adf8a1aeb7c86f77"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/5bfcb7a6dfa9771e2248eb8c4448613330f343ff",
"reference": "5bfcb7a6dfa9771e2248eb8c4448613330f343ff",
"url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/5c9c894b1d20bc1a39814063adf8a1aeb7c86f77",
"reference": "5c9c894b1d20bc1a39814063adf8a1aeb7c86f77",
"shasum": ""
},
"require": {
"bower-asset/jquery": "2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
"bower-asset/jquery.inputmask": "~3.2.2",
"bower-asset/jquery.inputmask": "~3.2.2 | ~3.3.3",
"bower-asset/punycode": "1.3.*",
"bower-asset/yii2-pjax": "~2.0.1",
"cebe/markdown": "~1.0.0 | ~1.1.0",
@@ -3453,6 +3450,12 @@
"name": "Dmitry Naumenko",
"email": "d.naumenko.a@gmail.com",
"role": "Core framework development"
},
{
"name": "Boudewijn Vahrmeijer",
"email": "info@dynasource.eu",
"homepage": "http://dynasource.eu",
"role": "Core framework development"
}
],
"description": "Yii PHP Framework Version 2",
@@ -3461,7 +3464,7 @@
"framework",
"yii2"
],
"time": "2016-10-20 12:02:50"
"time": "2017-02-02 18:53:16"
},
{
"name": "yiisoft/yii2-bootstrap",
@@ -3642,54 +3645,6 @@
"bower-asset-main": "dist/typeahead.bundle.js"
}
},
{
"name": "fzaninotto/faker",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/fzaninotto/Faker.git",
"reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fzaninotto/Faker/zipball/44f9a286a04b80c76a4e5fb7aad8bb539b920123",
"reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123",
"shasum": ""
},
"require": {
"php": "^5.3.3|^7.0"
},
"require-dev": {
"ext-intl": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~1.5"
},
"type": "library",
"extra": {
"branch-alias": []
},
"autoload": {
"psr-4": {
"Faker\\": "src/Faker/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "François Zaninotto"
}
],
"description": "Faker is a PHP library that generates fake data for you.",
"keywords": [
"data",
"faker",
"fixtures"
],
"time": "2016-04-29 12:21:54"
},
{
"name": "phpspec/php-diff",
"version": "v1.1.0",
@@ -3775,53 +3730,6 @@
],
"time": "2016-11-24 09:42:29"
},
{
"name": "yiisoft/yii2-faker",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/yiisoft/yii2-faker.git",
"reference": "b88ca69ee226a3610b2c26c026c3203d7ac50f6c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yiisoft/yii2-faker/zipball/b88ca69ee226a3610b2c26c026c3203d7ac50f6c",
"reference": "b88ca69ee226a3610b2c26c026c3203d7ac50f6c",
"shasum": ""
},
"require": {
"fzaninotto/faker": "*",
"yiisoft/yii2": "*"
},
"type": "yii2-extension",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"yii\\faker\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Mark Jebri",
"email": "mark.github@yandex.ru"
}
],
"description": "Fixture generator. The Faker integration for the Yii framework.",
"keywords": [
"Fixture",
"faker",
"yii2"
],
"time": "2015-03-01 06:22:44"
},
{
"name": "yiisoft/yii2-gii",
"version": "2.0.5",
@@ -3878,7 +3786,9 @@
],
"aliases": [],
"minimum-stability": "dev",
"stability-flags": [],
"stability-flags": {
"bower-asset/snackbarjs": 20
},
"prefer-stable": true,
"prefer-lowest": false,
"platform": {

View File

@@ -40,11 +40,16 @@ return [
'showScriptName' => false,
'rules' => [
'' => 'panel/index',
'login' => 'auth/login',
'<controller>' => '<controller>/index',
'profile/<id:\d+>' => 'profile/index',
'admin/<controller>/<id:\d+>/<action:(create|update|delete)>' => 'admin/<controller>/<action>',
'admin/<controller>/<id:\d+>' => 'admin/<controller>/view',
'admin/<controller>s' => 'admin/<controller>/index',
[
'class' => 'yii\rest\UrlRule',
'controller' => ['api/room', 'api/item'],
'pluralize' => false,
],
],
],
'view' => [
@@ -54,20 +59,15 @@ return [
'force_charset' => 'UTF-8',
],
'formatter' => [
// 'dateFormat' => 'dd.MM.yyyy',
// 'datetimeFormat' => 'php:d.m.Y H:i',
'defaultTimeZone' => 'Europe/Kiev',
'timeZone' => 'Europe/Kiev',
],
'assetManager' => [
'appendTimestamp' => true,
'bundles' => [
'dmstr\web\AdminLteAsset' => [
'skin' => 'skin-purple',
'yii\bootstrap\BootstrapAsset' => [
'css' => [],
],
// 'yii\bootstrap\BootstrapAsset' => [
// 'css' => [],
// 'js' => [],
// ],
],
],
],

View File

@@ -12,6 +12,15 @@ $params = [
'connectionCheckTimeout' => 180,
'connectionCheckMaxIteration' => 2,
],
'items' => [
'rgb' => [
'fade-time' => 3000,
'color-time' => 3000,
'red' => 0,
'green' => 150,
'blue' => 150,
],
],
'telegramBotApiKey' => '',
'telegramBotChatId' => '',
];

View File

@@ -10,8 +10,6 @@ use app\models\LoginForm;
class AuthController extends Controller
{
public $layout = 'base';
public function behaviors()
{
return [
@@ -41,14 +39,14 @@ class AuthController extends Controller
return $this->goHome();
}
$this->layout = 'base';
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
}
$this->layout = 'base';
return $this->render('login', [
'model' => $model,
]);

View File

@@ -2,8 +2,10 @@
namespace app\controllers;
use app\models\Room;
use Yii;
use yii\filters\AccessControl;
use yii\helpers\Url;
use yii\web\Controller;
use yii\web\View;
@@ -29,14 +31,21 @@ class PanelController extends Controller
public function actionIndex()
{
$this->layout = 'main-no-content';
$this->view->registerJs('
var wsURL = "' . Yii::$app->params['wsURL']
. '/?type=user&id=' . Yii::$app->user->identity->id
. '&auth_token=' . Yii::$app->user->identity->getAuthToken()
. '";
var itemValueChartUrl = "' . Url::to(['/api/item/chart-data', 'access-token' => Yii::$app->user->identity->api_key]) . '"
', View::POS_HEAD);
return $this->render('index');
$roomModels = Room::find()->orderBy('sort_order')->all();
return $this->render('index', [
'roomModels' => $roomModels,
]);
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace app\controllers;
use app\models\User;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
class ProfileController extends Controller
{
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['@'],
],
],
],
];
}
public function actionIndex($id = false)
{
$user = $id ? User::findOne($id) : Yii::$app->user->identity;
return $this->render('index', [
'user' => $user,
]);
}
public function actionEdit()
{
$user = Yii::$app->user->identity;
$user->scenario = User::SCENARIO_UPDATE;
if ($user->load(Yii::$app->request->post())) {
$user->setPassword($user->password);
$user->generateAuthKey();
if ($user->save()) {
return $this->redirect(['index']);
}
}
return $this->render('edit', [
'user' => $user,
]);
}
}

View File

@@ -13,6 +13,7 @@ class SiteController extends Controller
'error' => [
'class' => 'app\components\ErrorAction',
'layout' => Yii::$app->user->isGuest ? 'base' : 'main',
'view' => Yii::$app->user->isGuest ? '/error/guest-error' : '/error/error',
],
];
}

View File

@@ -17,27 +17,23 @@ echo "<?php\n";
/* @var $dataProvider yii\data\ActiveDataProvider */
use yii\helpers\Html;
use <?= $generator->indexWidgetType === 'grid' ? "yii\\grid\\GridView" : "yii\\widgets\\ListView" ?>;
<?= $generator->enablePjax ? 'use yii\widgets\Pjax;' : '' ?>
<?= $generator->indexWidgetType === 'grid' ? null : "use yii\\widgets\\ListView;" ?>
<?= $generator->enablePjax ? 'use yii\widgets\Pjax;' . "\n" : '' ?>
$this->title = <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>;
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-index">
<p>
<?= "<?= " ?>Html::a(<?= $generator->generateString('Добавить') ?>, ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?php if(!empty($generator->searchModelClass)): ?>
<?= " <?php " . ($generator->indexWidgetType === 'grid' ? "// " : "") ?>echo $this->render('_search', ['model' => $searchModel]); ?>
<?php endif; ?>
<div class="card table-card">
<div class="table-card-actions">
<?= "<?= " ?>Html::a(<?= $generator->generateString('Добавить') ?>, ['create'], ['class' => 'btn btn-default btn-flat']) ?>
</div>
<?= $generator->enablePjax ? ' <?php Pjax::begin(); ?>' . "\n" : '' ?>
<?php if ($generator->indexWidgetType === 'grid'): ?>
<?= "<?= " ?>GridView::widget([
<?= "<?= " ?>\app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
<?= !empty($generator->searchModelClass) ? "'filterModel' => \$searchModel,\n 'columns' => [\n" : "'columns' => [\n"; ?>
<?php
$count = 0;

View File

@@ -24,8 +24,8 @@ $this->params['breadcrumbs'][] = $this->title;
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-view">
<p>
<?= "<?= " ?>Html::a(<?= \rmrevin\yii\fontawesome\FA::i('pencil') ?>, ['update', <?= $urlParams ?>], ['class' => 'btn btn-primary']) ?>
<?= "<?= " ?>Html::a(<?= \rmrevin\yii\fontawesome\FA::i('trash') ?>, ['delete', <?= $urlParams ?>], [
<?= "<?= " ?>Html::a('<?= \rmrevin\yii\fontawesome\FA::i('pencil') ?>', ['update', <?= $urlParams ?>], ['class' => 'btn btn-primary']) ?>
<?= "<?= " ?>Html::a('<?= \rmrevin\yii\fontawesome\FA::i('trash') ?>', ['delete', <?= $urlParams ?>], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => <?= $generator->generateString('Are you sure you want to delete this item?') ?>,

24
helpers/RGBHelper.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
namespace app\helpers;
class RGBHelper
{
/**
* @param integer $value
* @return integer
*/
public static function from8to10($value)
{
return $value * 4;
}
/**
* @param integer $value
* @return float|integer
*/
public static function from10to8($value)
{
return floor($value / 4);
}
}

View File

@@ -0,0 +1,45 @@
<?php
use yii\db\Migration;
class m170303_125418_create_item_widget extends Migration
{
public function safeUp()
{
$tableOptions = null;
if ($this->db->driverName === 'mysql') {
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
}
$this->createTable('item_widget', [
'id' => $this->primaryKey(),
'active' => $this->boolean()->defaultValue(true),
'type' => $this->smallInteger()->notNull(),
'value_type' => $this->smallInteger(),
'sort_order' => $this->integer()->defaultValue(0),
'item_id' => $this->integer()->notNull(),
'room_id' => $this->integer(),
'name' => $this->string()->notNull(),
'html_class' => $this->string(),
'icon' => $this->string()->notNull(),
], $tableOptions);
$this->createIndex('idx-item_widget-item_id', 'item_widget', 'item_id');
$this->addForeignKey('fk-item_widget-item_id', 'item_widget', 'item_id', 'item', 'id', 'CASCADE');
$this->createIndex('idx-item_widget-room_id', 'item_widget', 'room_id');
$this->addForeignKey('fk-item_widget-room_id', 'item_widget', 'room_id', 'room', 'id', 'CASCADE');
}
public function safeDown()
{
$this->dropForeignKey('fk-item_widget-item_id', 'item_widget');
$this->dropIndex('idx-item_widget-item_id', 'item_widget');
$this->dropForeignKey('fk-item_widget-room_id', 'item_widget');
$this->dropIndex('idx-item_widget-room_id', 'item_widget');
$this->dropTable('item_widget');
}
}

View File

@@ -0,0 +1,44 @@
<?php
use app\models\Item;
use app\models\ItemWidget;
use yii\db\Migration;
class m170303_150337_create_widgets_for_items extends Migration
{
public function safeUp()
{
foreach (Item::find()->all() as $item) {
$itemWidget = new ItemWidget();
$itemWidget->active = true;
$itemWidget->item_id = $item->id;
$itemWidget->room_id = $item->room_id;
$itemWidget->name = $item->name;
$itemWidget->html_class = $item->class;
$itemWidget->icon = 'fa-' . $item->icon;
$itemWidget->type = $item->type;
if ($item->type == 21 or $item->type == 22 or $item->type == 25 or $item->type == 26) {
$itemWidget->type = 20;
if ($item->type == 21) {
$itemWidget->value_type = ItemWidget::VALUE_TYPE_CELSIUS;
} elseif ($item->type == 22) {
$itemWidget->value_type = ItemWidget::VALUE_TYPE_PERCENT;
} elseif ($item->type == 25) {
$itemWidget->value_type = ItemWidget::VALUE_TYPE_BOOLEAN;
} elseif ($item->type == 26) {
$itemWidget->value_type = ItemWidget::VALUE_TYPE_DOOR;
}
}
$itemWidget->save();
}
}
public function safeDown()
{
return 0;
}
}

View File

@@ -0,0 +1,26 @@
<?php
use yii\db\Migration;
class m170303_164850_fix_items extends Migration
{
public function safeUp()
{
$this->dropColumn('item', 'active');
$this->dropColumn('item', 'room_id');
$this->dropColumn('item', 'bg');
$this->dropColumn('item', 'class');
$this->dropColumn('item', 'icon');
$this->dropColumn('item', 'sort_order');
}
public function safeDown()
{
$this->addColumn('item', 'active', $this->boolean()->defaultValue(true));
$this->addColumn('item', 'room_id', $this->integer()->notNull());
$this->addColumn('item', 'bg', $this->string());
$this->addColumn('item', 'class', $this->string());
$this->addColumn('item', 'icon', $this->string()->notNull());
$this->addColumn('item', 'sort_order', $this->integer()->defaultValue(0));
}
}

View File

@@ -0,0 +1,18 @@
<?php
use yii\db\Migration;
class m170312_221606_add_room_order_to_room extends Migration
{
public function safeUp()
{
$this->addColumn('room', 'sort_order', $this->integer()->defaultValue(0));
$this->dropColumn('room', 'bg');
}
public function safeDown()
{
$this->dropColumn('room', 'sort_order');
$this->addColumn('room', 'bg', $this->string());
}
}

View File

@@ -0,0 +1,26 @@
<?php
use yii\db\Migration;
class m170316_163700_add_user_fields extends Migration
{
public function safeUp()
{
$this->addColumn('user', 'name', $this->string()->after('email'));
$this->addColumn('user', 'avatar', $this->string()->after('name'));
$this->addColumn('user', 'room_id', $this->integer()->after('email'));
$this->createIndex('idx-user-room_id', 'user', 'room_id');
$this->addForeignKey('fk-user-room_id', 'user', 'room_id', 'room', 'id');
}
public function safeDown()
{
$this->dropForeignKey('fk-user-room_id', 'user');
$this->dropIndex('idx-user-room_id', 'user');
$this->dropColumn('user', 'name');
$this->dropColumn('user', 'avatar');
$this->dropColumn('user', 'room_id');
}
}

View File

@@ -11,25 +11,20 @@ use yii\helpers\ArrayHelper;
* This is the model class for table "item".
*
* @property integer $id
* @property boolean $active
* @property integer $type
* @property integer $update_interval
* @property boolean $enable_log
* @property integer $save_history_interval
* @property integer $room_id
* @property integer $board_id
* @property integer $pin
* @property string $url
* @property string $name
* @property string $icon
* @property string $bg
* @property string $class
* @property integer $sort_order
* @property string $default_value
*
* @property History[] $histories
* @property Room $room
* @property Board $board
* @property ItemWidget $widget
*/
class Item extends ActiveRecord
{
@@ -39,14 +34,15 @@ class Item extends ActiveRecord
const TYPE_VARIABLE_BOOLEAN_DOOR = 26;
const TYPE_VARIABLE_TEMPERATURE = 21;
const TYPE_VARIABLE_HUMIDITY = 22;
const TYPE_VARIABLE_LIGHT = 23;
const TYPE_RGB = 30;
const TYPE_LIGHT_LEVEL = 40;
const VALUE_ON = 1;
const VALUE_OFF = 0;
const MODE_RAINBOW = 'rainbow';
const MODE_BREATH = 'breath';
const RGB_MODE_STATIC = 'static';
const RGB_MODE_WAVE = 'wave';
const RGB_MODE_FADE = 'fade';
/**
* Used for WS handler
@@ -68,19 +64,12 @@ class Item extends ActiveRecord
public function rules()
{
return [
[['active', 'type', 'room_id', 'name', 'icon', 'bg', 'board_id'], 'required'],
[['type', 'name', 'board_id'], 'required'],
[
['type', 'update_interval', 'save_history_interval', 'room_id', 'sort_order', 'board_id', 'pin'],
['type', 'update_interval', 'save_history_interval', 'board_id', 'pin'],
'integer'
],
[['url', 'name', 'icon', 'bg', 'class', 'default_value'], 'string', 'max' => 255],
[
['room_id'],
'exist',
'skipOnError' => true,
'targetClass' => Room::className(),
'targetAttribute' => ['room_id' => 'id']
],
[['url', 'name', 'default_value'], 'string', 'max' => 255],
[
['board_id'],
'exist',
@@ -88,9 +77,7 @@ class Item extends ActiveRecord
'targetClass' => Board::className(),
'targetAttribute' => ['board_id' => 'id']
],
[['sort_order', 'update_interval', 'save_history_interval'], 'default', 'value' => 0],
[['active', 'enable_log'], 'default', 'value' => true],
[['active', 'enable_log'], 'boolean'],
[['update_interval', 'save_history_interval'], 'default', 'value' => 0],
[['default_value'], 'default', 'value' => null],
];
}
@@ -102,20 +89,14 @@ class Item extends ActiveRecord
{
return [
'id' => Yii::t('app', 'ID'),
'active' => Yii::t('app', 'Активно'),
'enable_log' => Yii::t('app', 'Логирование'),
'type' => Yii::t('app', 'Тип'),
'update_interval' => Yii::t('app', 'Интервал обновления'),
'save_history_interval' => Yii::t('app', 'Интервал сохранения в историю'),
'room_id' => Yii::t('app', 'Комната'),
'board_id' => Yii::t('app', 'Плата'),
'url' => Yii::t('app', 'Url'),
'pin' => Yii::t('app', 'Pin'),
'name' => Yii::t('app', 'Название'),
'icon' => Yii::t('app', 'Иконка'),
'bg' => Yii::t('app', 'CSS Background'),
'class' => Yii::t('app', 'CSS Класс'),
'sort_order' => Yii::t('app', 'Порядок сортировки'),
'default_value' => Yii::t('app', 'Значение по умолчанию'),
];
}
@@ -131,17 +112,17 @@ class Item extends ActiveRecord
/**
* @return \yii\db\ActiveQuery
*/
public function getRoom()
public function getBoard()
{
return $this->hasOne(Room::className(), ['id' => 'room_id'])->inverseOf('items');
return $this->hasOne(Board::className(), ['id' => 'board_id'])->inverseOf('items');
}
/**
* @return \yii\db\ActiveQuery
*/
public function getBoard()
public function getWidget()
{
return $this->hasOne(Board::className(), ['id' => 'board_id'])->inverseOf('items');
return $this->hasOne(ItemWidget::className(), ['item_id' => 'id'])->inverseOf('item');
}
/**
@@ -165,8 +146,8 @@ class Item extends ActiveRecord
self::TYPE_VARIABLE_BOOLEAN_DOOR => 'Переменная boolean дверь',
self::TYPE_VARIABLE_TEMPERATURE => 'Переменная температура',
self::TYPE_VARIABLE_HUMIDITY => 'Переменная влажность',
self::TYPE_RGB => 'RGB LED',
self::TYPE_LIGHT_LEVEL => 'Уровень освещенности',
self::TYPE_VARIABLE_LIGHT => 'Переменная освещенность',
self::TYPE_RGB => 'RGB',
];
}
@@ -180,16 +161,15 @@ class Item extends ActiveRecord
/**
* @param bool $prependId
* @param bool $appendRoomName
* @return array
*/
public static function getList($prependId = false, $appendRoomName = false)
public static function getList($prependId = false)
{
/** @var self[] $models */
$models = self::find()->all();
$result = [];
if (!$appendRoomName and !$prependId) {
if (!$prependId) {
return ArrayHelper::map($models, 'id', 'name');
}
@@ -202,10 +182,6 @@ class Item extends ActiveRecord
$title .= $model->name;
if ($appendRoomName) {
$title .= ' - ' . $model->room->name;
}
$result[$model->id] = $title;
}
@@ -215,43 +191,28 @@ class Item extends ActiveRecord
/**
* @return array
*/
public static function getModesArray()
public static function getRGBModesArray()
{
return [
self::MODE_RAINBOW,
self::MODE_BREATH,
self::RGB_MODE_STATIC,
self::RGB_MODE_WAVE,
self::RGB_MODE_FADE,
];
}
/**
* Returns normalized default value
* @return mixed
*/
public function getDefaultValue()
public function getDefaultNAValue()
{
if (!is_null($this->default_value)) {
return $this->default_value;
}
switch ($this->type) {
case Item::TYPE_SWITCH:
case Item::TYPE_VARIABLE_BOOLEAN:
case Item::TYPE_VARIABLE_BOOLEAN_DOOR:
return false;
case Item::TYPE_VARIABLE_TEMPERATURE:
case Item::TYPE_VARIABLE_HUMIDITY:
case Item::TYPE_LIGHT_LEVEL:
return 0;
case Item::TYPE_RGB:
case self::TYPE_RGB:
return [
0,
0,
0,
'mode' => 'static',
'red' => 0,
'green' => 0,
'blue' => 0,
'fade_time' => Yii::$app->params['items']['rgb']['fade-time'],
];
default:
return 'N/A';
}
return false;
}
}

View File

@@ -63,8 +63,6 @@ class ItemSearch extends Item
'type' => $this->type,
'update_interval' => $this->update_interval,
'save_history_interval' => $this->save_history_interval,
'room_id' => $this->room_id,
'sort_order' => $this->sort_order,
]);
$query->andFilterWhere(['like', 'url', $this->url])

159
models/ItemWidget.php Normal file
View File

@@ -0,0 +1,159 @@
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
/**
* This is the model class for table "item_widget".
*
* @property integer $id
* @property boolean $active
* @property integer $type
* @property integer $value_type
* @property integer $sort_order
* @property integer $item_id
* @property integer $room_id
* @property string $name
* @property string $html_class
* @property string $icon
*
* @property Item $item
* @property Room $room
*/
class ItemWidget extends ActiveRecord
{
const TYPE_SWITCH = 10;
const TYPE_VARIABLE = 20;
const TYPE_RGB = 30;
const VALUE_TYPE_BOOLEAN = 10;
const VALUE_TYPE_DOOR = 20;
const VALUE_TYPE_CELSIUS = 30;
const VALUE_TYPE_PERCENT = 40;
/**
* @inheritdoc
*/
public static function tableName()
{
return 'item_widget';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['sort_order', 'item_id', 'room_id', 'type', 'value_type'], 'integer'],
[['active'], 'boolean'],
[['active'], 'default', 'value' => true],
[['type'], 'in', 'range' => self::getTypesArray()],
[['value_type'], 'in', 'range' => self::getValueTypesArray()],
[['name', 'item_id', 'icon', 'type'], 'required'],
[['name', 'html_class', 'icon'], 'string', 'max' => 255],
[['sort_order'], 'default', 'value' => 0],
[['item_id'], 'exist', 'skipOnError' => true, 'targetClass' => Item::className(), 'targetAttribute' => ['item_id' => 'id']],
[['room_id'], 'exist', 'skipOnError' => true, 'targetClass' => Room::className(), 'targetAttribute' => ['room_id' => 'id']],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'active' => Yii::t('app', 'Активно'),
'type' => Yii::t('app', 'Тип'),
'value_type' => Yii::t('app', 'Тип Значения'),
'sort_order' => Yii::t('app', 'Порядок сортировки'),
'item_id' => Yii::t('app', 'Элемент'),
'room_id' => Yii::t('app', 'Комната'),
'name' => Yii::t('app', 'Название'),
'html_class' => Yii::t('app', 'HTML класс'),
'icon' => Yii::t('app', 'Иконка'),
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getItem()
{
return $this->hasOne(Item::className(), ['id' => 'item_id'])->inverseOf('widget');
}
/**
* @return \yii\db\ActiveQuery
*/
public function getRoom()
{
return $this->hasOne(Room::className(), ['id' => 'room_id'])->inverseOf('itemWidgets');
}
/**
* @inheritdoc
* @return ItemWidgetQuery the active query used by this AR class.
*/
public static function find()
{
return new ItemWidgetQuery(get_called_class());
}
/**
* @return string
*/
public function getName()
{
if ($this->name != null) {
return $this->name;
}
return $this->item->name;
}
/**
* @return array
*/
public static function getTypes()
{
return [
self::TYPE_SWITCH => 'Переключатель',
self::TYPE_VARIABLE => 'Переменная',
self::TYPE_RGB => 'RGB',
];
}
/**
* @return array
*/
public static function getTypesArray()
{
return array_keys(self::getTypes());
}
/**
* @return array
*/
public static function getValueTypes()
{
return [
self::VALUE_TYPE_BOOLEAN => 'Boolean',
self::VALUE_TYPE_DOOR => 'Дверь',
self::VALUE_TYPE_CELSIUS => 'Цельсии',
self::VALUE_TYPE_PERCENT => 'Проценты',
];
}
/**
* @return array
*/
public static function getValueTypesArray()
{
return array_keys(self::getValueTypes());
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace app\models;
use yii\db\ActiveQuery;
/**
* This is the ActiveQuery class for [[ItemWidget]].
*
* @see ItemWidget
*/
class ItemWidgetQuery extends ActiveQuery
{
/**
* @return $this
*/
public function active()
{
return $this->andWhere(['active' => true]);
}
/**
* @return $this
*/
public function switches()
{
return $this->andWhere(['type' => ItemWidget::TYPE_SWITCH]);
}
/**
* @return $this
*/
public function variables()
{
return $this->andWhere(['type' => ItemWidget::TYPE_VARIABLE]);
}
/**
* @return $this
*/
public function rgb()
{
return $this->andWhere(['type' => ItemWidget::TYPE_RGB]);
}
/**
* @inheritdoc
* @return ItemWidget[]|array
*/
public function all($db = null)
{
return parent::all($db);
}
/**
* @inheritdoc
* @return ItemWidget|array|null
*/
public function one($db = null)
{
return parent::one($db);
}
}

View File

@@ -3,6 +3,7 @@
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;
/**
@@ -10,11 +11,11 @@ use yii\helpers\ArrayHelper;
*
* @property integer $id
* @property string $name
* @property string $bg
* @property integer $sort_order
*
* @property Item[] $items
*/
class Room extends \yii\db\ActiveRecord
class Room extends ActiveRecord
{
/**
* @inheritdoc
@@ -31,7 +32,9 @@ class Room extends \yii\db\ActiveRecord
{
return [
[['name'], 'required'],
[['name', 'bg'], 'string', 'max' => 255],
[['name'], 'string', 'max' => 255],
[['sort_order'], 'integer'],
[['sort_order'], 'default', 'value' => 0],
];
}
@@ -43,25 +46,16 @@ class Room extends \yii\db\ActiveRecord
return [
'id' => Yii::t('app', 'ID'),
'name' => Yii::t('app', 'Название'),
'bg' => Yii::t('app', 'Фон'),
'sort_order' => Yii::t('app', 'Порядок сортировки'),
];
}
/**
* @return \yii\db\ActiveQuery
* @return \yii\db\ActiveQuery|ItemWidgetQuery
*/
public function getItems()
public function getItemWidgets()
{
return $this->hasMany(Item::className(), ['room_id' => 'id'])->inverseOf('room');
}
/**
* @inheritdoc
* @return RoomQuery the active query used by this AR class.
*/
public static function find()
{
return new RoomQuery(get_called_class());
return $this->hasMany(ItemWidget::className(), ['room_id' => 'id'])->inverseOf('room');
}
/**

View File

@@ -1,34 +0,0 @@
<?php
namespace app\models;
/**
* This is the ActiveQuery class for [[Room]].
*
* @see Room
*/
class RoomQuery extends \yii\db\ActiveQuery
{
/*public function active()
{
return $this->andWhere('[[status]]=1');
}*/
/**
* @inheritdoc
* @return Room[]|array
*/
public function all($db = null)
{
return parent::all($db);
}
/**
* @inheritdoc
* @return Room|array|null
*/
public function one($db = null)
{
return parent::one($db);
}
}

View File

@@ -18,8 +18,8 @@ class RoomSearch extends Room
public function rules()
{
return [
[['id'], 'integer'],
[['name', 'bg'], 'safe'],
[['id', 'sort_order'], 'integer'],
[['name'], 'safe'],
];
}
@@ -60,10 +60,10 @@ class RoomSearch extends Room
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'sort_order' => $this->sort_order,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'bg', $this->bg]);
$query->andFilterWhere(['like', 'name', $this->name]);
return $dataProvider;
}

View File

@@ -18,6 +18,9 @@ use yii\web\IdentityInterface;
* @property string $auth_key
* @property string $auth_token
* @property string $api_key
* @property string $name
* @property string $avatar
* @property integer $room_id
* @property integer $status
* @property integer $group
* @property integer $created_at
@@ -26,13 +29,15 @@ use yii\web\IdentityInterface;
* @property boolean $isAdmin
*
* @property string $password write-only password
*
* @property Room $room
*/
class User extends ActiveRecord implements IdentityInterface
{
const SCENARIO_CREATE = 'create';
const SCENARIO_UPDATE = 'update';
const STATUS_DELETED = 0;
const STATUS_DISABLED = 0;
const STATUS_ACTIVE = 10;
const GROUP_ADMIN = 10;
@@ -65,14 +70,15 @@ class User extends ActiveRecord implements IdentityInterface
{
return [
[['username', 'email'], 'required'],
[['api_key', 'auth_token'], 'string'],
[['group'], 'integer'],
[['api_key', 'auth_token', 'name', 'avatar'], 'string'],
[['group', 'room_id'], 'integer'],
[['password'], 'required', 'on' => self::SCENARIO_CREATE],
[['password'], 'safe', 'on' => self::SCENARIO_UPDATE],
[['auth_token'], 'default', 'value' => null],
[['status'], 'default', 'value' => self::STATUS_ACTIVE],
[['status'], 'in', 'range' => self::getStatusesArray()],
[['group'], 'in', 'range' => self::getGroupsArray()],
[['room_id'], 'exist', 'skipOnError' => true, 'targetClass' => Room::className(), 'targetAttribute' => ['room_id' => 'id']],
];
}
@@ -88,6 +94,9 @@ class User extends ActiveRecord implements IdentityInterface
'email' => 'Email',
'status' => 'Статус',
'group' => 'Группа',
'name' => 'Имя',
'avatar' => 'Аватар',
'room_id' => 'Комната',
'api_key' => 'API ключ',
'auth_token' => 'Auth токен',
'created_at' => 'Дата создания',
@@ -102,7 +111,7 @@ class User extends ActiveRecord implements IdentityInterface
{
return [
self::STATUS_ACTIVE => 'Активен',
self::STATUS_DELETED => 'Удален',
self::STATUS_DISABLED => 'Не активен',
];
}
@@ -260,12 +269,13 @@ class User extends ActiveRecord implements IdentityInterface
}
/**
* @param int $size
* @return string
*/
public function getAvatar()
public function getAvatar($size = 45)
{
$hash = md5($this->email);
return 'https://www.gravatar.com/avatar/' . $hash . '?s=45';
return 'https://www.gravatar.com/avatar/' . $hash . '?s=' . $size;
}
/**
@@ -276,6 +286,14 @@ class User extends ActiveRecord implements IdentityInterface
return $this->hasMany(History::className(), ['user_id' => 'id'])->inverseOf('user');
}
/**
* @return \yii\db\ActiveQuery
*/
public function getRoom()
{
return $this->hasOne(Room::className(), ['id' => 'room_id']);
}
/**
* @return bool
*/

View File

@@ -0,0 +1,125 @@
<?php
namespace app\modules\admin\controllers;
use Yii;
use app\models\ItemWidget;
use app\modules\admin\models\ItemWidgetSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* ItemWidgetController implements the CRUD actions for ItemWidget model.
*/
class ItemWidgetController extends Controller
{
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all ItemWidget models.
* @return mixed
*/
public function actionIndex()
{
$searchModel = new ItemWidgetSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single ItemWidget model.
* @param integer $id
* @return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new ItemWidget model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate()
{
$model = new ItemWidget();
$model->active = true;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing ItemWidget model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id
* @return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing ItemWidget model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* @param integer $id
* @return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the ItemWidget model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* @param integer $id
* @return ItemWidget the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = ItemWidget::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}

View File

@@ -4,7 +4,7 @@ namespace app\modules\admin\controllers;
use Yii;
use app\models\User;
use app\models\UserSearch;
use app\modules\admin\models\UserSearch;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\NotFoundHttpException;

View File

@@ -18,7 +18,7 @@ class ItemSearch extends Item
public function rules()
{
return [
[['id', 'type', 'room_id', 'board_id', 'sort_order', 'pin'], 'integer'],
[['id', 'type', 'board_id', 'pin'], 'integer'],
[['url', 'name'], 'safe'],
];
}
@@ -61,9 +61,7 @@ class ItemSearch extends Item
$query->andFilterWhere([
'id' => $this->id,
'type' => $this->type,
'room_id' => $this->room_id,
'board_id' => $this->board_id,
'sort_order' => $this->sort_order,
'pin' => $this->pin,
]);

View File

@@ -0,0 +1,75 @@
<?php
namespace app\modules\admin\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\ItemWidget;
/**
* ItemWidgetSearch represents the model behind the search form about `app\models\ItemWidget`.
*/
class ItemWidgetSearch extends ItemWidget
{
/**
* @inheritdoc
*/
public function rules()
{
return [
[['id', 'active', 'sort_order', 'item_id', 'room_id'], 'integer'],
[['name', 'html_class', 'icon'], 'safe'],
];
}
/**
* @inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return ActiveDataProvider
*/
public function search($params)
{
$query = ItemWidget::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'active' => $this->active,
'sort_order' => $this->sort_order,
'item_id' => $this->item_id,
'room_id' => $this->room_id,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'html_class', $this->html_class])
->andFilterWhere(['like', 'icon', $this->icon]);
return $dataProvider;
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace app\models;
namespace app\modules\admin\models;
use Yii;
use yii\base\Model;
@@ -18,8 +18,8 @@ class UserSearch extends User
public function rules()
{
return [
[['id', 'status', 'group', 'created_at', 'updated_at'], 'integer'],
[['username', 'email'], 'safe'],
[['id', 'status', 'group', 'created_at', 'updated_at', 'room_id'], 'integer'],
[['username', 'email', 'name'], 'safe'],
];
}
@@ -64,9 +64,12 @@ class UserSearch extends User
'group' => $this->group,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'room_id' => $this->room_id,
]);
$query->andFilterWhere(['like', 'username', $this->username])
$query
->andFilterWhere(['like', 'username', $this->username])
->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'email', $this->email]);
return $dataProvider;

View File

@@ -11,24 +11,21 @@ use yii\widgets\Pjax;
$this->title = 'Устройства';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="board-index">
<p>
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<div class="card table-card">
<div class="table-card-actions">
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-default btn-flat']) ?>
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'id',
'contentOptions' => ['style' => 'width: 5%']
],
'id',
'name',
[
'attribute' => 'type',
@@ -49,5 +46,6 @@ $this->params['breadcrumbs'][] = $this->title;
['class' => 'app\components\ActionButtonColumn'],
],
]); ?>
<?php Pjax::end(); ?>
</div>

View File

@@ -10,19 +10,17 @@ use yii\widgets\Pjax;
$this->title = 'События';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="event-index">
<p>
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<div class="card table-card">
<div class="table-card-actions">
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-default btn-flat']) ?>
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
'filterModel' => $searchModel,
'columns' => [
[

View File

@@ -7,21 +7,20 @@
use yii\helpers\Html;
use yii\grid\GridView;
use yii\widgets\Pjax;
$this->title = 'Histories';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="history-index">
<p>
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<div class="card table-card">
<div class="table-card-actions">
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-default btn-flat']) ?>
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
'filterModel' => $searchModel,
'columns' => [
'id',

View File

@@ -0,0 +1,128 @@
<?php
/* @var $this yii\web\View */
/* @var $model app\models\ItemWidget */
/* @var $form yii\widgets\ActiveForm */
use app\models\Item;
use app\models\ItemWidget;
use app\models\Room;
use kartik\select2\Select2;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
\app\assets\FontawesomeIconpickerAsset::register($this);
$this->registerJs("
$('.fontawesome-iconpicker-input').iconpicker({container: 'body', inputSearch: true,});
", \yii\web\View::POS_READY);
?>
<div class="item-widget-form">
<?php $form = ActiveForm::begin(); ?>
<div class="row">
<div class="col-sm-6">
<?= $form->field($model, 'item_id')->widget(Select2::className(), [
'data' => Item::getList(true),
'pluginEvents' => [
'change' => "function(e) {
$.get({
url: '" . \yii\helpers\Url::to([
'/api/item/view',
'access-token' => Yii::$app->user->identity->api_key,
]) . "&id=' + $('#itemwidget-item_id').val(),
success: function (data) {
if (data) {
$('#itemwidget-name').val(data.name).change();
var widgetType = data.type;
var valueType;
if (data.type == 20 || data.type == 21 || data.type == 22 || data.type == 25 || data.type == 26) {
widgetType = 20;
$('.field-itemwidget-value_type').fadeIn().removeClass('hidden');
}
if (data.type == 21) {
valueType = 30;
}
if (data.type == 22) {
valueType = 40;
}
if (data.type == 25) {
valueType = 10;
}
if (data.type == 26) {
valueType = 20;
}
$('#itemwidget-type').val(widgetType).change();
$('#itemwidget-value_type').val(valueType).change();
}
}
});
}",
],
'options' => [
'placeholder' => 'Выберите элемент ...',
],
]) ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'type')->widget(Select2::className(), [
'data' => ItemWidget::getTypes(),
'pluginEvents' => [
'change' => "function(e) {
if (parseInt($(this).val()) == 20) {
$('.field-itemwidget-value_type').fadeIn().removeClass('hidden');
} else {
$('.field-itemwidget-value_type').fadeOut().addClass('hidden');
}
}",
],
'options' => [
'placeholder' => 'Выберите тип ...',
],
]) ?>
<?= $form->field($model, 'value_type', ['options' => ['class' => 'form-group hidden']])->widget(Select2::className(), [
'data' => ItemWidget::getValueTypes(),
'options' => [
'placeholder' => 'Выберите тип значения ...',
],
]) ?>
<?= $form->field($model, 'active')->checkbox() ?>
</div>
<div class="col-sm-6">
<?= $form->field($model, 'icon')->textInput([
'maxlength' => true,
'class' => 'fontawesome-iconpicker-input form-control'
]) ?>
<?= $form->field($model, 'room_id')->widget(Select2::className(), [
'data' => Room::getList(),
'options' => [
'placeholder' => 'Выберите комнату ...',
],
]) ?>
<?= $form->field($model, 'html_class')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'sort_order')->input('number') ?>
</div>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Добавить' : 'Сохранить', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

View File

@@ -0,0 +1,18 @@
<?php
/* @var $this yii\web\View */
/* @var $model app\models\ItemWidget */
use yii\helpers\Html;
$this->title = 'Добавить Item Widget';
$this->params['breadcrumbs'][] = ['label' => 'Item Widgets', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="item-widget-create">
<?= $this->render('_form', [
'model' => $model,
]) ?>
</div>

View File

@@ -0,0 +1,53 @@
<?php
/* @var $this yii\web\View */
/* @var $searchModel app\modules\admin\models\ItemWidgetSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
use app\models\Item;
use app\models\ItemWidget;
use app\models\Room;
use yii\helpers\Html;
use yii\widgets\Pjax;
$this->title = 'Виджеты';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="card table-card">
<div class="table-card-actions">
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-default btn-flat']) ?>
</div>
<?php Pjax::begin(); ?>
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
'id',
'name',
'icon',
[
'attribute' => 'room_id',
'filter' => Room::getList(),
'value' => function ($model) {
/** @var $model ItemWidget */
return $model->room->name;
},
],
[
'attribute' => 'item_id',
'filter' => Item::getList(),
'value' => function ($model) {
/** @var $model ItemWidget */
return $model->item->name;
},
],
'active:boolean',
['class' => 'app\components\ActionButtonColumn'],
],
]); ?>
<?php Pjax::end(); ?>
</div>

View File

@@ -0,0 +1,19 @@
<?php
/* @var $this yii\web\View */
/* @var $model app\models\ItemWidget */
use yii\helpers\Html;
$this->title = 'Изменить Item Widget: ' . $model->name;
$this->params['breadcrumbs'][] = ['label' => 'Item Widgets', 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
$this->params['breadcrumbs'][] = 'Редактирование';
?>
<div class="item-widget-update">
<?= $this->render('_form', [
'model' => $model,
]) ?>
</div>

View File

@@ -0,0 +1,40 @@
<?php
/* @var $this yii\web\View */
/* @var $model app\models\ItemWidget */
use yii\helpers\Html;
use yii\widgets\DetailView;
$this->title = $model->name;
$this->params['breadcrumbs'][] = ['label' => 'Item Widgets', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="item-widget-view">
<p>
<?= Html::a('<i class="fa fa-pencil"></i>', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a('<i class="fa fa-trash"></i>', ['delete', 'id' => $model->id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => 'Are you sure you want to delete this item?',
'method' => 'post',
],
]) ?>
</p>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'active',
'sort_order',
'item_id',
'room_id',
'name',
'html_class',
'icon',
],
]) ?>
</div>

View File

@@ -12,7 +12,6 @@ use yii\helpers\Html;
use yii\widgets\ActiveForm;
if ($model->isNewRecord) {
$model->active = true;
$model->enable_log = true;
}
?>
@@ -23,8 +22,6 @@ if ($model->isNewRecord) {
<div class="row">
<div class="col-md-6">
<h2>Основные настройки</h2>
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'type')->dropDownList(Item::getTypesArray(), [
@@ -50,38 +47,8 @@ if ($model->isNewRecord) {
<?= $form->field($model, 'save_history_interval')->input('number') ?>
</div>
<div class="col-md-6">
<h2>Сниппет</h2>
<?= $form->field($model, 'icon')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'bg')->dropDownList([
'light-blue' => 'Светло-синий',
'aqua' => 'Бирюзовый',
'green' => 'Зеленый',
'yellow' => 'Желтый',
'red' => 'Красный',
'gray' => 'Серый',
'navy' => 'Navy',
'teal' => 'Teal',
'purple' => 'Фиолетовый',
'orange' => 'Оранжевый',
'maroon' => 'Бордовый',
'black' => 'Черный',
]) ?>
<?= $form->field($model, 'class')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'room_id')->dropDownList(
ArrayHelper::map(Room::find()->all(), 'id', 'name')
) ?>
<?= $form->field($model, 'sort_order')->input('number') ?>
</div>
</div>
<?= $form->field($model, 'active')->checkbox() ?>
<?= $form->field($model, 'enable_log')->checkbox() ?>
<div class="form-group">

View File

@@ -13,40 +13,28 @@ use yii\widgets\Pjax;
$this->title = 'Элементы';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="item-index">
<p>
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-success']) ?>
<div class="card table-card">
<div class="table-card-actions">
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-default btn-flat']) ?>
<?= Html::a('Обновить на сервере', [
'/api/panel/update-items',
'access-token' => Yii::$app->user->identity->api_key,
], [
'class' => 'btn btn-default ajax-call',
'class' => 'btn btn-default btn-flat ajax-call',
]) ?>
</p>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'id',
'contentOptions' => ['style' => 'width: 5%']
],
'id',
'name',
[
'attribute' => 'room_id',
'filter' => Room::getList(),
'value' => function ($model) {
/** @var $model Item */
return $model->room->name;
},
],
[
'attribute' => 'board_id',
'filter' => Board::getList(),
@@ -68,5 +56,6 @@ $this->params['breadcrumbs'][] = $this->title;
['class' => 'app\components\ActionButtonColumn'],
],
]); ?>
<?php Pjax::end(); ?>
</div>

View File

@@ -28,18 +28,13 @@ $this->params['breadcrumbs'][] = $this->title;
'attributes' => [
'id',
'name',
'icon',
'bg',
'class',
['attribute' => 'board_id', 'value' => $model->board->name],
'pin',
'type',
'default_value',
'update_interval',
'save_history_interval',
['attribute' => 'room_id', 'value' => $model->room->name],
'url:url',
'sort_order',
],
]) ?>

View File

@@ -14,12 +14,7 @@ use yii\widgets\ActiveForm;
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'bg')->dropDownList([
'success' => 'Зеленый',
'danger' => 'Красный',
'warning' => 'Оранжевый',
'info' => 'Синий',
]) ?>
<?= $form->field($model, 'sort_order')->input('number') ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Добавить' : 'Сохранить', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>

View File

@@ -7,26 +7,25 @@
use yii\helpers\Html;
use yii\grid\GridView;
use yii\widgets\Pjax;
$this->title = 'Комнаты';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="room-index">
<p>
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<div class="card table-card">
<div class="table-card-actions">
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-default btn-flat']) ?>
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
'filterModel' => $searchModel,
'columns' => [
'id',
'name',
'bg',
'sort_order',
['class' => 'app\components\ActionButtonColumn'],
],

View File

@@ -28,7 +28,7 @@ $this->params['breadcrumbs'][] = $this->title;
'attributes' => [
'id',
'name',
'bg',
'sort_order',
],
]) ?>

View File

@@ -11,10 +11,6 @@ $this->params['breadcrumbs'][] = $this->title;
?>
<div class="setting-index">
<h1 class="page-header">
<?= $this->title ?>
</h1>
<form action="<?= Url::to(['save']) ?>" method="post">
<input type="hidden" name="<?= Yii::$app->request->csrfParam; ?>" value="<?= Yii::$app->request->csrfToken; ?>">

View File

@@ -36,7 +36,7 @@ if ($model->isNewRecord) {
<h2>Выполнить</h2>
<?= $form->field($model, 'item_id')->widget(Select2::className(), [
'data' => Item::getList(false, true),
'data' => Item::getList(true),
'options' => [
'placeholder' => 'Выберите элемент ...',
],

View File

@@ -11,18 +11,17 @@ use yii\widgets\Pjax;
$this->title = 'Задачи';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="task-index">
<p>
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<div class="card table-card">
<div class="table-card-actions">
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-default btn-flat']) ?>
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
'filterModel' => $searchModel,
'columns' => [
'id',

View File

@@ -86,7 +86,7 @@ if ($model->isNewRecord) {
<div class="row type-10 type-20">
<div class="col-sm-6">
<?= $form->field($model, 'item_id')->widget(Select2::className(), [
'data' => Item::getList(false, true),
'data' => Item::getList(true),
'options' => [
'placeholder' => 'Выберите элемент ...',
],

View File

@@ -11,30 +11,26 @@ use yii\widgets\Pjax;
$this->title = 'Триггеры';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="trigger-index">
<p>
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-success']) ?>
<div class="card table-card">
<div class="table-card-actions">
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-default btn-flat']) ?>
<?= Html::a('Обновить на сервере', [
'/api/panel/schedule-triggers',
'access-token' => Yii::$app->user->identity->api_key
], [
'class' => 'btn btn-default ajax-call',
'class' => 'btn btn-default btn-flat ajax-call',
]) ?>
</p>
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'id',
'contentOptions' => ['style' => 'width: 5%']
],
'id',
'name',
[
'filter' => Trigger::getTypes(),

View File

@@ -4,7 +4,9 @@
/* @var $model app\models\User */
/* @var $form yii\widgets\ActiveForm */
use app\models\Room;
use app\models\User;
use kartik\widgets\Select2;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
@@ -26,10 +28,21 @@ if ($model->isNewRecord) {
<?= $form->field($model, 'email')->input('email') ?>
<?= $form->field($model, 'name')->textInput() ?>
<?= $form->field($model, 'avatar')->textInput() ?>
<?= $form->field($model, 'status')->dropDownList(User::getStatuses()) ?>
<?= $form->field($model, 'group')->dropDownList(User::getGroups()) ?>
<?= $form->field($model, 'room_id')->widget(Select2::className(), [
'data' => Room::getList(),
'options' => [
'placeholder' => 'Выберите комнату ...',
],
]) ?>
<?= $form->field($model, 'api_key')->textInput()->hint($randomApiKey) ?>
<div class="form-group">

View File

@@ -11,8 +11,6 @@ $this->params['breadcrumbs'][] = $this->title;
?>
<div class="user-create">
<h1 class="page-header"><?= $this->title ?></h1>
<?= $this->render('_form', [
'model' => $model,
]) ?>

View File

@@ -1,32 +1,41 @@
<?php
/* @var $this yii\web\View */
/* @var $searchModel app\models\UserSearch */
/* @var $searchModel \app\modules\admin\models\UserSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
use app\models\Room;
use app\models\User;
use yii\helpers\Html;
use yii\grid\GridView;
use yii\widgets\Pjax;
$this->title = 'Пользователи';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="user-index">
<p><?= Html::a('Добавить', ['create'], ['class' => 'btn btn-success']) ?></p>
<div class="card table-card">
<div class="table-card-actions">
<?= Html::a('Добавить', ['create'], ['class' => 'btn btn-default btn-flat']) ?>
</div>
<?= GridView::widget([
<?php Pjax::begin(); ?>
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
'columns' => [
[
'attribute' => 'id',
'contentOptions' => ['style' => 'width: 5%']
],
'id',
'username',
'email',
'name',
[
'attribute' => 'room_id',
'filter' => Room::getList(),
'value' => function ($model) {
/** @var $model User */
return $model->room ? $model->room->name : null;
},
],
[
'filter' => User::getStatuses(),
'attribute' => 'status',
@@ -47,4 +56,5 @@ $this->params['breadcrumbs'][] = $this->title;
['class' => 'app\components\ActionButtonColumn'],
],
]); ?>
<?php Pjax::end(); ?>
</div>

View File

@@ -10,8 +10,6 @@ $this->params['breadcrumbs'][] = 'Редактирование';
?>
<div class="user-update">
<h1 class="page-header"><?= $this->title ?></h1>
<?= $this->render('_form', [
'model' => $model,
]) ?>

View File

@@ -12,8 +12,7 @@ $this->params['breadcrumbs'][] = $this->title;
?>
<div class="user-view">
<h1 class="page-header">
<?= $this->title ?>
<p>
<?= Html::a('Редактировать', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a('Удалить', ['delete', 'id' => $model->id], [
'class' => 'btn btn-danger',
@@ -22,13 +21,14 @@ $this->params['breadcrumbs'][] = $this->title;
'method' => 'post',
],
]) ?>
</h1>
</p>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'username',
'name',
'email:email',
[
'attribute' => 'status',
@@ -38,6 +38,10 @@ $this->params['breadcrumbs'][] = $this->title;
'attribute' => 'group',
'value' => $model->getGroupLabel(),
],
[
'attribute' => 'room_id',
'value' => $model->room ? $model->room->name : null,
],
'api_key',
'created_at:datetime',
'updated_at:datetime',

View File

@@ -93,44 +93,6 @@ class WebSocketAPIBridge
]);
}
/**
* @param int $itemID
* @param int $red
* @param int $green
* @param int $blue
* @param boolean $fade
* @return bool
* @internal param array $rgbData
*/
public function rgb($itemID, $red, $green, $blue, $fade)
{
return $this->send([
'type' => 'rgb',
'item_id' => $itemID,
'red' => $red,
'green' => $green,
'blue' => $blue,
'fade' => $fade,
]);
}
/**
* @param int $itemID
* @param string $mode
* @param bool $start
* @return bool
* @internal param array $rgbData
*/
public function rgbMode($itemID, $mode, $start)
{
return $this->send([
'type' => 'rgbMode',
'item_id' => $itemID,
'mode' => $mode,
'start' => $start,
]);
}
/**
* @param int $triggerID
* @return bool

View File

@@ -3,18 +3,22 @@
namespace app\modules\api\controllers;
use app\models\Board;
use app\models\History;
use app\models\Item;
use app\modules\api\components\WebSocketAPIBridge;
use Yii;
use yii\base\InvalidParamException;
use yii\base\NotSupportedException;
use yii\rest\Controller;
use yii\rest\ActiveController;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;
use yii\web\ServerErrorHttpException;
use yii\web\UnprocessableEntityHttpException;
class ItemController extends Controller
class ItemController extends ActiveController
{
public $modelClass = 'app\models\Item';
/**
* @inheritdoc
*/
@@ -24,19 +28,10 @@ class ItemController extends Controller
'turn-on' => ['POST'],
'turn-off' => ['POST'],
'rgb' => ['POST'],
'rgb-mode' => ['POST'],
'value' => ['GET'],
];
}
/**
* @throws NotSupportedException
*/
public function actionIndex()
{
throw new NotSupportedException();
}
/**
* @param $item_id
* @return array
@@ -138,21 +133,75 @@ class ItemController extends Controller
/**
* @param int $item_id
* @param string $mode
* @param int $fade_time
* @param int $red
* @param int $green
* @param int $blue
* @param bool $fade
* @param int $color_time
* @return array
* @throws BadRequestHttpException
* @throws NotSupportedException
* @throws ServerErrorHttpException
* @throws UnprocessableEntityHttpException
* @internal param bool $fade
*/
public function actionRgb($item_id, $red = 0, $green = 0, $blue = 0, $fade = false)
{
public function actionRgb(
$item_id,
$mode,
$fade_time = null,
$red = null,
$green = null,
$blue = null,
$color_time = null
) {
$item = $this->findItem($item_id);
if ($item->type !== Item::TYPE_RGB) {
throw new BadRequestHttpException();
throw new BadRequestHttpException('It is not a RGB Item');
}
if (!in_array($mode, Item::getRGBModesArray())) {
throw new BadRequestHttpException('Invalid mode');
}
if (!isset($fade_time) or $fade_time === null) {
$fade_time = Yii::$app->params['items']['rgb']['fade-time'];
} elseif ($fade_time < 0) {
$fade_time = 0;
}
$sendParameters = [
'type' => 'rgb',
'item_id' => $item_id,
'mode' => $mode,
'fade_time' => $fade_time,
];
if ($mode === Item::RGB_MODE_STATIC or $mode === Item::RGB_MODE_FADE) {
if (!isset($red) or $red === null) {
throw new UnprocessableEntityHttpException('Missing red parameter');
}
if (!isset($green) or $green === null) {
throw new UnprocessableEntityHttpException('Missing green parameter');
}
if (!isset($blue) or $blue === null) {
throw new UnprocessableEntityHttpException('Missing blue parameter');
}
$sendParameters['red'] = $red;
$sendParameters['green'] = $green;
$sendParameters['blue'] = $blue;
}
if ($mode === Item::RGB_MODE_WAVE or $mode === Item::RGB_MODE_FADE) {
if (!isset($color_time) or $color_time === null) {
throw new UnprocessableEntityHttpException('Missing color_time parameter');
}
$sendParameters['color_time'] = $color_time;
}
$board = $item->board;
@@ -165,7 +214,7 @@ class ItemController extends Controller
$api = new WebSocketAPIBridge(Yii::$app->user->identity);
return [
'success' => $api->rgb($item_id, $red, $green, $blue, $fade),
'success' => $api->send($sendParameters),
];
default:
throw new ServerErrorHttpException();
@@ -189,7 +238,7 @@ class ItemController extends Controller
throw new BadRequestHttpException('This item is not the RGB one');
}
if (!in_array($mode, Item::getModesArray())) {
if (!in_array($mode, Item::getRGBModesArray())) {
throw new InvalidParamException('Unknown mode');
}
@@ -210,6 +259,47 @@ class ItemController extends Controller
}
}
/**
* @param int $item_id
* @return array
* @throws BadRequestHttpException
*/
public function actionChartData($item_id)
{
$item = $this->findItem($item_id);
if (!in_array($item->type, [
Item::TYPE_VARIABLE,
Item::TYPE_VARIABLE_HUMIDITY,
Item::TYPE_VARIABLE_LIGHT,
Item::TYPE_VARIABLE_TEMPERATURE
])
) {
throw new BadRequestHttpException('This item is not the variable one');
}
$historyModels = History::find()
->where([
'type' => History::TYPE_ITEM_VALUE,
'item_id' => $item->id,
])
->andWhere(['>=', 'commited_at', time() - 21600])
->orderBy('commited_at DESC')
->all();
$data = [];
foreach ($historyModels as $historyModel) {
$data[$historyModel->commited_at] = $historyModel->value;
}
return [
'success' => true,
'data' => $data,
'item' => $item,
];
}
/**
* @param int $id
* @return Item

View File

@@ -0,0 +1,10 @@
<?php
namespace app\modules\api\controllers;
use yii\rest\ActiveController;
class RoomController extends ActiveController
{
public $modelClass = 'app\models\Room';
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->title = 'Авторизация';
$this->params['body-class'] = 'login-page';
$this->params['bodyClass'] = 'login-body';
$fieldOptions1 = [
'options' => ['class' => 'form-group has-feedback'],
@@ -21,37 +21,37 @@ $fieldOptions2 = [
];
?>
<div class="login-box">
<div class="login-box-body">
<div class="container login-container">
<div class="row">
<div class="col-sm-6 col-md-4 col-md-offset-4 col-sm-offset-3">
<div class="card">
<div class="login-logo product-font">
<span>Solomaha</span> Home
</div>
<div class="login-logo product-font">
<span>Solomaha</span> Home
</div>
<?php $form = ActiveForm::begin(['id' => 'login-form', 'enableClientValidation' => false]); ?>
<!-- <hr>-->
<?= $form
->field($model, 'username', $fieldOptions1)
->label(false)
->textInput(['placeholder' => $model->getAttributeLabel('username')]) ?>
<?php $form = ActiveForm::begin(['id' => 'login-form', 'enableClientValidation' => false]); ?>
<?= $form
->field($model, 'password', $fieldOptions2)
->label(false)
->passwordInput(['placeholder' => $model->getAttributeLabel('password')]) ?>
<?= $form
->field($model, 'username', $fieldOptions1)
->label(false)
->textInput(['placeholder' => $model->getAttributeLabel('username')]) ?>
<div class="row">
<div class="col-xs-8">
<?= $form->field($model, 'rememberMe')->checkbox() ?>
</div>
<div class="col-xs-4">
<?= Html::submitButton('Войти', ['class' => 'btn btn-primary btn-block', 'name' => 'login-button']) ?>
</div>
</div>
<?= $form
->field($model, 'password', $fieldOptions2)
->label(false)
->passwordInput(['placeholder' => $model->getAttributeLabel('password')]) ?>
<div class="row">
<div class="col-xs-8">
<?= $form->field($model, 'rememberMe')->checkbox() ?>
</div>
<div class="col-xs-4">
<?= Html::submitButton('Войти', ['class' => 'btn btn-primary btn-block btn-flat', 'name' => 'login-button']) ?>
<?php ActiveForm::end(); ?>
</div>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>

16
views/error/error.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
/* @var $this yii\web\View */
/* @var $name string */
/* @var $message string */
/* @var $exception Exception */
use yii\helpers\Html;
$this->title = $name;
$this->params['in-card'] = false;
?>
<div class="alert alert-danger">
<?= nl2br(Html::encode($message)) ?>
</div>

View File

@@ -0,0 +1,25 @@
<?php
/* @var $this yii\web\View */
/* @var $name string */
/* @var $message string */
/* @var $exception Exception */
use yii\helpers\Html;
$this->title = $name;
?>
<div class="container">
<div class="error-page-logo">
<a href="<?= \yii\helpers\Url::home() ?>" class="product-font">
<span>Solomaha</span> Home
</a>
</div>
<h1><?= $this->title ?></h1>
<div class="alert alert-danger">
<?= nl2br(Html::encode($message)) ?>
</div>
</div>

View File

@@ -6,7 +6,6 @@
use app\models\History;
use app\models\Item;
$this->params['not-boxed'] = true;
?>
<div class="panel panel-defaul">

View File

@@ -9,6 +9,7 @@ use yii\widgets\Pjax;
$this->title = 'История';
$this->params['breadcrumbs'][] = $this->title;
$this->params['in-card'] = false;
?>
<div class="history-index">

View File

@@ -1,52 +1,29 @@
<?php
/* @var $this \yii\web\View */
use yii\helpers\Html;
use yii\helpers\Inflector;
use yii\widgets\Breadcrumbs;
use dmstr\widgets\Alert;
$inCard = isset($this->params['in-card']) ? $this->params['in-card'] : true;
$tableCard = isset($this->params['table-card']) ? $this->params['table-card'] : false;
?>
<div class="content-wrapper">
<section class="content-header">
<?php if (isset($this->blocks['content-header'])): ?>
<h1><?= $this->blocks['content-header'] ?></h1>
<?php else: ?>
<h1>
<?php
if ($this->title !== null) {
echo Html::encode($this->title);
} else {
echo Inflector::camel2words(
Inflector::id2camel($this->context->module->id)
);
echo ($this->context->module->id !== Yii::$app->id) ? '<small>Module</small>' : '';
} ?>
</h1>
<?php endif; ?>
<?= Breadcrumbs::widget([
'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
]) ?>
</section>
<main class="content">
<div class="container-fluid">
<section class="content-header">
<h1><?= Html::encode($this->title) ?></h1>
<section class="content">
<?= Alert::widget() ?>
</section>
<?php if (!isset($this->params['not-boxed']) or !$this->params['not-boxed']): ?>
<div class="box">
<div class="box-body">
<section class="content-section">
<?php if ($inCard): ?>
<div class="card">
<?= $content ?>
</div>
</div>
<?php else: ?>
<?= $content ?>
<?php endif; ?>
</section>
</div>
<footer class="main-footer">
<span class="product-font">
<span>Smart</span> Home by <a href="https://solomaha.com" target="_blank">Alex Solomaha</a>
</span>
</footer>
<?php else: ?>
<?= $content ?>
<?php endif; ?>
</section>
</div>
</main>

89
views/layouts/_drawer.php Normal file
View File

@@ -0,0 +1,89 @@
<?php
/* @var $this \yii\web\View */
use rmrevin\yii\fontawesome\FA;
use yii\bootstrap\Nav;
?>
<aside id="drawer" class="drawer">
<div class="drawer-content">
<div class="user-block">
<div class="user-avatar">
<img src="<?= Yii::$app->user->identity->getAvatar(40) ?>">
</div>
<div class="user-info">
<div class="user-info-name">
<?= Yii::$app->user->identity->username ?>
</div>
</div>
<div class="user-caret"><?= FA::i('chevron-down') ?></div>
</div>
<?= Nav::widget([
'items' => [
[
'label' => FA::i('sliders fa-fw') . 'Панель Управления',
'url' => ['/panel/index'],
],
[
'label' => FA::i('history fa-fw') . 'История',
'url' => ['/history/index'],
],
'<li class="divider"></li>',
[
'label' => FA::i('microchip fa-fw') . 'Элементы',
'url' => ['/admin/item/index'],
],
[
'label' => FA::i('toggle-on fa-fw') . 'Виджеты',
'url' => ['/admin/item-widget/index'],
],
[
'label' => FA::i('wifi fa-fw') . 'Устройства',
'url' => ['/admin/board/index'],
],
[
'label' => FA::i('code-fork fa-fw') . 'События',
'url' => ['/admin/event/index'],
],
[
'label' => FA::i('feed fa-fw') . 'Триггеры',
'url' => ['/admin/trigger/index'],
],
[
'label' => FA::i('check fa-fw') . 'Задачи',
'url' => ['/admin/task/index'],
],
[
'label' => FA::i('folder-open fa-fw') . 'Комнаты',
'url' => ['/admin/room/index'],
],
[
'label' => FA::i('cog fa-fw') . 'Настройки',
'url' => ['/admin/setting/index'],
],
[
'label' => FA::i('users fa-fw') . 'Пользователи',
'url' => ['/admin/user/index'],
],
'<li class="divider"></li>',
[
'label' => FA::i('user fa-fw') . 'Профиль',
'url' => ['/profile/index'],
],
[
'label' => FA::i('sign-out fa-fw') . 'Выйти',
'url' => ['/auth/logout'],
'linkOptions' => [
'data-method' => 'post',
],
],
],
'encodeLabels' => false,
'options' => [
'class' => 'drawer-menu nav-stacked',
],
]); ?>
</div>
</aside>

View File

@@ -5,150 +5,43 @@
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\Breadcrumbs;
?>
<header class="main-header">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a href="#" class="navbar-toggle-drawer">
<div class="navbar-toggle-drawer-icon">
<span class="toggle-bar"></span>
<span class="toggle-bar"></span>
<span class="toggle-bar"></span>
</div>
</a>
<?= Html::a('<span class="logo-mini product-font">SH</span><span class="logo-lg product-font"><span>Solomaha</span> Home</span>',
Yii::$app->homeUrl, ['class' => 'logo']) ?>
<nav class="navbar navbar-static-top" role="navigation">
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button"></a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<!-- Messages: style can be found in dropdown.less-->
<li class="dropdown messages-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-envelope-o"></i>
<!-- <span class="label label-success">1</span>-->
</a>
<ul class="dropdown-menu">
<li class="header">You have 4 messages</li>
<li>
<!-- inner menu: contains the actual data -->
<ul class="menu">
<li><!-- start message -->
<a href="#">
<div class="pull-left">
<img src="<?= Yii::$app->user->identity->getAvatar() ?>" class="img-circle"
alt="User Image">
</div>
<h4>
Support Team
<small><i class="fa fa-clock-o"></i> 5 mins</small>
</h4>
<p>Why not buy a new awesome theme?</p>
</a>
</li>
<!-- end message -->
</ul>
</li>
<li class="footer"><a href="#">See All Messages</a></li>
</ul>
</li>
<li class="dropdown notifications-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-bell-o"></i>
<!-- <span class="label label-warning">10</span>-->
</a>
<ul class="dropdown-menu">
<li class="header">You have 10 notifications</li>
<li>
<!-- inner menu: contains the actual data -->
<ul class="menu">
<li>
<a href="#">
<i class="fa fa-users text-aqua"></i> 5 new members joined today
</a>
</li>
</ul>
</li>
<li class="footer"><a href="#">View all</a></li>
</ul>
</li>
<!-- Tasks: style can be found in dropdown.less -->
<li class="dropdown tasks-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-flag-o"></i>
<!-- <span class="label label-danger">9</span>-->
</a>
<ul class="dropdown-menu">
<li class="header">You have 9 tasks</li>
<li>
<!-- inner menu: contains the actual data -->
<ul class="menu">
<li><!-- Task item -->
<a href="#">
<h3>
Design some buttons
<small class="pull-right">20%</small>
</h3>
<div class="progress xs">
<div class="progress-bar progress-bar-aqua" style="width: 20%"
role="progressbar" aria-valuenow="20" aria-valuemin="0"
aria-valuemax="100">
<span class="sr-only">20% Complete</span>
</div>
</div>
</a>
</li>
<!-- end task item -->
</ul>
</li>
<li class="footer">
<a href="#">View all tasks</a>
</li>
</ul>
</li>
<!-- User Account: style can be found in dropdown.less -->
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<img src="<?= Yii::$app->user->identity->getAvatar() ?>" class="user-image" alt="User Image">
<span class="hidden-xs"><?= Yii::$app->user->identity->username ?></span>
</a>
<ul class="dropdown-menu">
<!-- User image -->
<li class="user-header">
<img src="<?= Yii::$app->user->identity->getAvatar() ?>" class="img-circle"
alt="User Image">
<p>
<?= Yii::$app->user->identity->username ?>
<small>
Зарегистрирован <?= Yii::$app->formatter->asDate(Yii::$app->user->identity->created_at) ?>
</small>
</p>
</li>
<!-- Menu Footer-->
<li class="user-footer">
<div class="pull-left">
<a href="<?= Url::to(['/user/view', 'id' => Yii::$app->user->id]) ?>"
class="btn btn-default btn-flat">
Профиль
</a>
</div>
<div class="pull-right">
<?= Html::a(
'Выйти',
['/auth/logout'],
['data-method' => 'post', 'class' => 'btn btn-default btn-flat']
) ?>
</div>
</li>
</ul>
</li>
<!-- User Account: style can be found in dropdown.less -->
<!-- <li>-->
<!-- <a href="#" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a>-->
<!-- </li>-->
</ul>
<a class="navbar-brand product-font" href="<?= Url::home() ?>"><span>Solomaha</span> Home</a>
</div>
</nav>
</header>
<div class="navbar-breadcrumbs hidden-xs">
<?= Breadcrumbs::widget([
'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
'homeLink' => false,
]) ?>
</div>
<ul class="nav navbar-nav navbar-right hidden-xs">
<li class="dropdown notifications-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false"><i class="fa fa-bell"></i></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
</ul>
</li>
</ul>
</div><!-- /.container-fluid -->
</nav>

View File

@@ -1,41 +0,0 @@
<aside class="main-sidebar">
<section class="sidebar">
<!-- Sidebar user panel -->
<div class="user-panel">
<div class="pull-left image">
<img src="<?= Yii::$app->user->identity->getAvatar() ?>" class="img-circle" alt="<?= Yii::$app->user->identity->username ?> Avatar">
</div>
<div class="pull-left info">
<p><?= Yii::$app->user->identity->username ?></p>
<a href="#"><i class="fa fa-circle text-success"></i> Online</a>
</div>
</div>
<?= dmstr\widgets\Menu::widget(
[
'options' => ['class' => 'sidebar-menu'],
'items' => [
['label' => 'Управление', 'options' => ['class' => 'header']],
['label' => 'Панель Управления', 'icon' => 'fa fa-sliders', 'url' => ['/panel/index']],
['label' => 'История', 'icon' => 'fa fa-th-list', 'url' => ['/history/index']],
['label' => 'Администрирование', 'options' => ['class' => 'header'], 'visible' => Yii::$app->user->identity->isAdmin],
['label' => 'Элементы', 'icon' => 'fa fa-toggle-on', 'url' => ['/admin/item/index'], 'visible' => Yii::$app->user->identity->isAdmin],
['label' => 'Устройства', 'icon' => 'fa fa-hdd-o', 'url' => ['/admin/board/index'], 'visible' => Yii::$app->user->identity->isAdmin],
['label' => 'События', 'icon' => 'fa fa-code-fork', 'url' => ['/admin/event/index'], 'visible' => Yii::$app->user->identity->isAdmin],
['label' => 'Триггеры', 'icon' => 'fa fa-feed', 'url' => ['/admin/trigger/index'], 'visible' => Yii::$app->user->identity->isAdmin],
['label' => 'Задачи', 'icon' => 'fa fa-check', 'url' => ['/admin/task/index'], 'visible' => Yii::$app->user->identity->isAdmin],
['label' => 'Комнаты', 'icon' => 'fa fa-folder-open', 'url' => ['/admin/room/index'], 'visible' => Yii::$app->user->identity->isAdmin],
['label' => 'Параметры', 'icon' => 'fa fa-cogs', 'url' => ['/admin/setting/index'], 'visible' => Yii::$app->user->identity->isAdmin],
// ['label' => 'История', 'icon' => 'fa fa-bar-chart', 'url' => ['/admin/history/index'], 'visible' => Yii::$app->user->identity->isAdmin],
['label' => 'Пользователи', 'icon' => 'fa fa-users', 'url' => ['/admin/user/index'], 'visible' => Yii::$app->user->identity->isAdmin],
],
]
) ?>
</section>
</aside>

View File

@@ -3,19 +3,15 @@
/* @var $this \yii\web\View */
/* @var $content string */
use dmstr\helpers\AdminLteHelper;
use dmstr\web\AdminLteAsset;
use app\assets\MDThemeAsset;
use yii\helpers\Html;
use app\assets\AppAsset;
use yii\helpers\Url;
AppAsset::register($this);
AdminLteAsset::register($this);
MDThemeAsset::register($this);
if (isset($this->params['body-class'])) {
$bodyClass = $this->params['body-class'];
} else {
$bodyClass = null;
}
$bodyClass = isset($this->params['bodyClass']) ? $this->params['bodyClass'] : '';
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
@@ -29,8 +25,14 @@ if (isset($this->params['body-class'])) {
<title><?= $this->title ?> - <?= Yii::$app->name ?></title>
<link rel="apple-touch-icon" sizes="180x180" href="<?= Yii::$app->homeUrl ?>img/apple-touch-icon.png">
<link rel="icon" type="image/png" href="<?= Yii::$app->homeUrl ?>img/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="<?= Yii::$app->homeUrl ?>img/favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="<?= Yii::$app->homeUrl ?>manifest.json">
<link rel="mask-icon" href="<?= Yii::$app->homeUrl ?>img/safari-pinned-tab.svg" color="#5bbad5">
<meta name="application-name" content="<?= Yii::$app->name ?>">
<meta name="theme-color" content="#605CA8">
<meta name="theme-color" content="#009688">
<link rel="publisher" href="https://plus.google.com/+AlexSolomaha21">
<link rel="me" href="https://plus.google.com/+AlexSolomaha21" type="text/html">
@@ -40,7 +42,7 @@ if (isset($this->params['body-class'])) {
<?php $this->head() ?>
</head>
<body class="hold-transition <?= AdminLteHelper::skinClass() ?> <?= $bodyClass ?> sidebar-mini">
<body class="<?= $bodyClass ?>">
<?php $this->beginBody() ?>
<?= $content ?>

View File

@@ -0,0 +1,14 @@
<?php
/* @var $this \yii\web\View */
/* @var $content string */
?>
<?php $this->beginContent('@app/views/layouts/base.php'); ?>
<?= $this->render('_header.php') ?>
<?= $this->render('_drawer.php') ?>
<?= $content ?>
<?php $this->endContent(); ?>

View File

@@ -1,21 +1,14 @@
<?php
/* @var $this \yii\web\View */
/* @var $content string */
$directoryAsset = Yii::$app->assetManager->getPublishedUrl('@vendor/almasaeed2010/adminlte/dist');
?>
<?php $this->beginContent('@app/views/layouts/base.php'); ?>
<div class="wrapper">
<?= $this->render('_header.php') ?>
<?= $this->render('_header.php', ['directoryAsset' => $directoryAsset]) ?>
<?= $this->render('_drawer.php') ?>
<?= $this->render('_left.php', ['directoryAsset' => $directoryAsset]) ?>
<?= $this->render('_content.php', ['content' => $content, 'directoryAsset' => $directoryAsset]) ?>
</div>
<?= $this->render('_content.php', ['content' => $content]) ?>
<?php $this->endContent(); ?>

View File

@@ -1,37 +1,17 @@
<?php
/* @var $this yii\web\View */
/* @var $item \app\models\Item */
/* @var $widget \app\models\ItemWidget */
?>
<div class="col-md-4 panel-item item-rgb" data-item-id="<?= $item->id ?>">
<div class="info-box bg-<?= $item->bg ?> <?= $item->class ?>">
<span class="info-box-icon"><i class="fa fa-<?= $item->icon ?>"></i></span>
<div class="info-box-content">
<div class="col-xs-4 border-right">
<span class="info-box-text"><?= $item->name ?></span>
<span class="info-box-number"><input type="text"
id="colorpicker-<?= $item->id ?>"
class="rgb-colorpicker"
data-item-id="<?= $item->id ?>"></span>
<label>
<input type="checkbox" class="fade-checkbox" data-item-id="<?= $item->id ?>" checked>
Плавно
</label>
</div>
<div class="col-xs-8">
<span class="info-box-text">Режимы</span>
<div class="rgb-modes-list">
<div class="rgb-mode" data-mode="rainbow">
<div class="rgb-mode-image rgb-mode-rainbow"></div>
</div>
<div class="rgb-mode" data-mode="breath">
<div class="rgb-mode-image rgb-mode-breath"></div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-4 col-sm-6">
<div class="panel-item panel-item-rgb withripple <?= $widget->html_class ?>" data-item-id="<?= $widget->item_id ?>">
<div class="panel-item-rgb-icon">
<i class="fa <?= $widget->icon ?>"></i>
</div>
<div class="panel-item-rgb-name">
<?= $widget->getName() ?>
</div>
</div>
</div>

View File

@@ -1,22 +1,17 @@
<?php
/* @var $this yii\web\View */
/* @var $item \app\models\Item */
/* @var $widget \app\models\ItemWidget */
?>
<div class="col-md-3 col-sm-4 control-panel-item item-switch"
data-item-id="<?= $item->id ?>">
<div class="info-box bg-<?= $item->bg ?> <?= $item->class ?>">
<div class="info-box-action material-switch">
<input id="switch-for-item-<?= $item->id ?>" class="item-switch-checkbox"
type="checkbox" data-item-id="<?= $item->id ?>">
<label for="switch-for-item-<?= $item->id ?>" class="label-default"></label>
<div class="col-lg-3 col-md-4 col-sm-6">
<div class="panel-item panel-item-switch withripple <?= $widget->html_class ?>" data-item-id="<?= $widget->item_id ?>">
<div class="panel-item-switch-icon">
<i class="fa <?= $widget->icon ?>"></i>
</div>
<div class="info-box-content">
<span class="info-box-text"><?= $item->name ?></span>
<div class="panel-item-switch-name">
<?= $widget->getName() ?>
</div>
<!-- /.info-box-content -->
</div>
</div>

View File

@@ -1,27 +1,18 @@
<?php
/* @var $this yii\web\View */
/* @var $item \app\models\Item */
use app\models\Item;
/* @var $widget \app\models\ItemWidget */
?>
<div class="col-md-3 col-sm-4 control-panel-item item-variable"
data-item-id="<?= $item->id ?>">
<div class="info-box bg-<?= $item->bg ?> <?= $item->class ?>">
<span class="info-box-icon"><i class="fa fa-<?= $item->icon ?>"></i></span>
<div class="info-box-content">
<span class="info-box-text"><?= $item->name ?></span>
<span class="info-box-number item-value <?= (in_array($item->type, [
Item::TYPE_VARIABLE_TEMPERATURE,
Item::TYPE_VARIABLE_HUMIDITY,
Item::TYPE_LIGHT_LEVEL
])) ? 'temperature' : '' ?>">
НЕИЗВЕСТНО
</span>
<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6">
<div class="panel-item panel-item-variable <?= $widget->html_class ?> withripple"
title="<?= $widget->getName() ?>"
data-item-id="<?= $widget->item_id ?>"
data-item-type="<?= $widget->item->type ?>">
<div class="item-variable-icon">
<i class="fa <?= $widget->icon ?>"></i>
</div>
<!-- /.info-box-content -->
<div class="item-variable-value item-value"><?= $widget->item->getDefaultNAValue() ?></div>
</div>
</div>

View File

@@ -1,60 +1,178 @@
<?php
/* @var $this yii\web\View */
/* @var $roomModels \app\models\Room[] */
use app\assets\WSClientAsset;
use app\models\Item;
use app\models\Room;
use yii\web\View;
use app\assets\PanelAsset;
use rmrevin\yii\fontawesome\FA;
use yii\helpers\Html;
PanelAsset::register($this);
$this->title = 'Панель Управления';
$this->params['not-boxed'] = true;
WSClientAsset::register($this);
?>
<div class="loader" id="loader">
<div class="loader-animation">
<span></span>
<span></span>
<span></span>
</div>
<div class="loader-text text-danger"></div>
<div class="linear-loader">
<div class="indeterminate"></div>
</div>
<div class="control-panel">
<?php foreach (Room::find()->all() as $room): ?>
<div class="box control-panel-room box-<?= $room->bg ?>" data-room-id="<?= $room->id ?>">
<div class="box-header with-border">
<h3 class="box-title"><?= $room->name ?></h3>
</div>
<div class="box-body control-panel-items">
<div class="row items-variable">
<?php foreach ($room->getItems()->variables()->active()->all() as $item): ?>
<?= $this->render('_variable', [
'item' => $item,
]) ?>
<?php endforeach; ?>
</div>
<div class="row items-switch">
<?php foreach ($room->getItems()->switches()->active()->all() as $item): ?>
<?= $this->render('_switch', [
'item' => $item,
]) ?>
<?php endforeach; ?>
</div>
<div class="row items-rgb">
<?php foreach ($room->getItems()->rgb()->all() as $item): ?>
<?= $this->render('_rgb', [
'item' => $item,
]) ?>
<?php endforeach; ?>
<main class="content">
<div class="container-fluid">
<div id="loader">
<div class="loader-icon">
<div class="circle">
<?= FA::i('home') ?>
</div>
</div>
<!-- /.box-body -->
<div class="loader-brand">
<span class="product-font"><span>Solomaha</span> Home</span>
</div>
<div class="loader-message">OFFLINE</div>
</div>
<?php endforeach; ?>
<div class="control-panel">
<section class="content-header">
<h1><?= Html::encode($this->title) ?></h1>
</section>
<?php foreach ($roomModels as $room): ?>
<div class="card panel-room" data-room-id="<?= $room->id ?>">
<div class="card-header">
<h3 class="card-header-title"><?= $room->name ?></h3>
</div>
<div class="card-body">
<div class="row panel-items-variable">
<?php foreach ($room->getItemWidgets()->variables()->active()->all() as $widget): ?>
<?= $this->render('_variable', [
'widget' => $widget,
]) ?>
<?php endforeach; ?>
</div>
<div class="row panel-items-switch">
<?php foreach ($room->getItemWidgets()->switches()->active()->all() as $widget): ?>
<?= $this->render('_switch', [
'widget' => $widget,
]) ?>
<?php endforeach; ?>
</div>
<div class="row panel-items-rgb">
<?php foreach ($room->getItemWidgets()->rgb()->active()->all() as $widget): ?>
<?= $this->render('_rgb', [
'widget' => $widget,
]) ?>
<?php endforeach; ?>
</div>
</div>
<!-- /.box-body -->
</div>
<?php endforeach; ?>
</div>
</div>
</main>
<script id="rgb-item-widget-popover-content" type="text/x-handlebars-template">
<div class="rgb-widget-popover-content" data-item-id="{{item_id}}">
<ul class="nav nav-tabs nav-justified">
<li class="active">
<a href="#rgb-widget-static" class="rgb-widget-mode rgb-widget-mode-static" data-toggle="tab"
aria-expanded="true">
Static
</a>
</li>
<li>
<a href="#rgb-widget-wave" class="rgb-widget-mode rgb-widget-mode-wave" data-toggle="tab"
aria-expanded="false">
Wave
</a>
</li>
<li>
<a href="#rgb-widget-fade" class="rgb-widget-mode rgb-widget-mode-fade" data-toggle="tab"
aria-expanded="false">
Fade
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade in active" id="rgb-widget-static">
<form class="rgb-widget-form rgb-widget-form-static">
<div class="row">
<div class="col-sm-6">
<label for="colorpicker-{{item_id}}" class="hidden">Цвет</label>
<input type="text"
class="rgb-widget-colorpicker rgb-widget-colorpicker-static"
data-item-id="{{item_id}}"
id="colorpicker-{{item_id}}">
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="rgb-widget-static-fade-time">Время перехода (мс)</label>
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-static-fade-time"
value="<?= Yii::$app->params['items']['rgb']['fade-time'] ?>">
</div>
</div>
</div>
</form>
</div>
<div class="tab-pane fade" id="rgb-widget-wave">
<form class="rgb-widget-form rgb-widget-form-wave">
<div class="form-group">
<label for="rgb-widget-wave-fade-time">Время перехода (мс)</label>
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-wave-fade-time"
value="<?= Yii::$app->params['items']['rgb']['fade-time'] ?>">
</div>
<div class="form-group">
<label for="rgb-widget-wave-color-time">Время цвета (мс)</label>
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-wave-color-time"
value="<?= Yii::$app->params['items']['rgb']['color-time'] ?>">
</div>
<button class="btn btn-primary btn-save-times" data-mode="wave">Применить</button>
</form>
</div>
<div class="tab-pane fade" id="rgb-widget-fade">
<form class="rgb-widget-form rgb-widget-form-fade">
<div class="row">
<div class="col-sm-6">
<label for="fade-colorpicker-{{item_id}}" class="hidden">Цвет</label>
<input type="text"
class="rgb-widget-colorpicker rgb-widget-colorpicker-fade"
data-item-id="{{item_id}}"
id="fade-colorpicker-{{item_id}}">
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="rgb-widget-fade-fade-time">Время перехода (мс)</label>
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-fade-fade-time"
value="<?= Yii::$app->params['items']['rgb']['fade-time'] ?>">
</div>
<div class="form-group">
<label for="rgb-widget-fade-color-time">Время цвета (мс)</label>
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-fade-color-time"
value="<?= Yii::$app->params['items']['rgb']['color-time'] ?>">
</div>
<button class="btn btn-primary btn-save-times" data-mode="fade">Применить</button>
</div>
</div>
</form>
</div>
</div>
</div>
</script>
<!-- Modal -->
<div class="modal fade" id="item-chart-modal" tabindex="-1" role="dialog" aria-labelledby="item-chart-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="item-chart-modal-label">График элемента <span class="item-chart-name"></span></h4>
</div>
<div class="modal-body">
<canvas id="item-chart"></canvas>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button>
</div>
</div>
</div>
</div>

9
views/profile/edit.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
/** @var $this \yii\web\View */
/** @var $user \app\models\User */
use yii\helpers\Url;
$this->title = 'Редактировать профиль';
?>

58
views/profile/index.php Normal file
View File

@@ -0,0 +1,58 @@
<?php
/** @var $this \yii\web\View */
/** @var $user \app\models\User */
use yii\helpers\Url;
$this->title = 'Профиль ' . $user->username;
?>
<div class="row user-profile">
<div class="col-sm-2">
<img src="<?= $user->getAvatar(200) ?>" alt="<?= $user->username ?>" class="img-responsive img-circle center-block">
<div class="user-actions text-center">
<a href="<?= Url::to(['edit']) ?>" class="btn btn-primary"><i class="fa fa-pencil"></i>
Изменить</a>
</div>
</div>
<div class="col-sm-5">
<h4><i class="fa fa-user"></i> Информация</h4>
<table class="table">
<tbody>
<tr>
<th scope="row">ID</th>
<td><?= $user->id ?></td>
</tr>
<tr>
<th scope="row">Логин</th>
<td><?= $user->username ?></td>
</tr>
<tr>
<th scope="row">Email</th>
<td><?= $user->email ?></td>
</tr>
<tr>
<th scope="row">Группа</th>
<td><?= $user->getGroupLabel() ?></td>
</tr>
<tr>
<th scope="row">Имя</th>
<td><?= $user->name ?></td>
</tr>
<tr>
<th scope="row">Комната</th>
<td><?= $user->room ? $user->room->name : null ?></td>
</tr>
<?php if (Yii::$app->user->id === $user->id): ?>
<tr>
<th scope="row">API Ключ</th>
<td><span class="show-on-click" data-text="<?= $user->api_key ?>">показать</span></td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>

View File

@@ -1,26 +0,0 @@
<?php
/* @var $this yii\web\View */
/* @var $name string */
/* @var $message string */
/* @var $exception Exception */
use yii\helpers\Html;
$this->title = $name;
?>
<section class="content">
<div class="error-page">
<h2 class="headline text-info"><i class="fa fa-warning text-yellow"></i></h2>
<div class="error-content">
<h1><?= $name ?></h1>
<p>
<?= nl2br(Html::encode($message)) ?>
</p>
</div>
</div>
</section>

View File

@@ -3,9 +3,29 @@
/* @var $this yii\web\View */
$this->title = 'Главная';
\yii\helpers\VarDumper::dump(\app\models\Setting::getValueByKey('log.user_connection'),10,true);
?>
<div class="site-index">
<h1 class="page-header"><?= $this->title ?></h1>
<div class="form-group">
<label for="md-select">Опция</label>
<select class="md-select" id="md-select">
<option value="1">Опция 1</option>
<option value="2">Опция 2</option>
<option value="3" selected>Опция 3</option>
<option value="4">Опция 4</option>
<option value="5">Опция 5</option>
</select>
</div>
<!--<div class="mad-select">-->
<!-- <ul>-->
<!-- <li data-value="1">Option 1</li>-->
<!-- <li data-value="2 foo">Option 2</li>-->
<!-- <li data-value="3 bar">Option 3</li>-->
<!-- <li data-value="4">Option 4</li>-->
<!-- <li data-value="5">Option long desc 5</li>-->
<!-- <li data-value="6">Option 6</li>-->
<!-- <li data-value="7">Option 7</li>-->
<!-- <li data-value="8">Option 8</li>-->
<!-- </ul>-->
<!-- <input type="hidden" name="myOptions" value="3 bar">-->
<!--</div>-->

644
web/css/md.theme.css Normal file
View File

@@ -0,0 +1,644 @@
/* General Syles */
html, body {
background: #e8e8e8;
overflow-x: hidden;
height: 100%;
}
.content {
padding-top: 64px;
transition: transform .3s ease-in-out, margin .3s ease-in-out;
margin-left: 260px;
}
/* Navbar */
.navbar {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.navbar .container-fluid {
padding-left: 0;
}
.navbar .navbar-header {
margin-left: 0;
}
.navbar > .container-fluid a.navbar-brand.product-font {
color: #fff;
}
.navbar a.product-font:hover {
text-decoration: none;
}
.navbar .navbar-toggle-drawer {
position: relative;
display: block;
float: left;
width: 48px;
height: 48px;
margin: 8px 12px;
border-radius: 48px;
padding: 17.5px 15px;
overflow: hidden;
color: #fff;
}
.navbar .navbar-toggle-drawer-icon {
width: 18px;
height: 12px;
}
.navbar span.toggle-bar {
display: block;
height: 2px;
background: #fff;
width: 18px;
position: relative;
margin-bottom: 3px;
}
.navbar .navbar-toggle-drawer-icon span.toggle-bar:last-of-type {
margin-bottom: 0;
}
.navbar .user-image {
float: left;
width: 25px;
height: 25px;
border-radius: 50%;
margin-right: 10px;
margin-top: -1px;
}
.navbar-breadcrumbs {
display: inline-block;
}
.navbar-breadcrumbs .breadcrumb {
background: transparent;
margin: 0;
padding: 18px 0 15px;
}
.navbar-breadcrumbs .breadcrumb li {
font-weight: 500;
font-size: 16px;
/*position: relative;*/
}
.navbar-breadcrumbs .breadcrumb li a {
color: #fff;
}
.navbar-breadcrumbs .breadcrumb li a:hover,
.navbar-breadcrumbs .breadcrumb li a:active,
.navbar-breadcrumbs .breadcrumb li a:focus {
text-decoration: none;
}
.navbar-breadcrumbs .breadcrumb li:before {
content: '\f054';
font-family: FontAwesome;
color: #fff;
padding: 0 10px 0 0;
}
.navbar-breadcrumbs .breadcrumb li + li:before {
padding: 0 10px;
}
.navbar-breadcrumbs .breadcrumb .active {
color: #fff;
font-weight: 500;
font-size: 16px;
}
/* Drawer */
.drawer {
position: fixed;
display: flex;
flex-direction: column;
top: 64px;
left: 0;
bottom: 0;
width: 260px;
z-index: 100;
background: #fff;
transition: transform .3s ease-in-out, width .3s ease-in-out;
border-right: 1px solid #d5d5d5;
overflow: auto;
}
.drawer .drawer-content {
height: 100%;
overflow: auto;
}
@media (max-width: 767px) {
/* Drawer styles */
.content {
margin-left: 0;
}
.drawer {
transform: translate(-260px, 0);
}
.drawer-open .drawer {
transform: translate(0, 0);
}
.drawer-open .content {
transform: translate(260px, 0);
}
/* Navbar styles */
.navbar .navbar-brand {
margin-left: -20px;
}
}
@media (max-width: 1200px) {
.content-header h1 {
font-size: 35px;
}
}
.drawer-menu {
margin-top: 10px;
}
.drawer-menu li a {
display: block;
width: 100%;
padding: 12px 20px;
font-size: 13px;
color: rgb(68, 68, 68);
font-weight: 500;
text-decoration: none;
}
.drawer-menu li a:hover {
background: rgba(0, 0, 0, 0.07);
}
.drawer-menu li.active a {
background: rgba(0, 0, 0, 0.07);
color: #009688;
}
.drawer-menu > li + li {
margin: 0;
}
.drawer-menu li a:hover,
.drawer-menu li a:active,
.drawer-menu li a:focus {
text-decoration: none;
}
.drawer-menu li a .fa {
font-weight: normal;
font-style: normal;
font-size: 20px;
line-height: 1;
letter-spacing: normal;
text-rendering: optimizeLegibility;
text-transform: none;
display: inline-block;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: 'liga';
-webkit-font-smoothing: antialiased;
color: #616161;
cursor: pointer;
margin-right: 16px;
margin-top: -4px;
opacity: .8;
overflow: hidden;
-webkit-transition: .15s transform;
transition: .15s transform;
vertical-align: middle;
}
.drawer-menu li.active a .fa {
color: #009688;
}
.drawer-menu li.divider {
display: block;
position: relative;
height: 1px;
width: 100%;
background: #efefef;
margin: 10px 0;
}
.user-block {
height: 64px;
padding: 12px;
border-bottom: 1px solid #efefef;
display: flex;
align-items: center;
}
.user-block .user-info {
display: inline-block;
font-weight: 500;
flex: 1;
text-align: center;
}
.user-block .user-avatar {
display: inline-block;
}
.user-block .user-avatar img {
border-radius: 50%;
height: 40px;
width: 40px;
}
.user-block .user-caret {
display: inline-block;
margin-left: auto;
padding: 5px 10px;
border-radius: 50%;
}
/* Cards */
.card {
background: #fff;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12);
margin-bottom: 20px;
border-radius: 2px;
padding: 24px;
}
.card-header .card-header-title {
font-size: 24px;
margin: 0 0 8px 0;
}
/* Panel Items */
.panel-item.panel-item-switch {
background: #009688;
border-radius: 30px;
color: #fff;
margin: 10px 0;
display: flex;
cursor: pointer;
align-items: center;
min-height: 50px;
box-shadow: 0 1px 1.5px 0 rgba(0, 0, 0, .12), 0 1px 1px 0 rgba(0, 0, 0, .24);
transition: 0.5s;
user-select: none;
}
.panel-item.panel-item-switch.off {
background: #909090;
}
.panel-item-switch-icon,
.panel-item-rgb-icon {
position: absolute;
padding: 0 15px 0 20px;
font-size: 20px;
line-height: 50px;
/*border-right: 1px solid rgba(95, 95, 95, 0.3);*/
background: rgba(0, 0, 0, 0.1);
border-top-left-radius: 30px;
border-bottom-left-radius: 30px;
}
.panel-item-switch-name,
.panel-item-rgb-name {
text-align: center;
width: 100%;
padding-left: 25px;
}
.panel-item.panel-item-variable {
width: 100%;
background: #009688;
border-radius: 2px;
box-shadow: 0 1px 1.5px 0 rgba(0, 0, 0, .12), 0 1px 1px 0 rgba(0, 0, 0, .24);
color: #fff;
text-align: center;
margin: 10px 0;
cursor: pointer;
user-select: none;
}
.panel-item-variable .item-variable-icon {
font-size: 45px;
}
.panel-item-variable .item-variable-value {
background: rgba(0, 0, 0, 0.3);
font-size: 20px;
}
.panel-item.panel-item-rgb {
background: #009688;
border-radius: 30px;
color: #fff;
margin: 10px 0;
display: flex;
cursor: pointer;
align-items: center;
height: 50px;
width: 100%;
box-shadow: 0 1px 1.5px 0 rgba(0, 0, 0, .12), 0 1px 1px 0 rgba(0, 0, 0, .24);
transition: 1s;
user-select: none;
}
.rgb-widget-form {
padding: 10px;
}
.sp-container {
display: block;
border-radius: 0;
background-color: transparent;
border: none;
padding: 0;
}
.sp-picker-container {
width: 100%;
border: none;
}
.sp-picker-container, .sp-palette-container {
float: none;
padding: 2px 0 0 0;
margin: 0;
}
/* Snackbar fixes */
#snackbar-container {
position: fixed;
right: 20px;
bottom: 0;
left: auto;
z-index: 99999;
}
/* Linear loader */
.linear-loader {
position: absolute;
top: 64px;
left: 0;
right: 0;
overflow: hidden;
width: 100%;
height: 4px;
background-color: #B3E5FC;
z-index: 1090;
}
.indeterminate {
position: relative;
width: 100%;
height: 100%;
}
.indeterminate:before {
content: '';
position: absolute;
height: 100%;
background-color: #03A9F4;
animation: indeterminate_first 3s infinite ease-out;
}
.indeterminate:after {
content: '';
position: absolute;
height: 100%;
background-color: #4FC3F7;
animation: indeterminate_second 3s infinite ease-in;
}
@keyframes indeterminate_first {
0% {
left: -100%;
width: 100%;
}
100% {
left: 100%;
width: 10%;
}
}
@keyframes indeterminate_second {
0% {
left: -150%;
width: 100%;
}
100% {
left: 100%;
width: 10%;
}
}
/* Login page */
.login-logo {
text-align: center;
font-size: 30px;
margin-bottom: 20px;
}
.login-container .card {
margin-top: calc(50vh - 140px);
}
body.login-body {
background: url("../img/login-bg.jpg") no-repeat;
background-size: cover;
}
@media only screen and (max-width: 767px) {
body.login-body {
background-image: url("../img/login-bg-small.jpg");
}
}
/* Error page */
.error-page-logo {
text-align: center;
margin: 40px 0;
}
.error-page-logo a {
color: #666666;
font-size: 40px;
transition: 0.5s;
}
.error-page-logo a:hover,
.error-page-logo a:active,
.error-page-logo a:focus {
color: #444444;
text-decoration: none;
}
/* Data Table */
.material-table > thead > tr > th {
padding: 16px 12px;
}
.material-table thead a {
color: #666;
}
.material-table thead a:hover, .material-table thead a:active {
color: #373737;
text-decoration: none;
}
.material-table > tbody > tr > td {
padding: 12px;
}
.material-table > tbody > tr:hover {
background-color: #EEEEEE;
}
.material-table a.asc:before, .material-table a.desc:before {
position: absolute;
font-family: FontAwesome, sans-serif;
font-style: normal;
font-weight: normal;
line-height: 1;
top: 0;
left: -18px;
}
.material-table thead a {
position: relative;
}
.material-table a.asc:before {
content: "\f062";
}
.material-table a.desc:before {
content: "\f063";
}
.material-table a.btn-flat {
box-shadow: none;
border: none;
border-radius: 0;
background: transparent;
color: #717171;
font-size: 15px;
}
.material-table a.btn-flat:hover {
color: #000;
}
.material-table thead tr th:first-child {
padding-left: 24px;
}
.material-table tbody tr td:first-child {
padding-left: 24px;
width: 60px;
}
.table-card {
padding: 0;
}
.table-card-actions {
padding: 10px;
border-bottom: 1px solid #dddddd;
}
.table-card-actions .btn-flat {
color: #009688;
font-weight: 500;
}
.table-card .material-table {
margin-bottom: 0;
}
.table-card .table-footer {
display: flex;
height: 56px;
align-items: center;
justify-content: flex-end;
flex-wrap: wrap-reverse;
box-sizing: border-box;
border-top: 1px solid #dddddd;
padding-right: 14px;
}
.table-footer-summary {
display: inline-block;
}
.table-footer .pagination {
display: inline-block;
margin: 0 0 0 32px;
}
/*.table-footer .pagination {*/
/*margin: 0;*/
/*padding: 0;*/
/*display: block;*/
/*}*/
.table-footer .prev,
.table-footer .next {
font-family: FontAwesome;
}
.table-footer .pagination > li > a,
.table-footer .pagination > li > span {
border: none;
color: #717171;
}
.table-footer .pagination > .disabled > span,
.table-footer .pagination > .disabled > span:hover,
.table-footer .pagination > .disabled > span:focus,
.table-footer .pagination > .disabled > a,
.table-footer .pagination > .disabled > a:hover,
.table-footer .pagination > .disabled > a:focus {
color: rgba(0, 0, 0, 0.3);
}
.btn-flat {
background: transparent;
box-shadow: none;
}
.btn-flat,
.btn-flat:active,
.btn-flat:hover,
.btn-flat:focus {
box-shadow: none;
}
/* Profile */
.user-actions .btn {
margin: 20px 0;
}
.user-profile h4 {
margin-bottom: 20px;
font-weight: lighter;
}
.show-on-click:not(.open) {
text-decoration: underline;
cursor: pointer;
}

66
web/css/panel.css Normal file
View File

@@ -0,0 +1,66 @@
/* Content loader */
#loader {
position: relative;
}
.loader-icon {
background: #2f2f2f;
border-radius: 100%;
height: 150px;
width: 150px;
margin: 100px auto 30px;
color: #fff;
text-align: center;
line-height: 150px;
font-size: 100px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.loader-brand {
text-align: center;
font-size: 40px;
}
.loader-message {
opacity: 0;
text-align: center;
font-size: 18px;
position: absolute;
left: calc(50% - 15px);
top: 125px;
background: #F44336;
border-radius: 50px;
padding: 0 10px;
color: #fff;
box-shadow: 0 0 10px #f44336;
width: 100px;
transition: 0.8s;
}
#loader.error .loader-message {
opacity: 1;
}
.control-panel {
display: none;
}
/* Popover */
.popover {
width: 300px;
box-shadow: 0 16px 24px 2px rgba(0,0,0,0.14), 0 6px 30px 5px rgba(0,0,0,0.12), 0 8px 10px -5px rgba(0,0,0,0.3);
max-width: none;
border-radius: 0;
padding: 0;
margin-bottom: 30px;
}
.popover-content {
padding: 0;
}
@media (min-width: 767px) {
.popover {
width: 500px;
}
}

47
web/css/ripples.css Normal file
View File

@@ -0,0 +1,47 @@
.withripple {
position: relative;
}
.ripple-container {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
overflow: hidden;
border-radius: inherit;
pointer-events: none;
}
.ripple {
position: absolute;
width: 20px;
height: 20px;
margin-left: -10px;
margin-top: -10px;
border-radius: 100%;
background-color: #000;
background-color: rgba(0, 0, 0, 0.05);
-webkit-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
-webkit-transform-origin: 50%;
-ms-transform-origin: 50%;
-o-transform-origin: 50%;
transform-origin: 50%;
opacity: 0;
pointer-events: none;
}
.ripple.ripple-on {
-webkit-transition: opacity 0.15s ease-in 0s, -webkit-transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
-o-transition: opacity 0.15s ease-in 0s, -o-transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
transition: opacity 0.15s ease-in 0s, transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
opacity: 0.1;
}
.ripple.ripple-out {
-webkit-transition: opacity 0.1s linear 0s !important;
-o-transition: opacity 0.1s linear 0s !important;
transition: opacity 0.1s linear 0s !important;
opacity: 0;
}
/*# sourceMappingURL=ripples.css.map */

View File

@@ -1,8 +1,3 @@
.not-set {
color: #c55;
font-style: italic;
}
.product-font {
font-family: 'Product Sans', Arial, sans-serif;
}
@@ -11,185 +6,11 @@
font-weight: bold;
}
.control-panel-room-title {
color: #8a8a8a;
border-bottom: 1px solid #efefef;
font-size: 30px;
margin-bottom: 20px;
.not-set {
color: #c55;
font-style: italic;
}
.item-switch .info-box-text {
font-weight: 400;
font-size: 20px;
text-align: center;
line-height: 80px;
}
.login-page {
background: url("../img/login-bg.png") no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
.login-box {
box-shadow: 0 0 10px 0 rgba(0,0,0,0.5);
}
.material-switch > input[type="checkbox"] {
display: none;
}
.material-switch > label {
cursor: pointer;
height: 0px;
position: relative;
width: 40px;
}
.material-switch > label::before {
background: rgb(0, 0, 0);
/*box-shadow: inset 0px 0px 10px rgba(0, 0, 0, 0.5);*/
border-radius: 8px;
content: '';
height: 16px;
margin-top: -8px;
position: absolute;
opacity: 0.3;
transition: all 0.4s ease-in-out;
width: 40px;
}
.material-switch > label::after {
background: rgb(255, 255, 255);
border-radius: 16px;
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3);
content: '';
height: 24px;
left: -4px;
margin-top: -8px;
position: absolute;
top: -4px;
transition: all 0.3s ease-in-out;
width: 24px;
}
.material-switch > input[type="checkbox"]:checked + label::before {
background: inherit;
opacity: 0.5;
}
.material-switch > input[type="checkbox"]:checked + label::after {
background: inherit;
left: 20px;
}
.info-box-action {
border-radius: 2px 0 0 2px;
float: left;
height: 90px;
width: 90px;
/*text-align: center;*/
/*font-size: 45px;*/
/*line-height: 90px;*/
background: rgba(0, 0, 0, 0.2);
display: flex;
justify-content: center;
align-items: center;
}
.item-switch .info-box {
cursor: pointer;
}
/* WS Loader */
.content-wrapper {
position: relative;
}
.control-panel {
display: none;
}
.loader .loader-animation {
margin: 30px auto 0;
}
.loader .loader-text {
margin: 30px auto;
text-align: center;
font-weight: 600;
text-transform: uppercase;
display: none;
}
.loader .loader-animation span {
transition: 0.5s;
}
.loader.error .loader-animation span {
background: #DD4B39;
}
.loader-animation {
position: relative;
.fontawesome-iconpicker-input {
display: block;
width: 100px;
height: 100px;
margin: 50px;
background: transparent;
}
.loader-animation span {
position: absolute;
top: 50px;
display: block;
width: 30px;
height: 30px;
background: #605ca8;
border-radius: 50%;
}
.loader-animation span:nth-child(1) {
-webkit-animation: bounce 0.8s ease-in-out infinite;
animation: bounce 0.8s ease-in-out infinite;
}
.loader-animation span:nth-child(2) {
left: 40px;
-webkit-animation: bounce 0.8s ease-in-out 0.25s infinite;
animation: bounce 0.8s ease-in-out 0.25s infinite;
}
.loader-animation span:nth-child(3) {
left: 80px;
-webkit-animation: bounce 0.8s ease-in-out 0.5s infinite;
animation: bounce 0.8s ease-in-out 0.5s infinite;
}
@-webkit-keyframes bounce {
0%, 100% {
-webkit-transform: translateY(0px);
transform: translateY(0px);
}
50% {
-webkit-transform: translateY(-25px);
transform: translateY(-25px);
}
}
@keyframes bounce {
0%, 100% {
-webkit-transform: translateY(0px);
transform: translateY(0px);
}
50% {
-webkit-transform: translateY(-25px);
transform: translateY(-25px);
}
}
.select2-container--krajee .select2-selection--single {
line-height: 2;
}

6663
web/css/theme.css Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,623 +0,0 @@
// Paper 3.3.7
// Bootswatch
// -----------------------------------------------------
@web-font-path: "https://fonts.googleapis.com/css?family=Roboto:300,400,500,700";
.web-font(@path) {
@import url("@{path}");
}
.web-font(@web-font-path);
// Navbar =====================================================================
.navbar {
border: none;
.box-shadow(0 1px 2px rgba(0,0,0,.3));
&-brand {
font-size: 24px;
}
&-inverse {
.navbar-form {
input[type=text],
input[type=password] {
color: #fff;
.box-shadow(inset 0 -1px 0 @navbar-inverse-link-color);
.placeholder(@navbar-inverse-link-color);
&:focus {
.box-shadow(inset 0 -2px 0 #fff);
}
}
}
}
}
// Buttons ====================================================================
#btn(@class,@bg) {
.btn-@{class} {
background-size: 200% 200%;
background-position: 50%;
&:focus {
background-color: @bg;
}
&:hover,
&:active:hover {
background-color: darken(@bg, 6%);
}
&:active {
background-color: darken(@bg, 12%);
#gradient > .radial(darken(@bg, 12%) 10%, @bg 11%);
background-size: 1000% 1000%;
.box-shadow(2px 2px 4px rgba(0,0,0,.4));
}
}
}
#btn(default,@btn-default-bg);
#btn(primary,@btn-primary-bg);
#btn(success,@btn-success-bg);
#btn(info,@btn-info-bg);
#btn(warning,@btn-warning-bg);
#btn(danger,@btn-danger-bg);
#btn(link,#fff);
.btn {
text-transform: uppercase;
border: none;
.box-shadow(1px 1px 4px rgba(0,0,0,.4));
.transition(all 0.4s);
&-link {
border-radius: @btn-border-radius-base;
.box-shadow(none);
color: @btn-default-color;
&:hover,
&:focus {
.box-shadow(none);
color: @btn-default-color;
text-decoration: none;
}
}
&-default {
&.disabled {
background-color: rgba(0, 0, 0, 0.1);
color: rgba(0, 0, 0, 0.4);
opacity: 1;
}
}
}
.btn-group {
.btn + .btn,
.btn + .btn-group,
.btn-group + .btn,
.btn-group + .btn-group {
margin-left: 0;
}
&-vertical {
> .btn + .btn,
> .btn + .btn-group,
> .btn-group + .btn,
> .btn-group + .btn-group {
margin-top: 0;
}
}
}
// Typography =================================================================
body {
-webkit-font-smoothing: antialiased;
letter-spacing: .1px;
}
p {
margin: 0 0 1em;
}
input,
button {
-webkit-font-smoothing: antialiased;
letter-spacing: .1px;
}
a {
.transition(all 0.2s);
}
// Tables =====================================================================
.table-hover {
> tbody > tr,
> tbody > tr > th,
> tbody > tr > td {
.transition(all 0.2s);
}
}
// Forms ======================================================================
label {
font-weight: normal;
}
textarea,
textarea.form-control,
input.form-control,
input[type=text],
input[type=password],
input[type=email],
input[type=number],
[type=text].form-control,
[type=password].form-control,
[type=email].form-control,
[type=tel].form-control,
[contenteditable].form-control {
padding: 0;
border: none;
border-radius: 0;
-webkit-appearance: none;
.box-shadow(inset 0 -1px 0 #ddd);
font-size: 16px;
&:focus {
.box-shadow(inset 0 -2px 0 @brand-primary);
}
&[disabled],
&[readonly] {
.box-shadow(none);
border-bottom: 1px dotted #ddd;
}
&.input {
&-sm {
font-size: @font-size-small;
}
&-lg {
font-size: @font-size-large;
}
}
}
select,
select.form-control {
border: 0;
border-radius: 0;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding-left: 0;
padding-right: 0\9; // remove padding for < ie9 since default arrow can't be removed
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEVmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmaP/QSjAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=);
background-size: 13px;
background-repeat: no-repeat;
background-position: right center;
.box-shadow(inset 0 -1px 0 #ddd);
font-size: 16px;
line-height: 1.5;
&::-ms-expand {
display: none;
}
&.input {
&-sm {
font-size: @font-size-small;
}
&-lg {
font-size: @font-size-large;
}
}
&:focus {
.box-shadow(inset 0 -2px 0 @brand-primary);
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEUhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF8S9ewAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=);
}
&[multiple] {
background: none;
}
}
.radio,
.radio-inline,
.checkbox,
.checkbox-inline {
label {
padding-left: 25px;
}
input[type="radio"],
input[type="checkbox"] {
margin-left: -25px;
}
}
input[type="radio"],
.radio input[type="radio"],
.radio-inline input[type="radio"] {
position: relative;
margin-top: 6px;
margin-right: 4px;
vertical-align: top;
border: none;
background-color: transparent;
-webkit-appearance: none;
appearance: none;
cursor: pointer;
&:focus {
outline: none;
}
&:before,
&:after {
content: "";
display: block;
width: 18px;
height: 18px;
border-radius: 50%;
.transition(240ms);
}
&:before {
position: absolute;
left: 0;
top: -3px;
background-color: @brand-primary;
.scale(0);
}
&:after {
position: relative;
top: -3px;
border: 2px solid @gray;
}
&:checked:before {
.scale(0.5);
}
&:disabled:checked:before {
background-color: @gray-light;
}
&:checked:after {
border-color: @brand-primary;
}
&:disabled:after,
&:disabled:checked:after {
border-color: @gray-light;
}
}
input[type="checkbox"],
.checkbox input[type="checkbox"],
.checkbox-inline input[type="checkbox"] {
position: relative;
border: none;
margin-bottom: -4px;
-webkit-appearance: none;
appearance: none;
cursor: pointer;
&:focus {
outline: none;
}
&:focus:after {
border-color: @brand-primary;
}
&:after {
content: "";
display: block;
width: 18px;
height: 18px;
margin-top: -2px;
margin-right: 5px;
border: 2px solid @gray;
border-radius: 2px;
.transition(240ms);
}
&:checked:before {
content: "";
position: absolute;
top: 0;
left: 6px;
display: table;
width: 6px;
height: 12px;
border: 2px solid #fff;
border-top-width: 0;
border-left-width: 0;
.rotate(45deg);
}
&:checked:after {
background-color: @brand-primary;
border-color: @brand-primary;
}
&:disabled:after {
border-color: @gray-light;
}
&:disabled:checked:after {
background-color: @gray-light;
border-color: transparent;
}
}
.has-warning {
input:not([type=checkbox]),
.form-control,
input.form-control[readonly],
input[type=text][readonly],
[type=text].form-control[readonly],
input:not([type=checkbox]):focus,
.form-control:focus {
border-bottom: none;
.box-shadow(inset 0 -2px 0 @brand-warning);
}
}
.has-error {
input:not([type=checkbox]),
.form-control,
input.form-control[readonly],
input[type=text][readonly],
[type=text].form-control[readonly],
input:not([type=checkbox]):focus,
.form-control:focus {
border-bottom: none;
.box-shadow(inset 0 -2px 0 @brand-danger);
}
}
.has-success {
input:not([type=checkbox]),
.form-control,
input.form-control[readonly],
input[type=text][readonly],
[type=text].form-control[readonly],
input:not([type=checkbox]):focus,
.form-control:focus {
border-bottom: none;
.box-shadow(inset 0 -2px 0 @brand-success);
}
}
// Remove the Bootstrap feedback styles for input addons
.input-group-addon {
.has-warning &, .has-error &, .has-success & {
color: @input-color;
border-color: @input-group-addon-border-color;
background-color: @input-group-addon-bg;
}
}
.form-group-lg {
select,
select.form-control {
line-height: 1.5;
}
}
// Navs =======================================================================
.nav-tabs {
> li > a,
> li > a:focus {
margin-right: 0;
background-color: transparent;
border: none;
color: @navbar-default-link-color;
.box-shadow(inset 0 -1px 0 #ddd);
.transition(all 0.2s);
&:hover {
background-color: transparent;
.box-shadow(inset 0 -2px 0 @brand-primary);
color: @brand-primary;
}
}
& > li.active > a,
& > li.active > a:focus {
border: none;
.box-shadow(inset 0 -2px 0 @brand-primary);
color: @brand-primary;
&:hover {
border: none;
color: @brand-primary;
}
}
& > li.disabled > a {
.box-shadow(inset 0 -1px 0 #ddd);
}
&.nav-justified {
& > li > a,
& > li > a:hover,
& > li > a:focus,
& > .active > a,
& > .active > a:hover,
& > .active > a:focus {
border: none;
}
}
.dropdown-menu {
margin-top: 0;
}
}
.dropdown-menu {
margin-top: 0;
border: none;
.box-shadow(0 1px 4px rgba(0,0,0,.3));
}
// Indicators =================================================================
.alert {
border: none;
color: #fff;
&-success {
background-color: @brand-success;
}
&-info {
background-color: @brand-info;
}
&-warning {
background-color: @brand-warning;
}
&-danger {
background-color: @brand-danger;
}
a:not(.close):not(.btn),
.alert-link {
color: #fff;
font-weight: bold;
}
.close {
color: #fff;
}
}
.badge {
padding: 4px 6px 4px;
}
.progress {
position: relative;
z-index: 1;
height: 6px;
border-radius: 0;
.box-shadow(none);
&-bar {
.box-shadow(none);
&:last-child {
border-radius: 0 3px 3px 0;
}
&:last-child {
&:before {
display: block;
content: "";
position: absolute;
width: 100%;
height: 100%;
left: 0;
right: 0;
z-index: -1;
background-color: lighten(@progress-bar-bg, 35%);
}
}
&-success:last-child.progress-bar:before {
background-color: lighten(@brand-success, 35%);
}
&-info:last-child.progress-bar:before {
background-color: lighten(@brand-info, 45%);
}
&-warning:last-child.progress-bar:before {
background-color: lighten(@brand-warning, 35%);
}
&-danger:last-child.progress-bar:before {
background-color: lighten(@brand-danger, 25%);
}
}
}
// Progress bars ==============================================================
// Containers =================================================================
.close {
font-size: 34px;
font-weight: 300;
line-height: 24px;
opacity: 0.6;
.transition(all 0.2s);
&:hover {
opacity: 1;
}
}
.list-group {
&-item {
padding: 15px;
}
&-item-text {
color: @gray-light;
}
}
.well {
border-radius: 0;
.box-shadow(none);
}
.panel {
border: none;
border-radius: 2px;
.box-shadow(0 1px 4px rgba(0,0,0,.3));
&-heading {
border-bottom: none;
}
&-footer {
border-top: none;
}
}
.popover {
border: none;
.box-shadow(0 1px 4px rgba(0,0,0,.3));
}
.carousel {
&-caption {
h1, h2, h3, h4, h5, h6 {
color: inherit;
}
}
}

1548
web/css/theme.min.css vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,107 +0,0 @@
.temperature {
font-size: 40px;
}
.item-rgb .sp-replacer {
margin: 4px 0;
padding: 0;
border: 0;
border-radius: 0;
color: inherit;
background: #efefef;
display: inline-block;
position: relative;
height: 30px;
width: 100%;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}
.item-rgb .sp-preview {
border: none;
margin-right: 0;
height: 30px;
width: 100%;
}
.item-rgb .sp-dd {
display: none;
}
.item-rgb label {
margin: 0;
}
.item-rgb .col-xs-4 {
margin: 0;
padding: 0;
padding-right: 10px;
}
.item-rgb .col-xs-8 {
margin: 0;
padding: 0;
padding-left: 10px;
}
.item-rgb .border-right {
border-right: 1px solid rgba(255, 255, 255, 0.5);
}
.item-rgb .rgb-mode {
display: inline-block;
width: 60px;
height: 50px;
cursor: pointer;
margin: 5px 5px 0 0;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
transition: 0.5s;
}
@media (min-width: 768px) {
.item-rgb .rgb-mode {
width: 50px;
margin: 5px 10px 0 0;
}
}
.item-rgb .rgb-mode.active {
/*border: 1px solid #fff;*/
}
.item-rgb .rgb-mode.active .rgb-mode-image {
box-shadow: inset 0 0 0 2px #fff;
}
.item-rgb .rgb-mode-image {
height: 100%;
width: 100%;
transition: 0.5s;
}
.item-rgb .rgb-mode-rainbow {
background: red; /* not working, let's see some red */
background: -moz-linear-gradient(left,
rgba(255, 0, 0, 1) 0%,
rgba(255, 255, 0, 1) 15%,
rgba(0, 255, 0, 1) 30%,
rgba(0, 255, 255, 1) 50%,
rgba(0, 0, 255, 1) 65%,
rgba(255, 0, 255, 1) 80%,
rgba(255, 0, 0, 1) 100%);
background: -webkit-gradient(linear, left top, right top,
color-stop(0%, rgba(255, 0, 0, 1)),
color-stop(15%, rgba(255, 255, 0, 1)),
color-stop(30%, rgba(0, 255, 0, 1)),
color-stop(50%, rgba(0, 255, 255, 1)),
color-stop(65%, rgba(0, 0, 255, 1)),
color-stop(80%, rgba(255, 0, 255, 1)),
color-stop(100%, rgba(255, 0, 0, 1)));
}
.item-rgb .rgb-mode-breath {
background: #000000; /* Old browsers */
background: -moz-linear-gradient(left, #000000 0%, #30ff60 51%, #000000 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(left, #000000 0%, #30ff60 51%, #000000 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to right, #000000 0%, #30ff60 51%, #000000 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#000000', endColorstr='#000000', GradientType=1);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

BIN
web/img/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Some files were not shown because too many files have changed in this diff Show More