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; |
||
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)) { |
||
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) { |
||
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'), |
||
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
Bug
Best Practice
introduced
by
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 |