mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
New Blade Components: x-device-link, x-port-link, x-graph-row, x-popup (#13197)
* working popover * popup component * cleanup * finalize device-link component * attributes WIP * working graph component * widgets WIP * More dynamic configs * Graph row component * Build CSS so we can use a dark theme * graph row set columns * only one popup visible at a time. * Just set graph row width statically * responsive WIP * rsponsive option for graph-row "working" * remove @deviceLink and @portLink * fix non-responsive graph row * update js/css * fix style * bad type? * types * types * types #3 * remove testing code * full rebel, no closing tags for meta and link * match previous formatting * fix vlans display * restore newline * remove silly comment * remove unused line * style I guess
This commit is contained in:
@@ -99,7 +99,7 @@ class Smokeping
|
||||
'device' => $device,
|
||||
'graph' => [
|
||||
'type' => 'smokeping_' . $direction,
|
||||
'device' => $this->device->device_id,
|
||||
'device' => $this->device,
|
||||
$remote => $device->device_id,
|
||||
],
|
||||
];
|
||||
|
||||
@@ -139,10 +139,8 @@ class Url
|
||||
}
|
||||
|
||||
$content = '<div class=list-large>' . addslashes(htmlentities($port->device->displayName() . ' - ' . $label)) . '</div>';
|
||||
if ($port['port_descr_descr']) {
|
||||
$content .= addslashes(\LibreNMS\Util\Clean::html($port['port_descr_descr'], [])) . '<br />';
|
||||
} elseif ($port['ifAlias']) {
|
||||
$content .= addslashes(htmlentities($port->ifAlias)) . '<br />';
|
||||
if ($description = $port->getDescription()) {
|
||||
$content .= addslashes(htmlentities($description)) . '<br />';
|
||||
}
|
||||
|
||||
$content .= "<div style=\'width: 850px\'>";
|
||||
|
||||
@@ -203,13 +203,10 @@ class DeviceController extends TableController
|
||||
*/
|
||||
private function getHostname($device)
|
||||
{
|
||||
$hostname = Url::deviceLink($device);
|
||||
|
||||
if ($this->isDetailed()) {
|
||||
$hostname .= '<br />' . $device->name();
|
||||
}
|
||||
|
||||
return $hostname;
|
||||
return (string) view('device.list.hostname', [
|
||||
'device' => $device,
|
||||
'detailed' => $this->isDetailed(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
namespace App\Http\Controllers\Widgets;
|
||||
|
||||
use App\Models\Alert;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AlertsController extends WidgetController
|
||||
|
||||
@@ -100,6 +100,14 @@ class Port extends DeviceRelatedModel
|
||||
return Rewrite::shortenIfName(Rewrite::normalizeIfName($this->ifName ?: $this->ifDescr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of this port either the parsed description or ifAlias
|
||||
*/
|
||||
public function getDescription(): string
|
||||
{
|
||||
return (string) ($this->port_descr_descr ?: $this->ifAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can access this port.
|
||||
*
|
||||
|
||||
@@ -63,17 +63,9 @@ class AppServiceProvider extends ServiceProvider
|
||||
return auth()->check() && auth()->user()->isAdmin();
|
||||
});
|
||||
|
||||
Blade::directive('deviceLink', function ($arguments) {
|
||||
return "<?php echo \LibreNMS\Util\Url::deviceLink($arguments); ?>";
|
||||
});
|
||||
|
||||
Blade::directive('deviceUrl', function ($arguments) {
|
||||
return "<?php echo \LibreNMS\Util\Url::deviceUrl($arguments); ?>";
|
||||
});
|
||||
|
||||
Blade::directive('portLink', function ($arguments) {
|
||||
return "<?php echo \LibreNMS\Util\Url::portLink($arguments); ?>";
|
||||
});
|
||||
}
|
||||
|
||||
private function configureMorphAliases()
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use App\Facades\DeviceCache;
|
||||
use App\Models\Device;
|
||||
use Illuminate\View\Component;
|
||||
use LibreNMS\Util\Graph;
|
||||
|
||||
class DeviceLink extends Component
|
||||
{
|
||||
/**
|
||||
* @var \App\Models\Device
|
||||
*/
|
||||
public $device;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public $tab;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public $section;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $status;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param int|\App\Models\Device $device
|
||||
*/
|
||||
public function __construct($device, ?string $tab = null, ?string $section = null)
|
||||
{
|
||||
$this->device = $device instanceof Device ? $device : DeviceCache::get($device);
|
||||
$this->tab = $tab;
|
||||
$this->section = $section;
|
||||
$this->status = $this->status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Closure|string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
if (! $this->device->canAccess(auth()->user())) {
|
||||
return view('components.device-link-no-access');
|
||||
}
|
||||
|
||||
return view('components.device-link', [
|
||||
'graphs' => Graph::getOverviewGraphsForDevice($this->device),
|
||||
]);
|
||||
}
|
||||
|
||||
public function status(): string
|
||||
{
|
||||
if ($this->device->disabled) {
|
||||
return 'disabled';
|
||||
}
|
||||
|
||||
return $this->device->status ? 'up' : ($this->device->ignore ? 'disabled' : 'down');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use App\Models\Device;
|
||||
use App\Models\Port;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class Graph extends Component
|
||||
{
|
||||
const DEFAULT_WIDE_WIDTH = 340;
|
||||
const DEFAULT_WIDE_HEIGHT = 100;
|
||||
const DEFAULT_NORMAL_WIDTH = 300;
|
||||
const DEFAULT_NORMAL_HEIGHT = 150;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $vars;
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
public $width;
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
public $height;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $type;
|
||||
/**
|
||||
* @var int|string|null
|
||||
*/
|
||||
public $from;
|
||||
/**
|
||||
* @var int|string|null
|
||||
*/
|
||||
public $to;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $legend;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $absolute_size;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $vars
|
||||
* @param int|string $from
|
||||
* @param int|string $to
|
||||
* @param string $legend
|
||||
* @param string $aspect
|
||||
* @param int|null $width
|
||||
* @param int|null $height
|
||||
* @param int $absolute_size
|
||||
* @param \App\Models\Device|int|null $device
|
||||
* @param \App\Models\Port|int|null $port
|
||||
*/
|
||||
public function __construct(string $type = '', array $vars = [], $from = '-1d', $to = null, string $legend = 'no', string $aspect = 'normal', ?int $width = null, ?int $height = null, int $absolute_size = 0, $device = null, $port = null)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->vars = $vars;
|
||||
$this->from = $from;
|
||||
$this->to = $to;
|
||||
$this->legend = $legend;
|
||||
$this->absolute_size = $absolute_size;
|
||||
$this->width = $width ?: ($aspect == 'wide' ? self::DEFAULT_WIDE_WIDTH : self::DEFAULT_NORMAL_WIDTH);
|
||||
$this->height = $height ?: ($aspect == 'wide' ? self::DEFAULT_WIDE_HEIGHT : self::DEFAULT_NORMAL_HEIGHT);
|
||||
|
||||
// handle device and port ids/models for convenience could be set in $vars
|
||||
if ($device instanceof Device) {
|
||||
$this->vars['device'] = $device->device_id;
|
||||
} elseif (is_numeric($device)) {
|
||||
$this->vars['device'] = $device;
|
||||
} elseif ($port instanceof Port) {
|
||||
$this->vars['id'] = $port->port_id;
|
||||
} elseif (is_numeric($port)) {
|
||||
$this->vars['id'] = $port;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Closure|string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return view('components.graph', [
|
||||
'link' => url('graph.php') . '?' . http_build_query($this->vars + [
|
||||
'type' => $this->type,
|
||||
'legend' => $this->legend,
|
||||
'absolute_size' => $this->absolute_size,
|
||||
'width' => $this->width,
|
||||
'height' => $this->height,
|
||||
'from' => $this->from,
|
||||
'to' => $this->to,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class GraphRow extends Component
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $type;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $loading;
|
||||
/**
|
||||
* @var null
|
||||
*/
|
||||
public $device;
|
||||
/**
|
||||
* @var null
|
||||
*/
|
||||
public $port;
|
||||
/**
|
||||
* @var array|string[][]
|
||||
*/
|
||||
public $graphs;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public $title;
|
||||
/**
|
||||
* @var float|int
|
||||
*/
|
||||
public $rowWidth;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $responsive;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $aspect;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string|null $title
|
||||
* @param string $loading
|
||||
* @param string $aspect
|
||||
* @param int $columns
|
||||
* @param array $graphs
|
||||
* @param \App\Models\Device|int|null $device
|
||||
* @param \App\Models\Port|int|null $port
|
||||
*/
|
||||
public function __construct(string $type = '', string $title = null, string $loading = 'eager', string $aspect = 'normal', int $columns = 2, array $graphs = [['from' => '-1d'], ['from' => '-7d'], ['from' => '-30d'], ['from' => '-1y']], $device = null, $port = null)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->aspect = $aspect;
|
||||
$this->loading = $loading;
|
||||
$this->device = $device;
|
||||
$this->port = $port;
|
||||
$this->graphs = $graphs;
|
||||
$this->title = $title;
|
||||
$this->responsive = $columns == 'responsive';
|
||||
$this->rowWidth = $this->calculateRowWidth($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Closure|string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return view('components.graph-row');
|
||||
}
|
||||
|
||||
private function calculateRowWidth(int $columns): ?int
|
||||
{
|
||||
if ($this->responsive) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$max = max(array_column($this->graphs, 'width') + [0]);
|
||||
|
||||
if (! $max) {
|
||||
$max = $this->aspect == 'wide' ? Graph::DEFAULT_WIDE_WIDTH : Graph::DEFAULT_NORMAL_WIDTH;
|
||||
}
|
||||
|
||||
// width * columns, unless there is less graphs than columns
|
||||
return $max * min($columns, count($this->graphs));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class Popup extends Component
|
||||
{
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Closure|string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return view('components.popup');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use App\Models\Port;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\View\Component;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
use LibreNMS\Util\Url;
|
||||
|
||||
class PortLink extends Component
|
||||
{
|
||||
/**
|
||||
* @var \App\Models\Port
|
||||
*/
|
||||
public $port;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $link;
|
||||
/**
|
||||
* @var array|string|string[]
|
||||
*/
|
||||
public $label;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $description;
|
||||
/**
|
||||
* @var array|array[]
|
||||
*/
|
||||
public $graphs;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $status;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Port $port, ?array $graphs = null)
|
||||
{
|
||||
$this->port = $port;
|
||||
$this->link = Url::portUrl($port);
|
||||
$this->label = Rewrite::normalizeIfName($port->getLabel());
|
||||
$this->description = $port->getDescription();
|
||||
$this->status = $this->status();
|
||||
|
||||
$this->graphs = $graphs === null ? [
|
||||
['type' => 'port_bits', 'title' => trans('Traffic'), 'vars' => [['from' => '-1d'], ['from' => '-7d'], ['from' => '-30d'], ['from' => '-1y']]],
|
||||
] : Arr::wrap($graphs);
|
||||
|
||||
if ($this->description == $this->label) {
|
||||
$this->description = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Closure|string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return view('components.port-link');
|
||||
}
|
||||
|
||||
private function status(): string
|
||||
{
|
||||
if ($this->port->ifAdminStatus == 'down') {
|
||||
return 'disabled';
|
||||
}
|
||||
|
||||
return $this->port->ifAdminStatus == 'up' && $this->port->ifOperStatus != 'up'
|
||||
? 'down'
|
||||
: 'up';
|
||||
}
|
||||
|
||||
public function fillDefaultVars(array $vars): array
|
||||
{
|
||||
return array_map(function ($graph_vars) {
|
||||
return array_merge([
|
||||
'from' => '-1d',
|
||||
'type' => 'port_bits',
|
||||
'legend' => 'yes',
|
||||
'text' => '',
|
||||
], Arr::wrap($graph_vars));
|
||||
}, $vars);
|
||||
}
|
||||
}
|
||||
+3
-3
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+5
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
(()=>{"use strict";var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var l=t[e]={id:e,loaded:!1,exports:{}};return r[e].call(l.exports,l,l.exports,o),l.loaded=!0,l.exports}o.m=r,e=[],o.O=(r,t,n,l)=>{if(!t){var i=1/0;for(d=0;d<e.length;d++){for(var[t,n,l]=e[d],a=!0,u=0;u<t.length;u++)(!1&l||i>=l)&&Object.keys(o.O).every((e=>o.O[e](t[u])))?t.splice(u--,1):(a=!1,l<i&&(i=l));a&&(e.splice(d--,1),r=n())}return r}l=l||0;for(var d=e.length;d>0&&e[d-1][2]>l;d--)e[d]=e[d-1];e[d]=[t,n,l]},o.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return o.d(r,{a:r}),r},o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={929:0,170:0};o.O.j=r=>0===e[r];var r=(r,t)=>{var n,l,[i,a,u]=t,d=0;for(n in a)o.o(a,n)&&(o.m[n]=a[n]);if(u)var f=u(o);for(r&&r(t);d<i.length;d++)l=i[d],o.o(e,l)&&e[l]&&e[l][0](),e[i[d]]=0;return o.O(f)},t=self.webpackChunk=self.webpackChunk||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})()})();
|
||||
(()=>{"use strict";var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var i=t[e]={id:e,loaded:!1,exports:{}};return r[e].call(i.exports,i,i.exports,o),i.loaded=!0,i.exports}o.m=r,e=[],o.O=(r,t,n,i)=>{if(!t){var l=1/0;for(f=0;f<e.length;f++){for(var[t,n,i]=e[f],a=!0,u=0;u<t.length;u++)(!1&i||l>=i)&&Object.keys(o.O).every((e=>o.O[e](t[u])))?t.splice(u--,1):(a=!1,i<l&&(l=i));if(a){e.splice(f--,1);var d=n();void 0!==d&&(r=d)}}return r}i=i||0;for(var f=e.length;f>0&&e[f-1][2]>i;f--)e[f]=e[f-1];e[f]=[t,n,i]},o.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return o.d(r,{a:r}),r},o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={929:0,213:0,170:0};o.O.j=r=>0===e[r];var r=(r,t)=>{var n,i,[l,a,u]=t,d=0;if(l.some((r=>0!==e[r]))){for(n in a)o.o(a,n)&&(o.m[n]=a[n]);if(u)var f=u(o)}for(r&&r(t);d<l.length;d++)i=l[d],o.o(e,i)&&e[i]&&e[i][0](),e[l[d]]=0;return o.O(f)},t=self.webpackChunk=self.webpackChunk||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})()})();
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*!
|
||||
* vue-i18n v8.24.4
|
||||
* vue-i18n v8.25.0
|
||||
* (c) 2021 kazuya kawaguchi
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
+11
-10
@@ -1,14 +1,15 @@
|
||||
{
|
||||
"/js/app.js": "/js/app.js?id=a04efc91bb73e91248e7",
|
||||
"/js/manifest.js": "/js/manifest.js?id=1514baaea419f38abb7d",
|
||||
"/css/app.css": "/css/app.css?id=996b9e3da0c3ab98067e",
|
||||
"/js/vendor.js": "/js/vendor.js?id=ccca9695062f1f68aaa8",
|
||||
"/js/lang/de.js": "/js/lang/de.js?id=8959e785f5790d6b6836",
|
||||
"/js/lang/en.js": "/js/lang/en.js?id=19867ecb0d7e260236b0",
|
||||
"/js/lang/fr.js": "/js/lang/fr.js?id=707149152bde5b5e2b8d",
|
||||
"/js/lang/it.js": "/js/lang/it.js?id=4e3b200da489000822dd",
|
||||
"/js/app.js": "/js/app.js?id=d5975c3162d3b388db35",
|
||||
"/js/manifest.js": "/js/manifest.js?id=8d61162bb0caf92f60ff",
|
||||
"/css/vendor.css": "/css/vendor.css?id=8d7b2ecb46047fe813e4",
|
||||
"/css/app.css": "/css/app.css?id=b21e1df1f5102369eabc",
|
||||
"/js/vendor.js": "/js/vendor.js?id=294cef17a3cf43045d61",
|
||||
"/js/lang/de.js": "/js/lang/de.js?id=cc551d5a4aa98a6d7453",
|
||||
"/js/lang/en.js": "/js/lang/en.js?id=fea09c4ff709961f8275",
|
||||
"/js/lang/fr.js": "/js/lang/fr.js?id=aeac40fc3bd66cdfa69e",
|
||||
"/js/lang/it.js": "/js/lang/it.js?id=ae198ed0b94351e4d950",
|
||||
"/js/lang/ru.js": "/js/lang/ru.js?id=f6b7c078755312a0907c",
|
||||
"/js/lang/uk.js": "/js/lang/uk.js?id=c19a5dcee4724579cb41",
|
||||
"/js/lang/zh-CN.js": "/js/lang/zh-CN.js?id=acab91683e556299b62b",
|
||||
"/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=4d48f47a17010848f963"
|
||||
"/js/lang/zh-CN.js": "/js/lang/zh-CN.js?id=427acc5a5aed577c98e4",
|
||||
"/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=f648dcc6f44e78951150"
|
||||
}
|
||||
|
||||
Generated
+4230
-13299
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -12,6 +12,7 @@
|
||||
"production": "mix --production"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.3.3",
|
||||
"axios": "^0.21.1",
|
||||
"bootstrap": "^4.5.3",
|
||||
"cross-env": "^5.2.1",
|
||||
@@ -19,10 +20,11 @@
|
||||
"laravel-mix": "^6.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"popper.js": "^1.16.1",
|
||||
"postcss": "^8.2.10",
|
||||
"postcss": "^8.3.6",
|
||||
"resolve-url-loader": "^3.1.2",
|
||||
"sass": "^1.29.0",
|
||||
"sass-loader": "^10.1.0",
|
||||
"tailwindcss": "^2.2.9",
|
||||
"vue": "^2.6.12",
|
||||
"vue-loader": "^15.9.6",
|
||||
"vue-template-compiler": "^2.6.12"
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@@ -0,0 +1,3 @@
|
||||
{{ $slot->isNotEmpty() ? $slot : $device->displayName() }}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<x-popup>
|
||||
<a class="tw-font-bold @if($status=='disabled') tw-text-gray-400 visited:tw-text-gray-400 @elseif($status=='down') tw-text-red-600 visited:tw-text-red-600 @else tw-text-blue-900 visited:tw-text-blue-900 @endif" href="{{ route('device', ['device' => $device->device_id, 'tab' => $tab, 'section' => $section]) }}">
|
||||
{{ $slot->isNotEmpty() ? $slot : $device->displayName() }}
|
||||
</a>
|
||||
<x-slot name="title">
|
||||
<span class="tw-text-nowrap tw-pr-1">
|
||||
<span class="tw-text-xl tw-font-bold">{{ $device->displayName() }}</span>
|
||||
{{ $device->hardware }}
|
||||
</span>
|
||||
<span class="tw-text-nowrap tw-pl-2 tw-pr-1">
|
||||
@if($device->os){{ \LibreNMS\Config::getOsSetting($device->os, 'text') }}@endif
|
||||
{{ $device->version }}
|
||||
</span>
|
||||
<span class="tw-text-nowrap tw-pl-2">
|
||||
@if($device->feature)({{ $device->features }})@endif
|
||||
@if($device->location)[{{ $device->location }}]@endif
|
||||
</span>
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
@foreach($graphs as $graph)
|
||||
@isset($graph['text'], $graph['graph'])
|
||||
<x-graph-row loading="lazy" :device="$device" :type="$graph['graph']" :title="$graph['text']" :graphs="[['from' => '-1d'], ['from' => '-7d']]"></x-graph-row>
|
||||
@endisset
|
||||
@endforeach
|
||||
</x-slot>
|
||||
</x-popup>
|
||||
@@ -0,0 +1,10 @@
|
||||
@isset($title)
|
||||
<div class="tw-border-b tw-font-semibold">
|
||||
{{ $title }}
|
||||
</div>
|
||||
@endisset
|
||||
<div class="tw-flex tw-flex-wrap" @if(! $responsive) style="width: {{ $rowWidth }}px;" @endif {{ $attributes }}>
|
||||
@foreach($graphs as $graph)
|
||||
<x-graph :type="$type" :loading="$loading" :aspect="$aspect" :port="$port" :device="$device" :vars="$graph" {{ $attributes->class(['xl:tw-w-1/4 lg:tw-w-1/2 sm:tw-w-full' => $responsive]) }}></x-graph>
|
||||
@endforeach
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
<img width="{{ $width }}" height="{{ $height }}" src="{{ $link }}" alt="{{ $type }}" {{ $attributes->merge(['class' => 'graph-image']) }}>
|
||||
@@ -0,0 +1,54 @@
|
||||
<div {{ $attributes->merge(['class' => 'tw-inline-block']) }} x-data="{
|
||||
popupShow: false,
|
||||
showTimeout: null,
|
||||
hideTimeout: null,
|
||||
ignoreNextShownEvent: false,
|
||||
delay: 300,
|
||||
show(timeout) {
|
||||
clearTimeout(this.hideTimeout);
|
||||
this.showTimeout = setTimeout(() => {
|
||||
this.popupShow = true;
|
||||
Popper.createPopper(this.$refs.targetRef, this.$refs.popupRef, {
|
||||
padding: 8
|
||||
});
|
||||
|
||||
// close other popups, except this one
|
||||
this.ignoreNextShownEvent = true;
|
||||
this.$dispatch('librenms-popup-shown', this.$el);
|
||||
}, timeout);
|
||||
},
|
||||
hide(timeout) {
|
||||
if (this.ignoreNextShownEvent) {
|
||||
this.ignoreNextShownEvent = false;
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(this.showTimeout);
|
||||
this.hideTimeout = setTimeout(() => this.popupShow = false, timeout)
|
||||
}
|
||||
}"
|
||||
x-on:click.away="hide(0)"
|
||||
x-on:librenms-popup-shown.window="() => hide(0)"
|
||||
>
|
||||
<div class="tw-inline-block" x-ref="targetRef" x-on:mouseenter='show(100)' x-on:mouseleave="hide(delay)">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
<div x-ref="popupRef"
|
||||
x-on:mouseenter="clearTimeout(hideTimeout)"
|
||||
x-on:mouseleave="hide(delay)"
|
||||
x-bind:class="{'tw-hidden': !popupShow, 'tw-block': popupShow}"
|
||||
class="tw-hidden tw-bg-white dark:tw-bg-gray-800 dark:tw-text-white tw-border-2 tw-border-gray-200 dark:tw-border-gray-600 tw-ml-3 tw-z-50 tw-font-normal tw-leading-normal tw-text-sm tw-text-left tw-no-underline tw-rounded-lg"
|
||||
style="max-width:95vw;"
|
||||
>
|
||||
@isset($title)
|
||||
<div class="tw-opacity-90 tw-p-3 tw-mb-0 tw-border-b-2 tw-border-solid tw-border-gray-200 dark:tw-border-gray-600 tw-rounded-t-lg">
|
||||
{{ $title }}
|
||||
</div>
|
||||
@endisset
|
||||
@isset($body)
|
||||
<div class="tw-p-3">
|
||||
{{ $body }}
|
||||
</div>
|
||||
@endisset
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,18 @@
|
||||
<x-popup>
|
||||
<a class="@if($status=='disabled') tw-text-gray-400 visited:tw-text-gray-400 @elseif($status=='down') tw-text-red-600 visited:tw-text-red-600 @else tw-text-blue-900 visited:tw-text-blue-900 @endif"
|
||||
href="{{ $link }}"
|
||||
{{ $attributes }}>
|
||||
{{ $slot->isNotEmpty() ? $slot : $label }}
|
||||
</a>
|
||||
<x-slot name="title">
|
||||
<div class="tw-text-xl tw-font-bold">{{ $port->device->displayName() }} - {{ $label }}</div>
|
||||
<div>{{ $description }}</div>
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<div>
|
||||
@foreach($graphs as $graph)
|
||||
<x-graph-row loading="lazy" :port="$port" :type="$graph['type'] ?? 'port_bits'" :title="$graph['title'] ?? null" :graphs="$fillDefaultVars($graph['vars'] ?? [])"></x-graph-row>
|
||||
@endforeach
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-popup>
|
||||
@@ -73,7 +73,7 @@
|
||||
@foreach($ungrouped_devices as $device)
|
||||
<tr id="row_{{ $device->device_id }}">
|
||||
<td><img alt="{{ $device->os }}" src="{{ asset($device->icon) }}" width="32px" height="32px" title="{{ $device->os }}"></td>
|
||||
<td>@deviceLink($device)<br />{{ $device->sysName }}</td>
|
||||
<td><x-device-link :device="$device" /><br />{{ $device->sysName }}</td>
|
||||
<td>{{ $device->hardware }}</td>
|
||||
<td>{{ $device->os }} {{ $device->version }} @if($device->features) ({{ $device->features }}) @endif </td>
|
||||
</tr>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
@if($device->isUnderMaintenance())
|
||||
<span title="@lang('Scheduled Maintenance')" class="fa fa-wrench fa-fw fa-lg"></span>
|
||||
@endif
|
||||
<span style="font-size: 20px;">@deviceLink($device)</span><br/>
|
||||
<span style="font-size: 20px;"><x-device-link :device="$device" /></span><br/>
|
||||
<a href="{{ url('/devices/location=' . urlencode($device->location)) }}">{{ $device->location }}</a>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<x-device-link :device="$device"></x-device-link>
|
||||
@if($detailed)
|
||||
<br />
|
||||
{{ $device->name() }}
|
||||
@endif
|
||||
@@ -20,37 +20,13 @@
|
||||
<div class="tab-content">
|
||||
@foreach($data['smokeping_tabs'] as $direction)
|
||||
<div class="tab-pane fade in @if($loop->first) active @endif" id="{{ $direction }}">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h3>Average</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@foreach(\LibreNMS\Util\Html::graphRow(['type' => "device_smokeping_{$direction}_all_avg", 'device' => $device->device_id]) as $graph)
|
||||
<div class='col-md-3'>{!! $graph !!}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h3>Aggregate</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@foreach(\LibreNMS\Util\Html::graphRow(['type' => "device_smokeping_{$direction}_all", 'device' => $device->device_id, 'legend' => 'no']) as $graph)
|
||||
<div class='col-md-3'>{!! $graph !!}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<x-graph-row :type="'device_smokeping_' . $direction . '_all_avg'" title="Average" :device="$device" columns="responsive"></x-graph-row>
|
||||
</div>
|
||||
<div class="row"><x-graph-row :type="'device_smokeping_' . $direction . '_all'" title="Aggregate" :device="$device" columns="responsive"></x-graph-row>
|
||||
@foreach($data['smokeping']->otherGraphs($direction) as $info)
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h3>@deviceLink($info['device'])</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@foreach(\LibreNMS\Util\Html::graphRow($info['graph']) as $graph)
|
||||
<div class='col-md-3'>{!! $graph !!}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<x-graph-row :type="$info['graph']" :device="$info['device']" columns="responsive">
|
||||
<x-slot name="title"><x-device-link device="$info['device']" /></x-slot>
|
||||
</x-graph-row>
|
||||
@endforeach
|
||||
</div>
|
||||
@endforeach
|
||||
@@ -221,7 +197,7 @@
|
||||
.panel.with-nav-tabs .nav-justified {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
|
||||
.bootstrap-datetimepicker-widget.dropdown-menu {
|
||||
inset: auto!important;
|
||||
}
|
||||
|
||||
@@ -18,14 +18,13 @@
|
||||
<td>
|
||||
@foreach($vlans as $port)
|
||||
@if(!$vars)
|
||||
@if($port->port)
|
||||
@portLink($port->port, $port->port->getShortLabel())
|
||||
@if($port->untagged)
|
||||
(U)@endif
|
||||
@if(!$loop->last),
|
||||
@endif
|
||||
@endif
|
||||
|
||||
<span class="tw-inline-flex">
|
||||
@if($port->port)
|
||||
<x-port-link :port="$port->port">{{ $port->port->getShortLabel() }}</x-port-link>
|
||||
@if($port->untagged)<span> (U)</span>@endif
|
||||
@if(!$loop->last)<span>,</span>@endif
|
||||
@endif
|
||||
</span>
|
||||
@else
|
||||
<div style="display: block; padding: 2px; margin: 2px; min-width: 139px; max-width:139px; min-height:85px; max-height:85px; text-align: center; float: left; background-color: {{ \LibreNMS\Config::get('list_colour.odd_alt2') }}">
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<tr>
|
||||
<td>
|
||||
@if ($vm->parentDevice)
|
||||
@deviceLink($vm->parentDevice)
|
||||
<x-device-link :device="$vm->parentDevice" />
|
||||
@else
|
||||
{{ $vm->vmwVmDisplayName }}
|
||||
@endif
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>{{ $pagetitle }}</title>
|
||||
<base href="{{ LibreNMS\Config::get('base_url') }}" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<base href="{{ LibreNMS\Config::get('base_url') }}">
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
@if(!LibreNMS\Config::get('favicon', false))
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('images/apple-touch-icon.png') }}">
|
||||
@@ -14,7 +14,7 @@
|
||||
<link rel="mask-icon" href="{{ asset('images/safari-pinned-tab.svg') }}" color="#5bbad5">
|
||||
<link rel="shortcut icon" href="{{ asset('images/favicon.ico') }}">
|
||||
@else
|
||||
<link rel="shortcut icon" href="{{ LibreNMS\Config::get('favicon') }}" />
|
||||
<link rel="shortcut icon" href="{{ LibreNMS\Config::get('favicon') }}">
|
||||
@endif
|
||||
|
||||
<link rel="manifest" href="{{ asset('images/manifest.json') }}" crossorigin="use-credentials">
|
||||
@@ -22,33 +22,36 @@
|
||||
<meta name="msapplication-config" content="{{ asset('images/browserconfig.xml') }}">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/bootstrap-datetimepicker.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/bootstrap-switch.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/toastr.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/jquery.bootgrid.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/tagmanager.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/mktree.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/vis.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/font-awesome.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/jquery.gridster.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/leaflet.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/MarkerCluster.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/MarkerCluster.Default.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/L.Control.Locate.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/leaflet.awesome-markers.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/select2.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/select2-bootstrap.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/query-builder.default.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset(LibreNMS\Config::get('stylesheet', 'css/styles.css')) }}?ver=20210421" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/' . LibreNMS\Config::get('applied_site_style', 'light') . '.css?ver=632417643') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/bootstrap-datetimepicker.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/bootstrap-switch.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/toastr.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/jquery.bootgrid.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/tagmanager.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/mktree.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/vis.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/font-awesome.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/jquery.gridster.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/leaflet.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/MarkerCluster.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/MarkerCluster.Default.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/L.Control.Locate.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/leaflet.awesome-markers.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/select2.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/select2-bootstrap.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/query-builder.default.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset(LibreNMS\Config::get('stylesheet', 'css/styles.css')) }}?ver=20210421" rel="stylesheet">
|
||||
<link href="{{ asset('css/' . LibreNMS\Config::get('applied_site_style', 'light') . '.css?ver=632417643') }}" rel="stylesheet">
|
||||
@foreach(LibreNMS\Config::get('webui.custom_css', []) as $custom_css)
|
||||
<link href="{{ $custom_css }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ $custom_css }}" rel="stylesheet">
|
||||
@endforeach
|
||||
@yield('css')
|
||||
@stack('styles')
|
||||
|
||||
<script src="{{ asset('js/polyfill.min.js') }}"></script>
|
||||
<script src="{{ asset('js/alpine.min.js') }}" defer></script>
|
||||
<script src="{{ asset('js/popper.min.js') }}"></script>
|
||||
<script src="{{ asset('js/jquery.min.js?ver=05072021') }}"></script>
|
||||
<script src="{{ asset('js/bootstrap.min.js?ver=05072021') }}"></script>
|
||||
<script src="{{ asset('js/bootstrap-hover-dropdown.min.js?ver=05072021') }}"></script>
|
||||
@@ -86,6 +89,14 @@
|
||||
<script type="text/javascript" src="{{ asset('js/overlib_mini.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ asset('js/toastr.min.js?ver=05072021') }}"></script>
|
||||
<script type="text/javascript" src="{{ asset('js/boot.js') }}"></script>
|
||||
<script>
|
||||
// Apply color scheme
|
||||
if ('{{ LibreNMS\Config::get('applied_site_style', 'light') }}' === 'dark' || window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.documentElement.classList.add('tw-dark')
|
||||
} else {
|
||||
document.documentElement.classList.remove('tw-dark')
|
||||
}
|
||||
</script>
|
||||
@yield('javascript')
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
@endsection
|
||||
|
||||
@push('styles')
|
||||
<link href="{{ asset(mix('/css/app.css')) }}" rel="stylesheet">
|
||||
<link href="{{ asset(mix('/css/vendor.css')) }}" rel="stylesheet">
|
||||
@endpush
|
||||
|
||||
@section('javascript')
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
@endsection
|
||||
|
||||
@push('styles')
|
||||
<link href="{{ asset(mix('/css/app.css')) }}" rel="stylesheet">
|
||||
<link href="{{ asset(mix('/css/vendor.css')) }}" rel="stylesheet">
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
<strong class="green">@lang('Global Viewing Access')</strong>
|
||||
@else
|
||||
@forelse($devices as $device)
|
||||
@deviceLink($device) <br />
|
||||
<x-device-link :device="$device" /><br />
|
||||
@empty
|
||||
<strong class="red">@lang('No access!')</strong>
|
||||
@endforelse
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
<tbody>
|
||||
@foreach($ports as $port)
|
||||
<tr>
|
||||
<td class="text-left">@deviceLink($port->device, $port->device->shortDisplayName())</td>
|
||||
<td class="text-left">@portLink($port, $port->getShortLabel())</td>
|
||||
<td class="text-left">@portLink($port, \LibreNMS\Util\Url::portErrorsThumbnail($port), 'port_errors')</td>
|
||||
<td class="text-left"><x-device-link :device="$port->device">{{$port->device->shortDisplayName() }}</x-device-link></td>
|
||||
<td class="text-left"><x-port-link :port="$port">{{ $port->getShortLabel() }}</x-port-link></td>
|
||||
<td class="text-left"><x-port-link :port="$port"><x-graph :port="$port" type="port_bits" width="150" height="21"></x-graph></x-port-link></td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
<tbody>
|
||||
@foreach($ports as $port)
|
||||
<tr>
|
||||
<td class="text-left">@deviceLink($port->device, $port->device->shortDisplayName())</td>
|
||||
<td class="text-left">@portLink($port, $port->getShortLabel())</td>
|
||||
<td class="text-left">@portLink($port, \LibreNMS\Util\Url::portThumbnail($port))</td>
|
||||
<td class="text-left"><x-device-link :device="$port->device">{{$port->device->shortDisplayName() }}</x-device-link></td>
|
||||
<td class="text-left"><x-port-link :port="$port">{{ $port->getShortLabel() }}</x-port-link></td>
|
||||
<td class="text-left"><x-port-link :port="$port"><x-graph :port="$port" type="port_bits" width="150" height="21"></x-graph></x-port-link></td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
module.exports = {
|
||||
prefix: 'tw-',
|
||||
purge: [
|
||||
'./storage/framework/views/*.php',
|
||||
'./resources/**/*.blade.php',
|
||||
'./resources/**/*.js',
|
||||
'./resources/**/*.vue',
|
||||
],
|
||||
darkMode: 'class',
|
||||
theme: {
|
||||
extend: {},
|
||||
screens: {
|
||||
'sm': '576px',
|
||||
'md': '768px',
|
||||
'lg': '992px',
|
||||
'xl': '1200px',
|
||||
}
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
+4
-1
@@ -14,6 +14,9 @@ const mix = require('laravel-mix');
|
||||
mix.setPublicPath('html/')
|
||||
.js('resources/js/app.js', 'js')
|
||||
.vue()
|
||||
.sass('resources/sass/app.scss', 'css')
|
||||
.sass('resources/sass/app.scss', 'css/vendor.css')
|
||||
.postCss('resources/css/app.css', 'css', [
|
||||
require('tailwindcss'),
|
||||
])
|
||||
.extract()
|
||||
.version('html/js/lang/*.js');
|
||||
|
||||
Reference in New Issue
Block a user