New asset dependency/inclusion management system.

This commit is contained in:
Buster "Silver Eagle" Neece 2017-09-24 06:29:19 -05:00
parent dd9905786b
commit f43143ec59
19 changed files with 615 additions and 249 deletions

210
app/bootstrap/assets.php Normal file
View file

@ -0,0 +1,210 @@
<?php
/**
* Static assets referenced in AzuraCast.
* Stored here to easily resolve dependencies on individual pages.
*/
return [
/*
* Core libraries
*/
[
'name' => 'jquery',
'order' => 0,
'group' => 'header',
'files' => [
'js' => [
'bower_components/jquery/dist/jquery.min.js',
],
],
],
[
'name' => 'vue',
'order' => 1,
'group' => 'header',
'files' => [
'js' => [
'bower_components/vue/dist/' . (APP_IN_PRODUCTION ? 'vue.min.js' : 'vue.js'),
],
],
],
/*
* Main per-layout dependencies
*/
[
'name' => 'minimal_header',
'order' => 2,
'group' => 'header',
'files' => [
'css' => [
'bower_components/animate.css/animate.min.css',
'bower_components/material-design-iconic-font/dist/css/material-design-iconic-font.min.css',
],
'js' => [
'bower_components/bootstrap/dist/js/bootstrap.min.js',
]
],
'require' => ['jquery'],
],
[
'name' => 'minimal_body',
'order' => 2,
'group' => 'body',
'files' => [
'js' => [
'bower_components/Waves/dist/waves.min.js',
'bower_components/remarkable-bootstrap-notify/dist/bootstrap-notify.min.js',
'js/app.min.js',
],
],
],
[
'name' => 'main_header',
'order' => 3,
'files' => [
'css' => [
'bower_components/bootstrap-sweetalert/lib/sweet-alert.css',
'bower_components/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.min.css',
],
],
'require' => ['minimal_header'],
],
[
'name' => 'main_body',
'order' => 3,
'files' => [
'js' => [
'bower_components/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js',
'bower_components/bootstrap-sweetalert/lib/sweet-alert.min.js',
'bower_components/autosize/dist/autosize.js',
],
],
'require' => ['minimal_body'],
],
/*
* Themes
*/
[
'name' => 'theme_dark',
'order' => 50,
'group' => 'body',
'files' => [
'css' => [
'css/dark.css'
],
]
],
[
'name' => 'theme_light',
'order' => 50,
'group' => 'body',
'files' => [
'css' => [
'css/light.css'
],
]
],
/*
* Individual libraries
*/
[
'name' => 'bootgrid',
'order' => 8,
'group' => 'body',
'files' => [
'css' => [
'bower_components/jquery.bootgrid/dist/jquery.bootgrid.min.css',
],
'js' => [
'bower_components/jquery.bootgrid/dist/jquery.bootgrid.min.js',
],
],
'require' => ['jquery'],
],
[
'name' => 'radio',
'order' => 20,
'group' => 'body',
'files' => [
'js' => [
'bower_components/store-js/store.min.js',
'js/radio.js',
'js/nchan.js',
],
],
'require' => ['jquery'],
],
[
'name' => 'highcharts',
'order' => 20,
'group' => 'body',
'files' => [
'js' => [
'//code.highcharts.com/highcharts.js',
'//code.highcharts.com/highcharts-more.js',
'//code.highcharts.com/modules/exporting.js',
],
]
],
[
'name' => 'highcharts_theme_dark',
'order' => 21,
'group' => 'body',
'files' => [
'js' => [
'js/highcharts/dark-blue.js',
]
]
],
[
'name' => 'highcharts_theme_light',
// empty
],
[
'name' => 'forms',
'order' => 9,
'group' => 'body',
'files' => [
'js' => [
'bower_components/chosen/chosen.jquery.min.js',
'bower_components/zxcvbn/dist/zxcvbn.js',
],
'css' => [
'bower_components/chosen/chosen.min.css',
]
],
],
[
'name' => 'daterangepicker',
'order' => 9,
'group' => 'body',
'files' => [
'js' => [
'//cdn.jsdelivr.net/momentjs/latest/moment.min.js',
'//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js',
],
'css' => [
'//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css',
],
]
],
[
'name' => 'codemirror_css',
'order' => 10,
'group' => 'body',
'files' => [
'js' => [
'bower_components/codemirror/lib/codemirror.js',
'bower_components/codemirror/mode/css/css.js',
],
'css' => [
'bower_components/codemirror/lib/codemirror.css',
'bower_components/codemirror/theme/material.css',
],
],
]
];

View file

@ -306,32 +306,15 @@ return function (\Slim\Container $di, $settings) {
$di['assets'] = function ($di) {
return new class($di['url'])
{
/** @var \App\Url */
protected $url;
$libraries = require('assets.php');
/** @var array */
protected $assets;
$versioned_files = [];
$assets_file = APP_INCLUDE_STATIC . '/assets.json';
if (file_exists($assets_file)) {
$versioned_files = json_decode(file_get_contents($assets_file), true);
}
public function __construct(\App\Url $url)
{
$this->url = $url;
$assets = [];
$assets_file = APP_INCLUDE_STATIC . '/assets.json';
if (file_exists($assets_file)) {
$assets = json_decode(file_get_contents($assets_file), true);
}
$this->assets = $assets;
}
public function getPath($asset)
{
return $this->url->content($this->assets[$asset] ?? $asset);
}
};
return new \AzuraCast\Assets($libraries, $versioned_files, $di['url']);
};

View file

@ -1,31 +1,22 @@
<?php $this->layout('main', ['title' => _('Custom Branding')]); ?>
<?=$this->fetch('partials/form') ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/codemirror/lib/codemirror.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/codemirror/mode/css/css.js') ?>"></script>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('codemirror_css');
?>
<script type="text/javascript">
$(function() {
$(function() {
$('textarea.css-editor').each(function() {
CodeMirror.fromTextArea($(this)[0], {
lineNumbers: true,
theme: 'default material'
$('textarea.css-editor').each(function() {
CodeMirror.fromTextArea($(this)[0], {
lineNumbers: true,
theme: '<?=(($customization->getTheme() === 'light') ? 'default' : 'material') ?>'
});
});
});
});
});
</script>
<?php $this->stop('custom_js') ?>
<?php $this->start('custom_css') ?>
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/codemirror/lib/codemirror.css') ?>">
<?php if ($customization->getTheme() !== 'light'): ?>
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/codemirror/theme/material.css') ?>">
<?php endif; ?>
<?php $this->stop('custom_css') ?>
<?=$this->fetch('partials/form') ?>

View file

@ -1,18 +1,12 @@
<?php $this->layout('main', ['title' => _('Dashboard'), 'manual' => true]); ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="//code.highcharts.com/highcharts.js"></script>
<script type="text/javascript" src="//code.highcharts.com/highcharts-more.js"></script>
<script type="text/javascript" src="//code.highcharts.com/modules/exporting.js"></script>
<?php if ($customization->getTheme() == 'dark'): ?>
<script type="text/javascript" src="<?=$url->content('js/highcharts/dark-blue.js') ?>"></script>
<?php endif; ?>
<script type="text/javascript" src="<?=$url->content('bower_components/store-js/store.min.js') ?>"></script>
<script type="text/javascript" src="<?=$assets->getPath('js/radio.js') ?>"></script>
<script type="text/javascript" src="<?=$assets->getPath('js/nchan.js') ?>"></script>
<?php $this->stop('custom_js') ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('radio')
->load('highcharts')
->load('highcharts_theme_'.$customization->getTheme());
?>
<div class="block-header">
<h2><?=_('Dashboard') ?></h2>

View file

@ -1,12 +1,13 @@
<?php /** @var \Entity\Station $station */ ?>
<?php $this->layout('embed', ['title' => $this->e($station->getName())]) ?>
<?php $this->layout('minimal', ['page_class' => 'embed', 'title' => $this->e($station->getName())]) ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/store-js/store.min.js') ?>"></script>
<script type="text/javascript" src="<?=$assets->getPath('js/radio.js') ?>"></script>
<script type="text/javascript" src="<?=$assets->getPath('js/nchan.js') ?>"></script>
<?php $this->stop('custom_js') ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('vue')
->load('radio');
?>
<ul class="actions pull-right">
<?=$this->fetch('partials/radio_controls') ?>

View file

@ -1,14 +1,11 @@
<?php /** @var \Entity\Station $station */ ?>
<?php $this->layout('embed', ['title' => $this->e($station->getName())]) ?>
<?php $this->layout('minimal', ['page_class' => 'embed', 'title' => $this->e($station->getName())]) ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/jquery.bootgrid/dist/jquery.bootgrid.min.js') ?>"></script>
<?php $this->stop('custom_js') ?>
<?php $this->start('custom_css') ?>
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/jquery.bootgrid/dist/jquery.bootgrid.min.css') ?>">
<?php $this->stop('custom_css') ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets->load('bootgrid');
?>
<table class="data-table table table-striped" id="requests-table">
<thead>

View file

@ -2,17 +2,13 @@
<?php $this->layout('minimal', ['title' => $this->e($station->getName()), 'page_class' => 'public-page-content']) ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/jquery.bootgrid/dist/jquery.bootgrid.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/store-js/store.min.js') ?>"></script>
<script type="text/javascript" src="<?=$assets->getPath('js/radio.js') ?>"></script>
<script type="text/javascript" src="<?=$assets->getPath('js/nchan.js') ?>"></script>
<?php $this->stop('custom_js') ?>
<?php $this->start('custom_css') ?>
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/jquery.bootgrid/dist/jquery.bootgrid.min.css') ?>">
<?php $this->stop('custom_css') ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('vue')
->load('radio')
->load('bootgrid');
?>
<div class="public-page">
<div class="public-block">

View file

@ -1,11 +1,13 @@
<?php $this->layout('main', ['title' => _('Media Manager'), 'manual' => true, 'page_class' => 'page-file-manager']) ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/store-js/store.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('js/radio.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/flow.js/dist/flow.min.js') ?>"></script>
<?php $this->stop('custom_js') ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('vue')
->load('radio')
->load('bootgrid')
->addJs('bower_components/flow.js/dist/flow.min.js', 'header');
?>
<div class="row">
<div class="col-sm-12">

View file

@ -1,14 +1,11 @@
<?php $this->layout('main', ['title' => _('Station Center'), 'manual' => true]) ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="//code.highcharts.com/highcharts.js"></script>
<script type="text/javascript" src="//code.highcharts.com/highcharts-more.js"></script>
<script type="text/javascript" src="//code.highcharts.com/modules/exporting.js"></script>
<?php if ($customization->getTheme() == 'dark'): ?>
<script type="text/javascript" src="<?=$url->content('js/highcharts/dark-blue.js') ?>"></script>
<?php endif; ?>
<?php $this->stop('custom_js') ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('highcharts')
->load('highcharts_theme_'.$customization->getTheme());
?>
<script type="text/javascript">
$(function () {

View file

@ -4,11 +4,12 @@
<?php $this->layout('main', ['title' => _('Station Profile'), 'manual' => true]) ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/store-js/store.min.js') ?>"></script>
<script type="text/javascript" src="<?=$assets->getPath('js/radio.js') ?>"></script>
<script type="text/javascript" src="<?=$assets->getPath('js/nchan.js') ?>"></script>
<?php $this->stop('custom_js') ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('vue')
->load('radio');
?>
<div class="row">
<div class="col-sm-6">

View file

@ -1,13 +1,11 @@
<?php $this->layout('main', ['title' => _('Listeners'), 'manual' => true]) ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="//cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js"></script>
<?php $this->end() ?>
<?php $this->start('custom_css') ?>
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css" />
<?php $this->end() ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('vue')
->load('daterangepicker');
?>
<div class="row">
<div class="col-sm-12">

View file

@ -1,5 +1,11 @@
<?php $this->layout('main', ['title' => _('Song Listener Impact'), 'manual' => true]) ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('bootgrid');
?>
<div class="card">
<div class="card-header ch-alt">
<h2><?=_('Song Listener Impact') ?></h2>

View file

@ -1,5 +1,11 @@
<?php $this->layout('main', ['title' => 'Recent Playback Timeline', 'manual' => true]) ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('bootgrid');
?>
<div class="card">
<div class="card-header ch-alt">
<h2><?=_('Station Playback Timeline') ?></h2>

View file

@ -1,5 +1,11 @@
<?php $this->layout('main', ['title' => _('Song Requests'), 'manual' => true]) ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets
->load('bootgrid');
?>
<div class="card">
<div class="card-header ch-alt">
<h2><?=_('Song Requests') ?></h2>

View file

@ -0,0 +1,288 @@
<?php
/**
* Asset management class for AzuraCast.
* Inspired by Asseter by Adam Banaszkiewicz: https://github.com/requtize
*
* @link https://github.com/requtize/assetter
*/
namespace AzuraCast;
class Assets
{
/** @var array Known libraries loaded in initialization. */
protected $libraries = [];
/** @var array An optional array lookup for versioned files. */
protected $versioned_files = [];
/** @var array Loaded libraries. */
protected $loaded = [];
/** @var string Default library group, if not specified. */
protected $default_group = 'body';
/** @var \App\Url URL Resolver object */
protected $url;
/** @var bool Whether the current loaded libraries have been sorted by order. */
protected $is_sorted = true;
/**
* Assets constructor.
*
* @param array $libraries
* @param array $versioned_files
* @param \App\Url $url URL Resolver object
*/
public function __construct(array $libraries = [], array $versioned_files = [], \App\Url $url)
{
foreach($libraries as $library) {
$this->addLibrary($library);
}
$this->versioned_files = $versioned_files;
$this->url = $url;
}
/**
* Add a library to the collection.
*
* @param array $data Array with asset data.
* @return $this
*/
public function addLibrary(array $data)
{
$library_name = $data['name'] ?? uniqid();
$this->libraries[$library_name] = [
'name' => $library_name,
'order' => $data['order'] ?? 0,
'files' => $data['files'] ?? [],
'inline' => $data['inline'] ?? [],
'group' => $data['group'] ?? $this->default_group,
'require' => $data['require'] ?? [],
];
return $this;
}
/**
* Loads assets from given name or array definition.
*
* @param mixed $data Name or array definition of library/asset.
* @return self
*/
public function load($data)
{
if (is_array($data)) {
$item = [
'name' => $data['name'] ?? uniqid(),
'order' => $data['order'] ?? 0,
'files' => $data['files'] ?? [],
'inline' => $data['inline'] ?? [],
'group' => isset($data['group']) ? $data['group'] : $this->default_group,
'require' => isset($data['require']) ? $data['require'] : []
];
} elseif (isset($this->libraries[$data])) {
$item = $this->libraries[$data];
} else {
throw new \InvalidArgumentException(sprintf('Library %s not found!', $data));
}
$name = $item['name'];
if (!isset($this->loaded[$name])) {
if (!empty($item['require'])) {
foreach($item['require'] as $require_name) {
$this->load($require_name);
}
}
$this->loaded[$name] = $item;
$this->is_sorted = false;
}
return $this;
}
/**
* Add a single (or array of) javascript file[s].
*
* @param $js_script
* @param null $group
* @return $this
*/
public function addJs($js_script, $group = null)
{
$this->load([
'group' => $group,
'order' => 100,
'files' => [
'js' => (is_array($js_script)) ? $js_script : array($js_script),
],
]);
return $this;
}
/**
* Add a single (or array of) javascript inline scripts.
*
* @param $js_script
* @param null $group
* @return $this
*/
public function addInlineJs($js_script, $group = null)
{
$this->load([
'group' => $group,
'order' => 100,
'inline' => [
'js' => (is_array($js_script)) ? $js_script : array($js_script),
],
]);
return $this;
}
/**
* Add a single (or array of) CSS file[s].
*
* @param $css_script
* @param null $group
* @return $this
*/
public function addCss($css_script, $group = null)
{
$this->load([
'group' => $group,
'order' => 100,
'files' => [
'css' => (is_array($css_script)) ? $css_script : array($css_script),
],
]);
return $this;
}
/**
* Add a single (or array of) inline CSS file[s].
*
* @param $css_script
* @param null $group
* @return $this
*/
public function addInlineCss($css_script, $group = null)
{
$this->load([
'group' => $group,
'order' => 100,
'inline' => [
'css' => (is_array($css_script)) ? $css_script : array($css_script),
],
]);
return $this;
}
/**
* Returns CSS includes and inline tags from given group.
*
* @param string $group Group name, or default if not specified.
* @return string HTML tags as string.
*/
public function css($group = null)
{
$this->_sort();
$group = $group ?? $this->default_group;
$result = [];
foreach($this->loaded as $item)
{
if($item['group'] != $group) {
continue;
}
if (!empty($item['files']['css'])) {
foreach($item['files']['css'] as $file) {
$result[] = '<link rel="stylesheet" type="text/css" href="'.$this->_getUrl($file).'" />';
}
}
if (!empty($item['inline']['css'])) {
foreach($item['inline']['css'] as $inline) {
$result[] = '<style type="text/css">'.$inline.'</style>';
}
}
}
return implode("\n", $result)."\n";
}
/**
* Returns JS tags from given group name.
* If group name is asterisk (*), will return from all loaded groups.
* @param string $group Group name.
* @return string HTML tags as string.
*/
public function js($group = null)
{
$this->_sort();
$group = $group ?? $this->default_group;
$result = [];
foreach($this->loaded as $item)
{
if($item['group'] != $group) {
continue;
}
if (!empty($item['files']['js'])) {
foreach($item['files']['js'] as $file) {
$result[] = '<script type="text/javascript" src="'.$this->_getUrl($file).'"></script>';
}
}
if (!empty($item['inline']['js'])) {
foreach($item['inline']['js'] as $inline) {
$result[] = '<script type="text/javascript">'.$inline.'</script>';
}
}
}
return implode("\n", $result)."\n";
}
/**
* Resolve the URI of the resource, whether local or remote/CDN-based.
*
* @param $resource_uri
* @return string The resolved resource URL.
*/
protected function _getUrl($resource_uri)
{
if (isset($this->versioned_files[$resource_uri])) {
$resource_uri = $this->versioned_files[$resource_uri];
}
if (preg_match('/^(https?:)?\/\//', $resource_uri)) {
return $resource_uri;
} else {
return $this->url->content($resource_uri);
}
}
/**
* Sort the list of loaded libraries.
*/
protected function _sort()
{
if (!$this->is_sorted) {
$this->loaded = \Packaged\Helpers\Arrays::isort($this->loaded, 'order');
$this->is_sorted = true;
}
}
}

View file

@ -1,59 +0,0 @@
<!DOCTYPE html>
<?php
/**
* @var \League\Plates\Template\Template $this
* @var \App\Auth $auth
* @var \AzuraCast\Acl\StationAcl $acl
* @var \App\Url $url
* @var \App\Flash $flash
* @var \AzuraCast\Customization $customization
* @var array $app_settings
* @var object $assets
*/
?>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php
if ($title)
$page_title = $title.' - '.$app_settings['name'];
else
$page_title = $app_settings['name'];
if (!APP_IN_PRODUCTION)
$page_title = '('.ucfirst(APP_APPLICATION_ENV).') '.$page_title;
?>
<title><?=$page_title ?></title>
<?=$this->fetch('partials/icons') ?>
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/animate.css/animate.min.css') ?>">
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/material-design-iconic-font/dist/css/material-design-iconic-font.min.css') ?>">
<link rel="stylesheet" type="text/css" href="<?=$url->content('css/light.css') ?>">
<?=$this->section('custom_css') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/jquery/dist/jquery.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/bootstrap/dist/js/bootstrap.min.js') ?>"></script>
<script type="text/javascript" src="<?= $url->content('bower_components/vue/dist/' . (APP_IN_PRODUCTION ? 'vue.min.js' : 'vue.js')) ?>"></script>
<script type="text/javascript">
var APP_AppEnv = '<?=APP_APPLICATION_ENV ?>';
var APP_BaseUrl = '<?=$url->named('home') ?>';
var APP_ContentPath = '<?=$url->content('') ?>';
</script>
</head>
<body class="embed <?=$page_class ?>">
<?=$this->section('content') ?>
<?=$this->section('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/Waves/dist/waves.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/remarkable-bootstrap-notify/dist/bootstrap-notify.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('js/app.min.js') ?>"></script>
</body>
</html>

View file

@ -7,8 +7,8 @@
* @var \App\Url $url
* @var \App\Flash $flash
* @var \AzuraCast\Customization $customization
* @var \AzuraCast\Assets $assets
* @var array $app_settings
* @var object $assets
*/
?>
<html>
@ -30,24 +30,20 @@ if (!APP_IN_PRODUCTION)
<?=$this->fetch('partials/icons') ?>
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/animate.css/animate.min.css') ?>">
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/material-design-iconic-font/dist/css/material-design-iconic-font.min.css') ?>">
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/bootstrap-sweetalert/lib/sweet-alert.css') ?>">
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.min.css') ?>">
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/jquery.bootgrid/dist/jquery.bootgrid.min.css') ?>">
<?php
$assets
->load('main_header')
->load('main_body')
->load('theme_'.$customization->getTheme());
?>
<?=$this->section('custom_css') ?>
<?=$assets->css('header') ?>
<?=$assets->css('body') ?>
<?=$assets->js('header') ?>
<style type="text/css">
<?=$customization->getCustomInternalCss() ?>
<?=$customization->getCustomInternalCss() ?>
</style>
<link rel="stylesheet" type="text/css" href="<?=$assets->getPath('css/'.$customization->getTheme().'.css') ?>">
<script type="text/javascript" src="<?=$url->content('bower_components/jquery/dist/jquery.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/bootstrap/dist/js/bootstrap.min.js') ?>"></script>
<script type="text/javascript" src="<?= $url->content('bower_components/vue/dist/' . (APP_IN_PRODUCTION ? 'vue.min.js' : 'vue.js')) ?>"></script>
<script type="text/javascript">
var APP_AppEnv = '<?=APP_APPLICATION_ENV ?>';
var APP_BaseUrl = '<?=$url->named('home') ?>';
@ -75,12 +71,6 @@ var APP_ContentPath = '<?=$url->content('') ?>';
<li class="pull-right">
<ul class="hi-menu">
<!--
<li id="top-search">
<a href=""><i class="tm-icon zmdi zmdi-search"></i></a>
</li>
-->
<?=$this->fetch('partials/radio_controls') ?>
<li class="dropdown">
@ -92,11 +82,6 @@ var APP_ContentPath = '<?=$url->content('') ?>';
<?php endif; ?>
<li><a href="<?=$url->named('profile:index') ?>"><i class="zmdi zmdi-account"></i> <?=_('My Account') ?></a></li>
<li class="divider">&nbsp;</li>
<!--
<li class="hidden-xs">
<a data-action="fullscreen" href=""><i class="zmdi zmdi-fullscreen"></i> <?=_('Toggle Fullscreen') ?></a>
</li>
-->
<?php if ($auth->isMasqueraded()): ?>
<li><a href="<?=$url->named('account:endmasquerade') ?>"><i class="zmdi zmdi-power"></i> <?=_('End Session') ?></a></li>
<?php else: ?>
@ -107,14 +92,6 @@ var APP_ContentPath = '<?=$url->content('') ?>';
</ul>
</li>
</ul>
<!-- Top Search Content
<div id="top-search-wrap">
<div class="tsw-inner">
<i id="top-search-close" class="zmdi zmdi-arrow-left"></i>
<input type="text">
</div>
</div> -->
</header>
<section id="main">
@ -148,30 +125,9 @@ var APP_ContentPath = '<?=$url->content('') ?>';
PHP <?=\PHP_VERSION ?>, SlimPHP 3
</footer>
<?php /*
<!-- Page Loader -->
<div class="page-loader">
<div class="preloader pls-blue">
<svg class="pl-circular" viewBox="25 25 50 50">
<circle class="plc-path" cx="50" cy="50" r="20"></circle>
</svg>
<p>Please wait...</p>
</div>
</div>
*/ ?>
<div id="radio-player"></div>
<?=$this->section('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/remarkable-bootstrap-notify/dist/bootstrap-notify.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/bootstrap-sweetalert/lib/sweet-alert.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/autosize/dist/autosize.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/jquery.bootgrid/dist/jquery.bootgrid.min.js') ?>"></script>
<script type="text/javascript" src="<?=$assets->getPath('js/app.min.js') ?>"></script>
<?=$assets->js('body') ?>
<?php if ($flash->hasMessages()): ?>
<script type="text/javascript">

View file

@ -7,8 +7,8 @@
* @var \App\Url $url
* @var \App\Flash $flash
* @var \AzuraCast\Customization $customization
* @var \AzuraCast\Assets $assets
* @var array $app_settings
* @var object $assets
*/
?>
<html>
@ -30,20 +30,20 @@ if (!APP_IN_PRODUCTION)
<?=$this->fetch('partials/icons') ?>
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/animate.css/animate.min.css') ?>">
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/material-design-iconic-font/dist/css/material-design-iconic-font.min.css') ?>">
<link rel="stylesheet" type="text/css" href="<?=$url->content('css/'.$customization->getPublicTheme().'.css') ?>">
<?php
$assets
->load('minimal_header')
->load('minimal_body')
->load('theme_'.$customization->getPublicTheme());
?>
<?=$this->section('custom_css') ?>
<?=$assets->css('header') ?>
<?=$assets->css('body') ?>
<?=$assets->js('header') ?>
<style type="text/css">
<?=$customization->getCustomPublicCss() ?>
</style>
<script type="text/javascript" src="<?=$url->content('bower_components/jquery/dist/jquery.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/bootstrap/dist/js/bootstrap.min.js') ?>"></script>
<script type="text/javascript" src="<?= $url->content('bower_components/vue/dist/' . (APP_IN_PRODUCTION ? 'vue.min.js' : 'vue.js')) ?>"></script>
<script type="text/javascript">
var APP_AppEnv = '<?=APP_APPLICATION_ENV ?>';
var APP_BaseUrl = '<?=$url->named('home') ?>';
@ -54,11 +54,7 @@ if (!APP_IN_PRODUCTION)
<body class="<?=$page_class ?>">
<?=$this->section('content') ?>
<?=$this->section('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/Waves/dist/waves.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('bower_components/remarkable-bootstrap-notify/dist/bootstrap-notify.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('js/app.min.js') ?>"></script>
<?=$assets->js('body') ?>
<?php if ($flash->hasMessages()): ?>
<script type="text/javascript">

View file

@ -6,13 +6,10 @@
<?=$this->fetch('partials/form_view') ?>
<?php endif; ?>
<?php $this->start('custom_js') ?>
<script type="text/javascript" src="<?=$url->content('bower_components/chosen/chosen.jquery.min.js') ?>"></script>
<script type="text/javascript" src="<?=$url->content('vendors/bower_components/zxcvbn/dist/zxcvbn.js') ?>"></script>
<?php $this->stop('custom_js') ?>
<?php $this->start('custom_css') ?>
<link rel="stylesheet" type="text/css" href="<?=$url->content('bower_components/chosen/chosen.min.css') ?>">
<?php $this->stop('custom_css') ?>
<?php
/** @var \AzuraCast\Assets $assets */
$assets->load('forms');
?>
<script type="text/javascript">
$(function() {