1 | <?php |
||||
2 | /** |
||||
3 | * Server module for HiPanel |
||||
4 | * |
||||
5 | * @link https://github.com/hiqdev/hipanel-module-server |
||||
6 | * @package hipanel-module-server |
||||
7 | * @license BSD-3-Clause |
||||
8 | * @copyright Copyright (c) 2015-2019, HiQDev (http://hiqdev.com/) |
||||
9 | */ |
||||
10 | |||||
11 | namespace hipanel\modules\server\grid; |
||||
12 | |||||
13 | use hipanel\base\Model; |
||||
14 | use hipanel\grid\BoxedGridView; |
||||
15 | use hipanel\grid\MainColumn; |
||||
16 | use hipanel\grid\RefColumn; |
||||
17 | use hipanel\grid\XEditableColumn; |
||||
18 | use hipanel\helpers\StringHelper; |
||||
19 | use hipanel\helpers\Url; |
||||
20 | use hipanel\modules\finance\models\Sale; |
||||
21 | use hipanel\modules\hosting\controllers\AccountController; |
||||
22 | use hipanel\modules\hosting\controllers\IpController; |
||||
23 | use hipanel\modules\server\menus\ServerActionsMenu; |
||||
24 | use hipanel\modules\server\models\Consumption; |
||||
25 | use hipanel\modules\server\models\HardwareSale; |
||||
26 | use hipanel\modules\server\models\Server; |
||||
27 | use hipanel\modules\server\widgets\DiscountFormatter; |
||||
28 | use hipanel\modules\server\widgets\Expires; |
||||
29 | use hipanel\modules\server\widgets\OSFormatter; |
||||
30 | use hipanel\modules\server\widgets\ResourceConsumptionTable; |
||||
31 | use hipanel\modules\server\widgets\State; |
||||
32 | use hipanel\widgets\ArraySpoiler; |
||||
33 | use hipanel\widgets\gridLegend\ColorizeGrid; |
||||
34 | use hipanel\widgets\gridLegend\GridLegend; |
||||
35 | use hipanel\widgets\Label; |
||||
36 | use hiqdev\yii2\menus\grid\MenuColumn; |
||||
37 | use Tuck\Sort\Sort; |
||||
38 | use Yii; |
||||
39 | use yii\data\ArrayDataProvider; |
||||
40 | use yii\helpers\ArrayHelper; |
||||
41 | use yii\helpers\Html; |
||||
42 | |||||
43 | class ServerGridView extends BoxedGridView |
||||
44 | { |
||||
45 | use ColorizeGrid; |
||||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||||
46 | |||||
47 | public $controllerUrl = '@server'; |
||||
48 | |||||
49 | /** |
||||
50 | * @var array |
||||
51 | */ |
||||
52 | public $osImages; |
||||
53 | |||||
54 | public function init() |
||||
55 | { |
||||
56 | parent::init(); |
||||
57 | |||||
58 | $this->view->registerCss(' |
||||
59 | .tariff-chain { |
||||
60 | list-style: none; |
||||
61 | background-color: transparent; |
||||
62 | } |
||||
63 | .tariff-chain > li { |
||||
64 | display: inline-block; |
||||
65 | } |
||||
66 | .tariff-chain > li + li:before { |
||||
67 | font: normal normal normal 14px/1 FontAwesome; |
||||
68 | content: "\f178\00a0"; |
||||
69 | padding: 0 5px; |
||||
70 | color: #ccc; |
||||
71 | } |
||||
72 | .inactiveLink { |
||||
73 | pointer-events: none; |
||||
74 | cursor: default; |
||||
75 | } |
||||
76 | '); |
||||
77 | } |
||||
78 | |||||
79 | protected function formatTariff($model) |
||||
80 | { |
||||
81 | $user = Yii::$app->user; |
||||
82 | $models = []; |
||||
83 | $html = ''; |
||||
84 | if ($user->can('sale.read') && isset($model->sales)) { |
||||
0 ignored issues
–
show
The method
can() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||||
85 | foreach ($model->sales as $sale) { |
||||
86 | $models[] = $sale; |
||||
87 | } |
||||
88 | } elseif ($user->can('plan.read')) { |
||||
89 | if (!empty($model->parent_tariff)) { |
||||
90 | $title = $model->parent_tariff; |
||||
91 | } else { |
||||
92 | $title = $model->tariff; |
||||
93 | } |
||||
94 | |||||
95 | $models[] = new Sale(['tariff' => $title, 'tariff_id' => $model->tariff_id]); |
||||
96 | } else { |
||||
97 | $models[] = new Sale([ |
||||
98 | 'tariff' => $model->tariff, |
||||
99 | 'tariff_id' => $model->tariff_id, |
||||
100 | ]); |
||||
101 | } |
||||
102 | |||||
103 | foreach ($models as $model) { |
||||
0 ignored issues
–
show
|
|||||
104 | if ($model->tariff) { |
||||
105 | $tariff = $model->tariff_id ? Html::a($model->tariff, [ |
||||
106 | '@plan/view', |
||||
107 | 'id' => $model->tariff_id, |
||||
108 | ]) : $model->tariff; |
||||
109 | $client = $model->seller ? '(' . Html::a($model->seller, [ |
||||
110 | '@client/view', 'id' => $model->seller_id, |
||||
111 | ]) . ')' : ''; |
||||
112 | |||||
113 | $html .= Html::tag('li', $tariff . ' ' . $client); |
||||
114 | } |
||||
115 | } |
||||
116 | |||||
117 | return Html::tag('ul', $html, [ |
||||
118 | 'class' => 'tariff-chain ' . ($user->can('support') ?: 'inactiveLink'), |
||||
0 ignored issues
–
show
Are you sure
$user->can('support') ?: 'inactiveLink' of type string|true can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
119 | 'style' => 'margin: 0; padding: 0;', |
||||
120 | ]); |
||||
121 | } |
||||
122 | |||||
123 | public function columns() |
||||
124 | { |
||||
125 | $canAdmin = Yii::$app->user->can('admin'); |
||||
126 | $canSupport = Yii::$app->user->can('support'); |
||||
127 | |||||
128 | return array_merge(parent::columns(), [ |
||||
129 | 'server' => [ |
||||
130 | 'class' => MainColumn::class, |
||||
131 | 'attribute' => 'name', |
||||
132 | 'filterAttribute' => 'name_like', |
||||
133 | 'note' => Yii::$app->user->can('server.set-label') ? 'label' : 'note', |
||||
134 | 'noteOptions' => [ |
||||
135 | 'url' => Yii::$app->user->can('server.set-label') ? Url::to('set-label') : (Yii::$app->user->can('server.set-note') ? Url::to('set-note') : ''), |
||||
136 | ], |
||||
137 | 'badges' => function ($model) use ($canSupport) { |
||||
138 | $badges = ''; |
||||
139 | if ($canSupport) { |
||||
140 | if ($model->wizzarded) { |
||||
141 | $badges .= Label::widget(['label' => 'W', 'tag' => 'sup', 'color' => 'success']); |
||||
142 | } |
||||
143 | } |
||||
144 | $badges .= Label::widget(['label' => Yii::t('hipanel:server', $model->type_label), 'tag' => 'sup', 'color' => 'info']); |
||||
145 | |||||
146 | return $badges; |
||||
147 | }, |
||||
148 | ], |
||||
149 | 'dc' => [ |
||||
150 | 'attribute' => 'dc', |
||||
151 | 'filter' => false, |
||||
152 | ], |
||||
153 | 'state' => [ |
||||
154 | 'class' => RefColumn::class, |
||||
155 | 'filterOptions' => ['class' => 'narrow-filter'], |
||||
156 | 'i18nDictionary' => 'hipanel:server', |
||||
157 | 'format' => 'raw', |
||||
158 | 'gtype' => 'state,device', |
||||
159 | 'visible' => $canSupport, |
||||
160 | 'value' => function ($model) { |
||||
161 | $html = State::widget(compact('model')); |
||||
162 | if ($model->status_time) { |
||||
163 | $html .= ' ' . Html::tag('nobr', Yii::t('hipanel:server', 'since {date}', ['date' => Yii::$app->formatter->asDate($model->status_time)])); |
||||
164 | } |
||||
165 | |||||
166 | return $html; |
||||
167 | }, |
||||
168 | ], |
||||
169 | 'panel' => [ |
||||
170 | 'attribute' => 'panel', |
||||
171 | 'format' => 'html', |
||||
172 | 'contentOptions' => ['class' => 'text-uppercase'], |
||||
173 | 'value' => function ($model) use ($canSupport) { |
||||
174 | $value = $model->getPanel() ? Yii::t('hipanel:server:panel', $model->getPanel()) : Yii::t('hipanel:server:panel', 'No control panel'); |
||||
175 | if ($canSupport) { |
||||
176 | $value .= $model->wizzarded ? Label::widget([ |
||||
177 | 'label' => 'W', 'tag' => 'sup', 'color' => 'success', |
||||
178 | ]) : ''; |
||||
179 | } |
||||
180 | |||||
181 | return $value; |
||||
182 | }, |
||||
183 | ], |
||||
184 | 'os' => [ |
||||
185 | 'attribute' => 'os', |
||||
186 | 'format' => 'raw', |
||||
187 | 'value' => function ($model) { |
||||
188 | return OSFormatter::widget([ |
||||
189 | 'osimages' => $this->osImages, |
||||
190 | 'imageName' => $model->osimage, |
||||
191 | ]); |
||||
192 | }, |
||||
193 | ], |
||||
194 | 'os_and_panel' => [ |
||||
195 | 'attribute' => 'os', |
||||
196 | 'format' => 'raw', |
||||
197 | 'value' => function ($model) { |
||||
198 | $html = OSFormatter::widget([ |
||||
199 | 'osimages' => $this->osImages, |
||||
200 | 'imageName' => $model->osimage, |
||||
201 | ]); |
||||
202 | $html .= ' ' . ($model->panel ?: ''); |
||||
203 | |||||
204 | return $html; |
||||
205 | }, |
||||
206 | ], |
||||
207 | 'discount' => [ |
||||
208 | 'attribute' => 'discount', |
||||
209 | 'label' => Yii::t('hipanel:server', 'Discount'), |
||||
210 | 'format' => 'raw', |
||||
211 | 'headerOptions' => ['style' => 'width: 1em'], |
||||
212 | 'value' => function ($model) { |
||||
213 | return DiscountFormatter::widget([ |
||||
214 | 'current' => $model->discounts['fee']['current'], |
||||
215 | 'next' => $model->discounts['fee']['next'], |
||||
216 | ]); |
||||
217 | }, |
||||
218 | ], |
||||
219 | 'expires' => [ |
||||
220 | 'filter' => false, |
||||
221 | 'format' => 'raw', |
||||
222 | 'headerOptions' => ['style' => 'width: 1em'], |
||||
223 | 'visible' => $canSupport, |
||||
224 | 'value' => function ($model) { |
||||
225 | return Expires::widget(compact('model')); |
||||
226 | }, |
||||
227 | ], |
||||
228 | 'tariff' => [ |
||||
229 | 'format' => 'raw', |
||||
230 | 'filterAttribute' => 'tariff_like', |
||||
231 | 'value' => function ($model) { |
||||
232 | return $this->formatTariff($model); |
||||
233 | }, |
||||
234 | ], |
||||
235 | 'tariff_and_discount' => [ |
||||
236 | 'attribute' => 'tariff', |
||||
237 | 'filterAttribute' => 'tariff_like', |
||||
238 | 'format' => 'raw', |
||||
239 | 'value' => function ($model) { |
||||
240 | return $this->formatTariff($model) . ' ' . DiscountFormatter::widget([ |
||||
241 | 'current' => $model->discounts['fee']['current'], |
||||
242 | 'next' => $model->discounts['fee']['next'], |
||||
243 | ]); |
||||
244 | }, |
||||
245 | ], |
||||
246 | 'ip' => [ |
||||
247 | 'filter' => false, |
||||
248 | ], |
||||
249 | 'mac' => [ |
||||
250 | 'filter' => false, |
||||
251 | ], |
||||
252 | 'ips' => [ |
||||
253 | 'format' => 'raw', |
||||
254 | 'attribute' => 'ips', |
||||
255 | 'filter' => false, |
||||
256 | 'contentOptions' => [ |
||||
257 | 'class' => 'text-center', |
||||
258 | 'style' => 'width:1%; white-space:nowrap;', |
||||
259 | ], |
||||
260 | 'value' => function ($model) { |
||||
261 | return ArraySpoiler::widget([ |
||||
262 | 'data' => ArrayHelper::getColumn($model->ips, 'ip'), |
||||
263 | 'delimiter' => '<br />', |
||||
264 | 'visibleCount' => 1, |
||||
265 | 'formatter' => function ($ip, $idx) use ($model) { |
||||
266 | if ($idx === 0) { |
||||
267 | return Html::a($ip, IpController::getSearchUrl(['server_in' => $model->name]), [ |
||||
268 | 'class' => 'text-bold', |
||||
269 | 'target' => '_blank', |
||||
270 | ]); |
||||
271 | } |
||||
272 | |||||
273 | return $ip; |
||||
274 | }, |
||||
275 | 'button' => [ |
||||
276 | 'label' => Yii::t('hipanel:server', '') . ' +' . (count($model->ips) - 1), |
||||
277 | 'tag' => 'button', |
||||
278 | 'type' => 'button', |
||||
279 | 'class' => 'btn btn-xs btn-flat', |
||||
280 | 'style' => 'font-size: 10px', |
||||
281 | 'popoverOptions' => [ |
||||
282 | 'html' => true, |
||||
283 | 'placement' => 'bottom', |
||||
284 | 'title' => Yii::t('hipanel:server', 'IPs'), |
||||
285 | 'template' => ' |
||||
286 | <div class="popover" role="tooltip"> |
||||
287 | <div class="arrow"></div> |
||||
288 | <h3 class="popover-title"></h3> |
||||
289 | <div class="popover-content" style="min-width: 15rem; height: 15rem; overflow-x: scroll;"></div> |
||||
290 | </div> |
||||
291 | ', |
||||
292 | ], |
||||
293 | ], |
||||
294 | ]); |
||||
295 | }, |
||||
296 | ], |
||||
297 | 'sale_time' => [ |
||||
298 | 'attribute' => 'sale_time', |
||||
299 | 'format' => 'datetime', |
||||
300 | ], |
||||
301 | 'note' => [ |
||||
302 | 'class' => XEditableColumn::class, |
||||
303 | 'pluginOptions' => [ |
||||
304 | 'url' => Url::to('set-note'), |
||||
305 | ], |
||||
306 | 'widgetOptions' => [ |
||||
307 | 'linkOptions' => [ |
||||
308 | 'data-type' => 'textarea', |
||||
309 | ], |
||||
310 | ], |
||||
311 | 'visible' => Yii::$app->user->can('server.set-note'), |
||||
312 | ], |
||||
313 | 'label' => [ |
||||
314 | 'class' => XEditableColumn::class, |
||||
315 | 'pluginOptions' => [ |
||||
316 | 'url' => Url::to('set-label'), |
||||
317 | ], |
||||
318 | 'widgetOptions' => [ |
||||
319 | 'linkOptions' => [ |
||||
320 | 'data-type' => 'textarea', |
||||
321 | ], |
||||
322 | ], |
||||
323 | 'visible' => Yii::$app->user->can('server.set-label'), |
||||
324 | ], |
||||
325 | 'type' => [ |
||||
326 | 'format' => 'html', |
||||
327 | 'filter' => false, |
||||
328 | 'value' => function ($model) { |
||||
329 | return Html::tag('span', $model->type_label, ['class' => 'label label-default']); |
||||
330 | }, |
||||
331 | ], |
||||
332 | 'detailed_type' => [ |
||||
333 | 'label' => Yii::t('hipanel', 'Type'), |
||||
334 | 'format' => 'html', |
||||
335 | 'filter' => false, |
||||
336 | 'value' => function ($model) { |
||||
337 | return Html::tag('span', $model->type_label, ['class' => 'label label-default']); |
||||
338 | }, |
||||
339 | 'contentOptions' => function ($model) { |
||||
340 | return GridLegend::create($this->findOrFailGridLegend($model))->gridColumnOptions('actions'); |
||||
341 | }, |
||||
342 | ], |
||||
343 | 'rack' => [ |
||||
344 | 'class' => BindingColumn::class, |
||||
345 | ], |
||||
346 | 'net' => [ |
||||
347 | 'class' => BindingColumn::class, |
||||
348 | ], |
||||
349 | 'kvm' => [ |
||||
350 | 'class' => BindingColumn::class, |
||||
351 | ], |
||||
352 | 'pdu' => [ |
||||
353 | 'class' => BindingColumn::class, |
||||
354 | ], |
||||
355 | 'ipmi' => [ |
||||
356 | 'class' => BindingColumn::class, |
||||
357 | ], |
||||
358 | 'location' => [ |
||||
359 | 'class' => BindingColumn::class, |
||||
360 | ], |
||||
361 | 'nums' => [ |
||||
362 | 'label' => '', |
||||
363 | 'format' => 'raw', |
||||
364 | 'value' => function ($model) { |
||||
365 | $ips_num = $model->ips_num; |
||||
366 | $ips = $ips_num ? Html::a("$ips_num ips", IpController::getSearchUrl(['server' => $model->name])) : 'no ips'; |
||||
367 | $act_acs_num = $model->acs_num - $model->del_acs_num; |
||||
368 | $del_acs_num = $model->del_acs_num; |
||||
369 | $acs_num = $act_acs_num . ($del_acs_num ? "+$del_acs_num" : ''); |
||||
370 | $acs = $acs_num ? Html::a("$acs_num acc", AccountController::getSearchUrl(['server' => $model->name])) : 'no acc'; |
||||
371 | |||||
372 | return Html::tag('nobr', $ips) . ' ' . Html::tag('nobr', $acs); |
||||
373 | }, |
||||
374 | ], |
||||
375 | 'monthly_fee' => [ |
||||
376 | 'label' => Yii::t('hipanel:finance', 'Monthly fee'), |
||||
377 | 'format' => 'html', |
||||
378 | 'filter' => false, |
||||
379 | 'value' => function ($model) { |
||||
380 | return $this->getMonthlyFee($model); |
||||
381 | }, |
||||
382 | 'visible' => Yii::$app->user->can('consumption.read'), |
||||
383 | ], |
||||
384 | 'traffic' => [ |
||||
385 | 'label' => Yii::t('hipanel:server', 'Traffic'), |
||||
386 | 'format' => 'html', |
||||
387 | 'filter' => false, |
||||
388 | 'value' => function ($model) { |
||||
389 | return isset($model->consumptions['overuse,server_traf_max']) ? $this->getFormattedConsumptionFor($model->consumptions['overuse,server_traf_max']) : null; |
||||
390 | }, |
||||
391 | 'visible' => Yii::$app->user->can('consumption.read'), |
||||
392 | ], |
||||
393 | 'additional_services' => [ |
||||
394 | 'label' => Yii::t('hipanel:server', 'Additional services'), |
||||
395 | 'format' => 'raw', |
||||
396 | 'filter' => false, |
||||
397 | 'contentOptions' => ['class' => 'no-padding'], |
||||
398 | 'value' => function ($model) { |
||||
399 | return $this->getAdditionalServices($model); |
||||
400 | }, |
||||
401 | 'visible' => Yii::$app->user->can('consumption.read'), |
||||
402 | ], |
||||
403 | 'type_of_sale' => [ |
||||
404 | 'label' => Yii::t('hipanel:server', 'Type of sale'), |
||||
405 | 'format' => 'raw', |
||||
406 | 'filter' => false, |
||||
407 | 'value' => function (Server $model) { |
||||
408 | return $this->getTypeOfSale($model); |
||||
409 | }, |
||||
410 | 'visible' => Yii::$app->user->can('consumption.read'), |
||||
411 | ], |
||||
412 | 'actions' => [ |
||||
413 | 'class' => MenuColumn::class, |
||||
414 | 'menuClass' => ServerActionsMenu::class, |
||||
415 | 'contentOptions' => [ |
||||
416 | 'class' => 'text-center', |
||||
417 | 'style' => 'width:1%; white-space:nowrap;', |
||||
418 | ], |
||||
419 | ], |
||||
420 | 'hwsummary' => [ |
||||
421 | 'filterAttribute' => 'hwsummary_like', |
||||
422 | 'label' => Yii::t('hipanel:server', 'Hardware Summary'), |
||||
423 | ], |
||||
424 | 'hwcomment' => [ |
||||
425 | 'filter' => false, |
||||
426 | 'label' => Yii::t('hipanel:server', 'Hardware Comment'), |
||||
427 | ], |
||||
428 | ]); |
||||
429 | } |
||||
430 | |||||
431 | private function getFormattedConsumptionFor(Consumption $consumption): string |
||||
432 | { |
||||
433 | $result = ''; |
||||
434 | $widget = Yii::createObject(['class' => ResourceConsumptionTable::class, 'model' => $consumption]); |
||||
435 | |||||
436 | if ($limit = $widget->getFormatted($consumption, $consumption->limit)) { |
||||
0 ignored issues
–
show
The property
limit does not exist on hipanel\modules\server\models\Consumption . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
437 | $result .= sprintf('%s: %s<br />', |
||||
438 | Html::tag('b', Yii::t('hipanel:server', 'included')), |
||||
439 | $limit |
||||
440 | ); |
||||
441 | } |
||||
442 | if ($price = $consumption->getFormattedPrice()) { |
||||
443 | $result .= sprintf('%s: %s', |
||||
444 | Html::tag('b', Yii::t('hipanel:server', 'price')), |
||||
445 | $price |
||||
446 | ); |
||||
447 | } |
||||
448 | |||||
449 | return $result; |
||||
450 | } |
||||
451 | |||||
452 | private function getMonthlyFee($model): string |
||||
453 | { |
||||
454 | $unionConsumption = new Consumption(); |
||||
455 | $prices = []; |
||||
456 | if ($model->consumptions) { |
||||
457 | array_walk($model->consumptions, function (Consumption $consumption) use (&$prices) { |
||||
458 | if ($consumption->type && $consumption->hasFormattedAttributes() && StringHelper::startsWith($consumption->type, 'monthly,')) { |
||||
459 | if ($consumption->price) { |
||||
0 ignored issues
–
show
The property
price does not exist on hipanel\modules\server\models\Consumption . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
460 | $consumption->setAttribute('prices', [$consumption->currency => $consumption->price]); |
||||
0 ignored issues
–
show
The property
currency does not exist on hipanel\modules\server\models\Consumption . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
461 | } |
||||
462 | foreach ($consumption->prices as $currency => $price) { |
||||
0 ignored issues
–
show
The property
prices does not exist on hipanel\modules\server\models\Consumption . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
463 | $prices[$currency] += $price; |
||||
464 | } |
||||
465 | } |
||||
466 | }); |
||||
467 | } |
||||
468 | $unionConsumption->setAttribute('prices', $prices); |
||||
469 | |||||
470 | return $unionConsumption->getFormattedPrice(); |
||||
471 | } |
||||
472 | |||||
473 | private function getAdditionalServices($model): string |
||||
474 | { |
||||
475 | $additional = new class() extends Model { |
||||
476 | /** |
||||
477 | * @var string |
||||
478 | */ |
||||
479 | public $typeLabel; |
||||
480 | |||||
481 | /** |
||||
482 | * @var string |
||||
483 | */ |
||||
484 | public $value; |
||||
485 | }; |
||||
486 | $models = []; |
||||
487 | foreach (['overuse,support_time', 'overuse,backup_du', 'monthly,win_license'] as $type) { |
||||
488 | if (isset($model->consumptions[$type]) && $model->consumptions[$type]->hasFormattedAttributes()) { |
||||
489 | $consumption = $model->consumptions[$type]; |
||||
490 | $models[] = new $additional([ |
||||
491 | 'typeLabel' => Yii::t('hipanel.server.consumption.type', $consumption->typeLabel), |
||||
492 | 'value' => $this->getFormattedConsumptionFor($consumption), |
||||
493 | ]); |
||||
494 | } |
||||
495 | } |
||||
496 | |||||
497 | return \yii\grid\GridView::widget([ |
||||
498 | 'layout' => '{items}', |
||||
499 | 'showOnEmpty' => false, |
||||
500 | 'emptyText' => '', |
||||
501 | 'tableOptions' => ['class' => 'table table-striped table-condensed'], |
||||
502 | 'headerRowOptions' => [ |
||||
503 | 'style' => 'display: none;', |
||||
504 | ], |
||||
505 | 'dataProvider' => new ArrayDataProvider(['allModels' => $models, 'pagination' => false]), |
||||
506 | 'columns' => [ |
||||
507 | [ |
||||
508 | 'attribute' => 'typeLabel', |
||||
509 | ], |
||||
510 | [ |
||||
511 | 'attribute' => 'value', |
||||
512 | 'format' => 'html', |
||||
513 | ], |
||||
514 | ], |
||||
515 | ]); |
||||
516 | } |
||||
517 | |||||
518 | private function getTypeOfSale(Server $model): string |
||||
519 | { |
||||
520 | $html = ''; |
||||
521 | $badgeColors = [ |
||||
522 | 'leasing' => 'bg-orange', |
||||
523 | 'rent' => 'bg-purple', |
||||
524 | 'sold' => 'bg-olive', |
||||
525 | ]; |
||||
526 | |||||
527 | if (empty($model->hardwareSales)) { |
||||
528 | return $html; |
||||
529 | } |
||||
530 | |||||
531 | $salesByType = [ |
||||
532 | HardwareSale::USAGE_TYPE_LEASING => [], |
||||
533 | HardwareSale::USAGE_TYPE_COLO => [], |
||||
534 | HardwareSale::USAGE_TYPE_RENT => [], |
||||
535 | ]; |
||||
536 | foreach ($model->hardwareSales as $sale) { |
||||
537 | $salesByType[$sale->usage_type][] = $sale; |
||||
538 | } |
||||
539 | |||||
540 | foreach ($salesByType as $usageType => $sales) { |
||||
541 | $html .= ArraySpoiler::widget([ |
||||
542 | 'data' => Sort::by($sales, function (HardwareSale $sale) { |
||||
543 | $order = ['CHASSIS', 'MOTHERBOARD', 'CPU', 'RAM', 'HDD', 'SSD']; |
||||
544 | $type = substr($sale->part, 0, strpos($sale->part, ':')); |
||||
545 | $key = array_search($type, $order, true); |
||||
546 | if ($key !== false) { |
||||
547 | return $key; |
||||
548 | } |
||||
549 | |||||
550 | return INF; |
||||
551 | }), |
||||
552 | 'delimiter' => '<br/>', |
||||
553 | 'visibleCount' => 0, |
||||
554 | 'button' => [ |
||||
555 | 'label' => (function () use ($usageType, $sales) { |
||||
556 | if ($usageType === HardwareSale::USAGE_TYPE_LEASING) { |
||||
557 | /** @var \DateTime $maxLeasingDate */ |
||||
558 | $maxLeasingDate = array_reduce($sales, function (\DateTime $max, HardwareSale $item) { |
||||
559 | $date = $item->saleTime(); |
||||
560 | |||||
561 | return $date > $max ? $date : $max; |
||||
562 | }, new \DateTime()); |
||||
563 | |||||
564 | return Yii::t('hipanel:server', $usageType) . ' ' . \count($sales) |
||||
565 | . '<br />' . $maxLeasingDate->format('d.m.Y'); |
||||
566 | } |
||||
567 | |||||
568 | return Yii::t('hipanel:server', $usageType) . ' ' . \count($sales); |
||||
569 | })(), |
||||
570 | 'tag' => 'button', |
||||
571 | 'type' => 'button', |
||||
572 | 'class' => "btn btn-xs {$badgeColors[$usageType]}", |
||||
573 | 'popoverOptions' => [ |
||||
574 | 'html' => true, |
||||
575 | 'placement' => 'bottom', |
||||
576 | 'title' => Yii::t('hipanel:server', 'Parts') . ' ' |
||||
577 | . Html::a( |
||||
578 | Yii::t('hipanel:server', 'To new tab {icon}', ['icon' => '<i class="fa fa-external-link"></i>']), |
||||
579 | Url::toSearch('part', ['dst_name_in' => $model->name]), |
||||
580 | ['class' => 'pull-right', 'target' => '_blank'] |
||||
581 | ), |
||||
582 | 'template' => ' |
||||
583 | <div class="popover" role="tooltip"> |
||||
584 | <div class="arrow"></div> |
||||
585 | <h3 class="popover-title"></h3> |
||||
586 | <div class="popover-content" style="height: 25rem; overflow-x: scroll;"></div> |
||||
587 | </div> |
||||
588 | ', |
||||
589 | ], |
||||
590 | ], |
||||
591 | 'formatter' => function (HardwareSale $item) { |
||||
592 | $additionalInfo = null; |
||||
593 | $title = $item->part; |
||||
594 | if (isset($item->serialno)) { |
||||
595 | $title .= ': ' . $item->serialno; |
||||
596 | } |
||||
597 | |||||
598 | if (isset($item->leasing_till)) { |
||||
599 | $additionalInfo = Yii::t('hipanel:server', '{since} — {till}', [ |
||||
600 | 'since' => Yii::$app->formatter->asDate($item->leasing_since, 'short'), |
||||
601 | 'till' => Yii::$app->formatter->asDate($item->leasing_till, 'short'), |
||||
602 | ]); |
||||
603 | } |
||||
604 | |||||
605 | if (isset($item->sale_time)) { |
||||
606 | $additionalInfo = Yii::t('hipanel:server', 'since {date}', [ |
||||
607 | 'date' => Yii::$app->formatter->asDate($item->sale_time, 'short'), |
||||
608 | ]); |
||||
609 | } |
||||
610 | |||||
611 | return Html::a( |
||||
612 | $title, |
||||
613 | ['@part/view', 'id' => $item['part_id']], |
||||
614 | ['class' => 'text-nowrap', 'target' => '_blank'] |
||||
615 | ) . ($additionalInfo ? " ($additionalInfo)" : ''); |
||||
616 | }, |
||||
617 | ]); |
||||
618 | } |
||||
619 | |||||
620 | return $html; |
||||
621 | } |
||||
622 | } |
||||
623 |