smarthome-49 Divide Item Widgets from Item

This commit is contained in:
Alex Solomaha
2017-03-03 19:20:30 +02:00
parent 038c35ce5c
commit f0fdf497b6
40 changed files with 989 additions and 223 deletions

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',
];
}

View File

@@ -21,7 +21,8 @@
"kartik-v/yii2-datecontrol": "^1.9",
"voskobovich/yii2-linker-behavior": "4.0.1-rc",
"bower-asset/js-cookie": "^2.1",
"bower-asset/chart.js": ">=2.5"
"bower-asset/chart.js": ">=2.5",
"bower-asset/fontawesome-iconpicker": "^1.3"
},
"require-dev": {
"yiisoft/yii2-debug": "*",

40
composer.lock generated
View File

@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "47716d6fa73b8f351afd27ba07ca61ea",
"content-hash": "510df4f657a11c48c1c48bbc30239f09",
"hash": "d72e15d1c94855a26467586b784ffcb8",
"content-hash": "50f7bcdee8e1349910fd57865528edf4",
"packages": [
{
"name": "bower-asset/bootstrap",
@@ -87,6 +87,42 @@
],
"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",

View File

@@ -44,6 +44,11 @@ return [
'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' => [
@@ -53,20 +58,14 @@ 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' => [],
// 'js' => [],
],
],
],

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?') ?>,

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

@@ -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
{
@@ -77,19 +72,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',
@@ -97,9 +85,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],
];
}
@@ -111,20 +97,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', 'Значение по умолчанию'),
];
}
@@ -140,17 +120,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');
}
/**
@@ -174,7 +154,7 @@ 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_RGB => 'RGB',
];
}
@@ -188,16 +168,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');
}
@@ -210,10 +189,6 @@ class Item extends ActiveRecord
$title .= $model->name;
if ($appendRoomName) {
$title .= ' - ' . $model->room->name;
}
$result[$model->id] = $title;
}

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])

158
models/ItemWidget.php Normal file
View File

@@ -0,0 +1,158 @@
<?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],
[['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

@@ -55,6 +55,14 @@ class Room extends \yii\db\ActiveRecord
return $this->hasMany(Item::className(), ['room_id' => 'id'])->inverseOf('room');
}
/**
* @return \yii\db\ActiveQuery|ItemWidgetQuery
*/
public function getItemWidgets()
{
return $this->hasMany(ItemWidget::className(), ['room_id' => 'id'])->inverseOf('room');
}
/**
* @inheritdoc
* @return RoomQuery the active query used by this AR class.

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

@@ -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

@@ -0,0 +1,119 @@
<?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(),
'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

@@ -35,14 +35,6 @@ $this->params['in-card'] = false;
'columns' => [
'id',
'name',
[
'attribute' => 'room_id',
'filter' => Room::getList(),
'value' => function ($model) {
/** @var $model Item */
return $model->room->name;
},
],
[
'attribute' => 'board_id',
'filter' => Board::getList(),

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

@@ -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

@@ -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

@@ -6,7 +6,6 @@
use app\models\User;
use yii\helpers\Html;
use yii\grid\GridView;
use yii\widgets\Pjax;
$this->title = 'Пользователи';
@@ -20,11 +19,9 @@ $this->params['in-card'] = false;
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
<?= \app\widgets\DataTable::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'summaryOptions' => ['class' => 'alert alert-info'],
'layout' => '{summary}<div class="table-responsive">{items}</div>{pager}',
'columns' => [
'id',
'username',

View File

@@ -8,13 +8,15 @@ 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;
class ItemController extends Controller
class ItemController extends ActiveController
{
public $modelClass = 'app\models\Item';
/**
* @inheritdoc
*/
@@ -29,14 +31,6 @@ class ItemController extends Controller
];
}
/**
* @throws NotSupportedException
*/
public function actionIndex()
{
throw new NotSupportedException();
}
/**
* @param $item_id
* @return array

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';
}

View File

@@ -226,24 +226,21 @@ class CoreServer implements MessageComponentInterface
$this->userConnections[$user->id] = $conn;
// Prepare Items for User
$itemModels = Item::find()
->active()
->all();
$itemModels = Item::find()->all();
$items = [];
foreach ($itemModels as $itemModel) {
$itemData = [];
$itemData['id'] = $itemModel->id;
$itemData['type'] = $itemModel->type;
$itemData['room_id'] = $itemModel->room_id;
$itemData['type'] = $itemModel->widget->type;
$itemData['value_type'] = $itemModel->widget->value_type;
$itemData['room_id'] = $itemModel->widget->room_id;
$itemData['board_id'] = $itemModel->board_id;
$itemData['pin'] = $itemModel->pin;
$itemData['name'] = $itemModel->name;
$itemData['icon'] = $itemModel->icon;
$itemData['bg'] = $itemModel->bg;
$itemData['class'] = $itemModel->class;
$itemData['sort_order'] = $itemModel->sort_order;
$itemData['name'] = $itemModel->widget->getName();
$itemData['icon'] = $itemModel->widget->icon;
$itemData['html_class'] = $itemModel->widget->html_class;
$itemData['sort_order'] = $itemModel->widget->sort_order;
$itemData['value'] = $this->getItemSavedValue($itemModel->id, $itemModel->getDefaultNAValue());
@@ -356,9 +353,9 @@ class CoreServer implements MessageComponentInterface
}
switch ($data['type']) {
case 'turnON':
case 'turn_on':
return $this->handleTurnOn($from, $user, $data);
case 'turnOFF':
case 'turn_off':
return $this->handleTurnOff($from, $user, $data);
case 'rgb':
return $this->handleRgb($from, $user, $data);
@@ -410,7 +407,7 @@ class CoreServer implements MessageComponentInterface
$this->sendUsers([
'type' => 'value',
'item_id' => $item->id,
'item_type' => $item->type,
'value_type' => $item->widget->type,
'value' => $value,
]);
@@ -502,7 +499,7 @@ class CoreServer implements MessageComponentInterface
$this->sendUsers([
'type' => 'value',
'item_id' => $item->id,
'item_type' => $item->type,
'value_type' => $item->widget->type,
'value' => $value,
]);
@@ -1353,11 +1350,11 @@ class CoreServer implements MessageComponentInterface
$this->log("Loading items...");
/** @var Item[] $items */
$items = Item::find()->active()->all();
$items = Item::find()->all();
foreach ($items as $item) {
if (!$this->hasItemSavedValue($item->id)) {
$this->saveItemValue($item->id, $item->getDefaultValue(), $item->type, false);
$this->saveItemValue($item->id, $item->getDefaultNAValue(), $item->type, false);
}
}

View File

@@ -31,11 +31,15 @@ use yii\bootstrap\Nav;
],
'<li class="divider"></li>',
[
'label' => FA::i('toggle-on fa-fw') . 'Элементы',
'label' => FA::i('microchip fa-fw') . 'Элементы',
'url' => ['/admin/item/index'],
],
[
'label' => FA::i('hdd-o fa-fw') . 'Устройства',
'label' => FA::i('toggle-on fa-fw') . 'Виджеты',
'url' => ['/admin/item-widget/index'],
],
[
'label' => FA::i('wifi fa-fw') . 'Устройства',
'url' => ['/admin/board/index'],
],
[

View File

@@ -1,19 +1,17 @@
<?php
/* @var $this yii\web\View */
/* @var $item \app\models\Item */
use rmrevin\yii\fontawesome\FA;
/* @var $widget \app\models\ItemWidget */
?>
<div class="col-lg-3 col-md-4 col-sm-6">
<div class="panel-item panel-item-rgb withripple <?= $item->class ?>" data-item-id="<?= $item->id ?>">
<div class="panel-item panel-item-rgb withripple <?= $widget->html_class ?>" data-item-id="<?= $widget->item_id ?>">
<div class="panel-item-rgb-icon">
<?= FA::i($item->icon) ?>
<i class="fa <?= $widget->icon ?>"></i>
</div>
<div class="panel-item-rgb-name">
<?= $item->name ?>
<?= $widget->getName() ?>
</div>
</div>
</div>

View File

@@ -1,19 +1,17 @@
<?php
/* @var $this yii\web\View */
/* @var $item \app\models\Item */
use rmrevin\yii\fontawesome\FA;
/* @var $widget \app\models\ItemWidget */
?>
<div class="col-lg-3 col-md-4 col-sm-6">
<div class="panel-item panel-item-switch withripple <?= $item->class ?>" data-item-id="<?= $item->id ?>">
<div class="panel-item panel-item-switch withripple <?= $widget->html_class ?>" data-item-id="<?= $widget->item_id ?>">
<div class="panel-item-switch-icon">
<?= FA::i($item->icon) ?>
<i class="fa <?= $widget->icon ?>"></i>
</div>
<div class="panel-item-switch-name">
<?= $item->name ?>
<?= $widget->getName() ?>
</div>
</div>
</div>

View File

@@ -1,19 +1,17 @@
<?php
/* @var $this yii\web\View */
/* @var $item \app\models\Item */
use rmrevin\yii\fontawesome\FA;
/* @var $widget \app\models\ItemWidget */
?>
<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6">
<div class="panel-item panel-item-variable bg-<?= $item->bg ?> withripple"
title="<?= $item->name ?>"
data-item-id="<?= $item->id ?>">
<div class="panel-item panel-item-variable <?= $widget->html_class ?> withripple"
title="<?= $widget->getName() ?>"
data-item-id="<?= $widget->item_id ?>">
<div class="item-variable-icon">
<?= FA::i($item->icon) ?>
<i class="fa <?= $widget->icon ?>"></i>
</div>
<div class="item-variable-value item-value"><?= $item->getDefaultNAValue() ?></div>
<div class="item-variable-value item-value"><?= $widget->item->getDefaultNAValue() ?></div>
</div>
</div>

View File

@@ -43,23 +43,23 @@ $this->title = 'Панель Управления';
<div class="card-body">
<div class="row panel-items-variable">
<?php foreach ($room->getItems()->variables()->active()->all() as $item): ?>
<?php foreach ($room->getItemWidgets()->variables()->active()->all() as $widget): ?>
<?= $this->render('_variable', [
'item' => $item,
'widget' => $widget,
]) ?>
<?php endforeach; ?>
</div>
<div class="row panel-items-switch">
<?php foreach ($room->getItems()->switches()->active()->all() as $item): ?>
<?php foreach ($room->getItemWidgets()->switches()->active()->all() as $widget): ?>
<?= $this->render('_switch', [
'item' => $item,
'widget' => $widget,
]) ?>
<?php endforeach; ?>
</div>
<div class="row panel-items-rgb">
<?php foreach ($room->getItems()->rgb()->all() as $item): ?>
<?php foreach ($room->getItemWidgets()->rgb()->all() as $widget): ?>
<?= $this->render('_rgb', [
'item' => $item,
'widget' => $widget,
]) ?>
<?php endforeach; ?>
</div>

View File

@@ -346,22 +346,6 @@ body {
user-select: none;
}
.popover {
width: 300px;
box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
max-width: none;
border-radius: 0;
padding: 0;
}
.popover-title {
display: none;
}
.popover-content {
padding: 0;
}
.rgb-widget-form {
padding: 10px;
}
@@ -385,12 +369,6 @@ body {
margin: 0;
}
@media (min-width: 767px) {
.popover {
width: 500px;
}
}
/* Snackbar fixes */
#snackbar-container {
position: fixed;

View File

@@ -44,3 +44,22 @@
.control-panel {
display: none;
}
/* Popover */
.popover {
width: 300px;
box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
max-width: none;
border-radius: 0;
padding: 0;
}
.popover-content {
padding: 0;
}
@media (min-width: 767px) {
.popover {
width: 500px;
}
}

View File

@@ -11,6 +11,6 @@
font-style: italic;
}
.select2-container--krajee .select2-selection--single {
line-height: 2;
.fontawesome-iconpicker-input {
display: block;
}

View File

@@ -48,7 +48,7 @@ function onMessage(e) {
saveItemValue(id, value.value);
}
updateItemValue(value.id, value.type, value.value);
updateItemValue(value.id, value.type, value.value, value.value_type);
}
});
@@ -128,7 +128,7 @@ function getSavedItemValue(itemId) {
return itemValues[itemId];
}
function updateItemValue(id, type, value) {
function updateItemValue(id, type, value, value_type) {
type = parseInt(type);
switch (type) {
@@ -143,33 +143,37 @@ function updateItemValue(id, type, value) {
break;
case 20: // Variable
itemSetValue(id, value);
break;
case 21: // Variable Temperature
itemSetValue(id, value + ' °C');
break;
case 22: // Variable Humidity
itemSetValue(id, value + '%');
break;
case 25: // Variable boolean
if (Boolean(value)) {
if (value != 'N/A') {
value = 'да';
}
} else {
value = 'нет';
if (!value_type || value_type == null) {
return itemSetValue(id, value);
}
itemSetValue(id, value);
switch (value_type) {
case 10: // Boolean
if (Boolean(value)) {
if (value != 'N/A') {
value = 'да';
}
} else {
value = 'нет';
}
break;
case 26: // Variable boolean door
if (value) {
if (value != 'N/A') {
value = 'открыто';
}
} else {
value = 'закрыто';
break;
case 20: // Variable boolean door
if (value) {
if (value != 'N/A') {
value = 'открыто';
}
} else {
value = 'закрыто';
}
break;
case 30: // Celsius
value += ' °C';
break;
case 40: // Percent
value += '%';
break;
}
itemSetValue(id, value);
@@ -187,7 +191,7 @@ $(document).ready(function () {
var item_id = $this.data('item-id');
send({
"type": $this.hasClass('off') ? 'turnON' : 'turnOFF',
"type": $this.hasClass('off') ? 'turn_on' : 'turn_off',
"item_id": item_id
});
});