commit
09133a0177
26 changed files with 859 additions and 20 deletions
.env
app
config
database
migrations
seeds
public
resources
assets
views
routes
vendor/composer
4
.env
4
.env
|
@ -1,7 +1,7 @@
|
|||
APP_NAME=Heimdall
|
||||
APP_ENV=production
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:I206O8ibx+GQyRE7BeOxDobn04Mfmyyc5Ptzns/C0mY=
|
||||
APP_DEBUG=false
|
||||
APP_DEBUG=true
|
||||
APP_LOG_LEVEL=debug
|
||||
APP_URL=http://localhost
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
|||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Item;
|
||||
use App\Setting;
|
||||
use App\SupportedApps\Nzbget;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
|
|
102
app/Http/Controllers/SettingsController.php
Normal file
102
app/Http/Controllers/SettingsController.php
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Setting;
|
||||
use App\SettingGroup;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$settings = SettingGroup::with([
|
||||
'settings',
|
||||
])->orderBy('order', 'ASC')->get();
|
||||
|
||||
return view('settings.list')->with([
|
||||
'groups' => $settings,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$setting = Setting::find($id);
|
||||
|
||||
if((bool)$setting->system === true) return abort(404);
|
||||
|
||||
if (!is_null($setting)) {
|
||||
return view('settings.edit')->with([
|
||||
'setting' => $setting,
|
||||
]);
|
||||
} else {
|
||||
return redirect()->route('settings.list')->with([
|
||||
'error' => 'This Setting does not exist.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$setting = Setting::find($id);
|
||||
|
||||
if (!is_null($setting)) {
|
||||
$data = Setting::getInput();
|
||||
|
||||
if ($setting->type == 'image') {
|
||||
|
||||
|
||||
if($request->hasFile('value')) {
|
||||
$path = $request->file('value')->store('backgrounds');
|
||||
$setting->value = $path;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
$setting->value = $data->value;
|
||||
}
|
||||
|
||||
$setting->save();
|
||||
|
||||
return redirect()->route('settings.index')->with([
|
||||
'success' => 'You have successfully edited this Setting!',
|
||||
]);
|
||||
} else {
|
||||
return redirect()->route('settings.index')->with([
|
||||
'error' => 'This Setting does not exist.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function clear($id)
|
||||
{
|
||||
$setting = Setting::find($id);
|
||||
if((bool)$setting->system !== true) {
|
||||
$setting->value = '';
|
||||
$setting->save();
|
||||
}
|
||||
return redirect()->route('settings.index')->with([
|
||||
'success' => 'You have successfully edited this Setting!',
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ namespace App\Providers;
|
|||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Artisan;
|
||||
use Schema;
|
||||
use App\Setting;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
@ -14,15 +16,35 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function boot()
|
||||
{
|
||||
if(!file_exists(database_path(env('DB_DATABASE')))) {
|
||||
$alt_bg = '';
|
||||
|
||||
if(!is_file(database_path(env('DB_DATABASE')))) {
|
||||
// first time setup
|
||||
touch(database_path(env('DB_DATABASE')));
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true));
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
Artisan::call('storage:link');
|
||||
//Cache
|
||||
//Artisan::call('config:cache');
|
||||
//Artisan::call('route:cache');
|
||||
}
|
||||
if(is_file(database_path(env('DB_DATABASE')))) {
|
||||
if(Schema::hasTable('settings')) {
|
||||
if($bg_image = Setting::fetch('background_image')) {
|
||||
$alt_bg = ' style="background-image: url('.asset('storage/'.$bg_image).')"';
|
||||
}
|
||||
|
||||
// check version to see if an upgrade is needed
|
||||
$db_version = Setting::fetch('version');
|
||||
$app_version = config('app.version');
|
||||
if(version_compare($app_version, $db_version) == 1) { // app is higher than db, so need to run migrations etc
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
}
|
||||
} else {
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
}
|
||||
}
|
||||
view()->share('alt_bg', $alt_bg);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,6 +54,8 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
$this->app->singleton('settings', function () {
|
||||
return new Setting();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
211
app/Setting.php
Normal file
211
app/Setting.php
Normal file
|
@ -0,0 +1,211 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Form;
|
||||
|
||||
class Setting extends Model
|
||||
{
|
||||
/**
|
||||
* The database table used by the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'settings';
|
||||
|
||||
/**
|
||||
* Tell the Model this Table doesn't support timestamps.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* Cache storage for Settings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $cache = [];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getInput()
|
||||
{
|
||||
return (object) [
|
||||
'value' => Input::get('value'),
|
||||
'image' => Input::file('value'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getListValueAttribute()
|
||||
{
|
||||
switch($this->type) {
|
||||
case 'image':
|
||||
if(!empty($this->value)) {
|
||||
$value = '<a href="'.asset('storage/'.$this->value).'" title="View" target="_blank">View</a>';
|
||||
} else {
|
||||
$value = '- not set -';
|
||||
}
|
||||
break;
|
||||
case 'boolean':
|
||||
if((bool)$this->value === true) {
|
||||
$value = 'Yes';
|
||||
} else {
|
||||
$value = 'No';
|
||||
}
|
||||
break;
|
||||
case 'select':
|
||||
if(!empty($this->value) && $this->value !== 'none') {
|
||||
$options = (array)json_decode($this->options);
|
||||
$value = $options[$this->value];
|
||||
} else {
|
||||
$value = '- not set -';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$value = $this->value;
|
||||
break;
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
||||
}
|
||||
|
||||
public function getEditValueAttribute()
|
||||
{
|
||||
switch($this->type) {
|
||||
case 'image':
|
||||
$value = '';
|
||||
if(isset($this->value) && !empty($this->value)) {
|
||||
$value .= '<a class="setting-view-image" href="'.asset('storage/'.$this->value).'" title="View" target="_blank"><img src="'.asset('storage/'.$this->value).'" /></a>';
|
||||
}
|
||||
$value .= Form::file('value', ['class' => 'form-control']);
|
||||
if(isset($this->value) && !empty($this->value)) {
|
||||
$value .= '<a class="settinglink" href="'.route('settings.clear', $this->id).'" title="Remove">Reset back to default</a>';
|
||||
}
|
||||
|
||||
break;
|
||||
case 'boolean':
|
||||
$checked = false;
|
||||
if(isset($this->value) && (bool)$this->value === true) $checked = true;
|
||||
$set_checked = ($checked) ? ' checked="checked"' : '';
|
||||
$value = '
|
||||
<label class="switch">
|
||||
<input type="hidden" name="value" value="0" />
|
||||
<input type="checkbox" name="value" value="1"'.$set_checked.' />
|
||||
<span class="slider round"></span>
|
||||
</label>';
|
||||
|
||||
break;
|
||||
case 'select':
|
||||
$options = json_decode($this->options);
|
||||
$value = Form::select('value', $options, null, ['class' => 'form-control']);
|
||||
break;
|
||||
default:
|
||||
$value = Form::text('value', null, ['class' => 'form-control']);
|
||||
break;
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
||||
}
|
||||
|
||||
public function group()
|
||||
{
|
||||
return $this->belongsTo('App\SettingGroup', 'group_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function fetch($key)
|
||||
{
|
||||
if (Setting::cached($key)) {
|
||||
return Setting::$cache[$key];
|
||||
} else {
|
||||
$find = self::where('key', '=', $key)->first();
|
||||
|
||||
if (!is_null($find)) {
|
||||
$value = $find->value;
|
||||
Setting::add($key, $value);
|
||||
|
||||
return $value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param $value
|
||||
*/
|
||||
public static function add($key, $value)
|
||||
{
|
||||
Setting::$cache[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function cached($key)
|
||||
{
|
||||
return array_key_exists($key, Setting::$cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return html
|
||||
*/
|
||||
public static function search()
|
||||
{
|
||||
$output = '';
|
||||
$homepage_search = self::fetch('homepage_search');
|
||||
$search_provider = self::where('key', '=', 'search_provider')->first();
|
||||
|
||||
//die(var_dump($search_provider->value));
|
||||
// return early if search isn't applicable
|
||||
if((bool)$homepage_search !== true) return $output;
|
||||
if($search_provider->value === 'none') return $output;
|
||||
if(empty($search_provider->value)) return $output;
|
||||
if(is_null($search_provider->value)) return $output;
|
||||
|
||||
|
||||
if((bool)$homepage_search && (bool)$search_provider) {
|
||||
|
||||
$options = (array)json_decode($search_provider->options);
|
||||
$name = $options[$search_provider->value];
|
||||
if((bool)$search_provider->value) {
|
||||
switch($search_provider->value) {
|
||||
case 'google':
|
||||
$url = 'https://www.google.com/search';
|
||||
$var = 'q';
|
||||
break;
|
||||
case 'ddg':
|
||||
$url = 'https://duckduckgo.com/';
|
||||
$var = 'q';
|
||||
break;
|
||||
case 'bing':
|
||||
$url = 'https://www.bing.com/search';
|
||||
$var = 'q';
|
||||
break;
|
||||
}
|
||||
$output .= '<div class="searchform">';
|
||||
$output .= Form::open(['url' => $url, 'method' => 'get']);
|
||||
$output .= '<div class="input-container">';
|
||||
$output .= Form::text($var, null, ['class' => 'homesearch', 'placeholder' => $name.' search...']);
|
||||
$output .= '<button type="submit">Search</button>';
|
||||
$output .= '</div>';
|
||||
$output .= Form::close();
|
||||
$output .= '</div>';
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
}
|
27
app/SettingGroup.php
Normal file
27
app/SettingGroup.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SettingGroup extends Model
|
||||
{
|
||||
/**
|
||||
* The database table used by the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'setting_groups';
|
||||
|
||||
/**
|
||||
* Tell the Model this Table doesn't support timestamps.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
public function settings()
|
||||
{
|
||||
return $this->hasMany('App\Setting', 'group_id');
|
||||
}
|
||||
}
|
|
@ -13,7 +13,8 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'Laravel'),
|
||||
'name' => env('APP_NAME', 'Heimdall'),
|
||||
'version' => '1.1.0',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateSettingsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('settings', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('group_id')->default(0);
|
||||
$table->string('key');
|
||||
$table->string('type')->default('text');
|
||||
$table->text('options')->nullable();
|
||||
$table->string('label');
|
||||
$table->string('value')->nullable();
|
||||
$table->string('order')->default(0);
|
||||
$table->boolean('system')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('settings');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateSettingGroupsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('setting_groups', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('title');
|
||||
$table->integer('order')->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('setting_groups');
|
||||
}
|
||||
}
|
|
@ -11,6 +11,6 @@ class DatabaseSeeder extends Seeder
|
|||
*/
|
||||
public function run()
|
||||
{
|
||||
// $this->call(UsersTableSeeder::class);
|
||||
$this->call(SettingsSeeder::class);
|
||||
}
|
||||
}
|
||||
|
|
91
database/seeds/SettingsSeeder.php
Normal file
91
database/seeds/SettingsSeeder.php
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Setting;
|
||||
use App\SettingGroup;
|
||||
|
||||
class SettingsSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// Groups
|
||||
if(!SettingGroup::find(1)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 1;
|
||||
$setting_group->title = 'System';
|
||||
$setting_group->order = 0;
|
||||
$setting_group->save();
|
||||
}
|
||||
if(!SettingGroup::find(2)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 2;
|
||||
$setting_group->title = 'Appearance';
|
||||
$setting_group->order = 1;
|
||||
$setting_group->save();
|
||||
}
|
||||
if(!SettingGroup::find(3)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 3;
|
||||
$setting_group->title = 'Miscellaneous';
|
||||
$setting_group->order = 2;
|
||||
$setting_group->save();
|
||||
}
|
||||
|
||||
if($version = Setting::find(1)) {
|
||||
$version->value = config('app.version');
|
||||
$version->save();
|
||||
} else {
|
||||
$setting = new Setting;
|
||||
$setting->id = 1;
|
||||
$setting->group_id = 1;
|
||||
$setting->key = 'version';
|
||||
$setting->type = 'text';
|
||||
$setting->label = 'Version';
|
||||
$setting->value = config('app.version');
|
||||
$setting->system = true;
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if(!Setting::find(2)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 2;
|
||||
$setting->group_id = 2;
|
||||
$setting->key = 'background_image';
|
||||
$setting->type = 'image';
|
||||
$setting->label = 'Background Image';
|
||||
$setting->save();
|
||||
}
|
||||
if(!Setting::find(3)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 3;
|
||||
$setting->group_id = 3;
|
||||
$setting->key = 'homepage_search';
|
||||
$setting->type = 'boolean';
|
||||
$setting->label = 'Homepage Search';
|
||||
$setting->save();
|
||||
}
|
||||
if(!Setting::find(4)) {
|
||||
$options = json_encode([
|
||||
'none' => '- not set -',
|
||||
'google' => 'Google',
|
||||
'ddg' => 'DuckDuckGo',
|
||||
'bing' => 'Bing'
|
||||
]);
|
||||
|
||||
$setting = new Setting;
|
||||
$setting->id = 4;
|
||||
$setting->group_id = 3;
|
||||
$setting->key = 'search_provider';
|
||||
$setting->type = 'select';
|
||||
$setting->options = $options;
|
||||
$setting->label = 'Search Provider';
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
105
public/css/app.css
vendored
105
public/css/app.css
vendored
|
@ -318,6 +318,13 @@ body {
|
|||
padding: 20px;
|
||||
}
|
||||
|
||||
#app main {
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#app main,
|
||||
#app #sortable {
|
||||
padding: 10px;
|
||||
|
@ -343,7 +350,7 @@ body {
|
|||
}
|
||||
|
||||
#config-buttons {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
display: -webkit-box;
|
||||
|
@ -371,6 +378,24 @@ body {
|
|||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.item-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.item-container .item-edit {
|
||||
color: white;
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 8px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message-container {
|
||||
width: 100%;
|
||||
padding: 10px 20px;
|
||||
|
@ -553,7 +578,7 @@ body {
|
|||
background: #f9fafd;
|
||||
max-width: 1000px;
|
||||
width: 100%;
|
||||
margin: 0 40px;
|
||||
margin: 10px 40px;
|
||||
}
|
||||
|
||||
.module-container header,
|
||||
|
@ -721,7 +746,8 @@ div.create .input label:not(.switch) {
|
|||
font-weight: 300;
|
||||
}
|
||||
|
||||
div.create .input input {
|
||||
div.create .input input,
|
||||
div.create .input select {
|
||||
width: 100%;
|
||||
border: 1px solid #dedfe2;
|
||||
padding: 10px;
|
||||
|
@ -864,6 +890,79 @@ button.link {
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
a.settinglink {
|
||||
color: #2f313a;
|
||||
font-size: 13px;
|
||||
margin: 15px 5px;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.setting-view-image {
|
||||
margin-bottom: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.setting-view-image img {
|
||||
max-width: 330px;
|
||||
}
|
||||
|
||||
.searchform {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-item-align: start;
|
||||
align-self: flex-start;
|
||||
text-align: center;
|
||||
margin: 50px auto;
|
||||
padding: 14px;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 14px;
|
||||
-webkit-box-shadow: inset 0px 1px 6px 0 rgba(0, 0, 0, 0.3);
|
||||
box-shadow: inset 0px 1px 6px 0 rgba(0, 0, 0, 0.3);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.5);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.35);
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.searchform form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.searchform .input-container {
|
||||
background: white;
|
||||
border-radius: 5px;
|
||||
-webkit-box-shadow: 0px 0px 5px 0 rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 0px 0px 5px 0 rgba(0, 0, 0, 0.4);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.searchform input {
|
||||
padding: 17px 15px;
|
||||
font-size: 15px;
|
||||
border: 0 none;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.searchform button {
|
||||
position: absolute;
|
||||
right: 14px;
|
||||
top: 14px;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
padding: 7px 15px;
|
||||
line-height: 37px;
|
||||
font-weight: 500;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
background: #d64d55;
|
||||
}
|
||||
|
||||
/*! Huebee v2.0.0
|
||||
http://huebee.buzz
|
||||
---------------------------------------------- */
|
||||
|
|
2
public/js/app.js
vendored
2
public/js/app.js
vendored
|
@ -46,6 +46,7 @@ $.when( $.ready ).then(function() {
|
|||
app.toggleClass('header');
|
||||
if(active) {
|
||||
$('.add-item').hide();
|
||||
$('.item-edit').hide();
|
||||
$('#app').removeClass('sidebar');
|
||||
$("#sortable").sortable("disable")
|
||||
} else {
|
||||
|
@ -54,6 +55,7 @@ $.when( $.ready ).then(function() {
|
|||
function()
|
||||
{
|
||||
$('.add-item').fadeIn();
|
||||
$('.item-edit').fadeIn();
|
||||
}, 350);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"/css/app.css": "/css/app.css?id=2bcada6f52a2ee8447df",
|
||||
"/js/app.js": "/js/app.js?id=aa9e426dc7b92d42d3b2"
|
||||
"/css/app.css": "/css/app.css?id=2102f4e7317cba78bff5",
|
||||
"/js/app.js": "/js/app.js?id=2dffa24cf7255229e085"
|
||||
}
|
2
resources/assets/js/app.js
vendored
2
resources/assets/js/app.js
vendored
|
@ -37,6 +37,7 @@ $.when( $.ready ).then(function() {
|
|||
app.toggleClass('header');
|
||||
if(active) {
|
||||
$('.add-item').hide();
|
||||
$('.item-edit').hide();
|
||||
$('#app').removeClass('sidebar');
|
||||
$("#sortable").sortable("disable")
|
||||
} else {
|
||||
|
@ -45,6 +46,7 @@ $.when( $.ready ).then(function() {
|
|||
function()
|
||||
{
|
||||
$('.add-item').fadeIn();
|
||||
$('.item-edit').fadeIn();
|
||||
}, 350);
|
||||
|
||||
}
|
||||
|
|
88
resources/assets/sass/_app.scss
vendored
88
resources/assets/sass/_app.scss
vendored
|
@ -66,6 +66,9 @@ body {
|
|||
}
|
||||
|
||||
}
|
||||
main {
|
||||
flex-direction: column;
|
||||
}
|
||||
main, #sortable {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
|
@ -80,7 +83,7 @@ body {
|
|||
}
|
||||
}
|
||||
#config-buttons {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
display:flex;
|
||||
|
@ -104,6 +107,20 @@ body {
|
|||
.item-container {
|
||||
//width: 340px;
|
||||
//transition: width .35s ease-in-out;
|
||||
position: relative;
|
||||
.item-edit {
|
||||
color: white;
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 8px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: rgba(0,0,0,0.7);
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.message-container {
|
||||
width: 100%;
|
||||
|
@ -163,6 +180,9 @@ body {
|
|||
}
|
||||
.item-container {
|
||||
//width: 240px;
|
||||
.item-edit {
|
||||
//display: block;
|
||||
}
|
||||
}
|
||||
.item, .add-item {
|
||||
transform: scale(0.9);
|
||||
|
@ -258,7 +278,7 @@ body {
|
|||
background: #f9fafd;
|
||||
max-width: 1000px;
|
||||
width: 100%;
|
||||
margin: 0 40px;
|
||||
margin: 10px 40px;
|
||||
header, footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -387,7 +407,7 @@ div.create {
|
|||
display: block;
|
||||
font-weight: 300;
|
||||
}
|
||||
input {
|
||||
input, select {
|
||||
width: 100%;
|
||||
border: 1px solid #dedfe2;
|
||||
padding: 10px;
|
||||
|
@ -512,4 +532,66 @@ div.create {
|
|||
border: none;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
a.settinglink {
|
||||
color: $app-text;
|
||||
font-size: 13px;
|
||||
margin: 15px 5px;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
}
|
||||
.setting-view-image {
|
||||
margin-bottom: 20px;
|
||||
display: inline-block;
|
||||
img {
|
||||
max-width: 330px;
|
||||
}
|
||||
}
|
||||
|
||||
.searchform {
|
||||
display: flex;
|
||||
align-self: flex-start;
|
||||
text-align: center;
|
||||
margin: 50px auto;
|
||||
padding: 14px;
|
||||
background: rgba(0,0,0,0.2);
|
||||
border-radius: 14px;
|
||||
box-shadow: inset 0px 1px 6px 0 rgba(0,0,0,0.3);
|
||||
border-top: 1px solid rgba(0,0,0,0.5);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.35);
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
form {
|
||||
width: 100%;
|
||||
}
|
||||
.input-container {
|
||||
background: white;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 0px 5px 0 rgba(0,0,0,0.4);
|
||||
overflow: hidden;
|
||||
}
|
||||
input {
|
||||
padding: 17px 15px;
|
||||
font-size: 15px;
|
||||
border: 0 none;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
}
|
||||
button {
|
||||
position: absolute;
|
||||
right: 14px;
|
||||
top: 14px;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
padding: 7px 15px;
|
||||
line-height: 37px;
|
||||
font-weight: 500;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
background: $app-red;
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<div id="app"{!! $alt_bg !!}>
|
||||
<nav class="sidenav">
|
||||
<a class="close-sidenav" href=""><i class="fas fa-times-circle"></i></a>
|
||||
@if(isset($all_apps))
|
||||
|
@ -62,7 +62,12 @@
|
|||
@if(!Request::is(['items', 'items/*']))
|
||||
<a id="items" class="config" href="{{ route('items.index') }}"><i class="fas fa-list"></i></a>
|
||||
@endif
|
||||
<a id="config-button" class="config" href=""><i class="fas fa-cogs"></i></a>
|
||||
@if(!Request::is(['settings', 'settings/*']))
|
||||
<a id="settings" class="config" href="{{ route('settings.index') }}"><i class="fas fa-cogs"></i></a>
|
||||
@endif
|
||||
@if(Route::is('dash'))
|
||||
<a id="config-button" class="config" href=""><i class="fas fa-exchange"></i></a>
|
||||
@endif
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
|
|
@ -9,4 +9,6 @@
|
|||
|
||||
<a class="link" href="{{ $app->url }}"><i class="fas fa-arrow-alt-to-right"></i></a>
|
||||
</div>
|
||||
<a class="item-edit" href="{{ route('items.edit', $app->id) }}"><i class="fas fa-pencil"></i></a>
|
||||
|
||||
</section>
|
||||
|
|
1
resources/views/partials/search.blade.php
Normal file
1
resources/views/partials/search.blade.php
Normal file
|
@ -0,0 +1 @@
|
|||
{!! App\Setting::search() !!}
|
9
resources/views/settings/edit.blade.php
Normal file
9
resources/views/settings/edit.blade.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
@extends('app')
|
||||
|
||||
@section('content')
|
||||
|
||||
{!! Form::model($setting, ['method' => 'PATCH', 'files' => true, 'route' => ['settings.edit', $setting->id]]) !!}
|
||||
@include('settings.form')
|
||||
{!! Form::close() !!}
|
||||
|
||||
@endsection
|
30
resources/views/settings/form.blade.php
Normal file
30
resources/views/settings/form.blade.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<section class="module-container">
|
||||
<header>
|
||||
<div class="section-title">{{ $setting->label }}</div>
|
||||
<div class="module-actions">
|
||||
<button type="submit"class="button"><i class="fa fa-save"></i><span>Save</span></button>
|
||||
<a href="{{ route('settings.index') }}" class="button"><i class="fa fa-ban"></i><span>Cancel</span></a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="create">
|
||||
{!! csrf_field() !!}
|
||||
<!--<div class="input">
|
||||
<label>Application name</label>
|
||||
{!! Form::select('supported', \App\Item::supportedOptions(), array('placeholder' => 'Title','class' => 'form-control')) !!}
|
||||
</div>-->
|
||||
|
||||
<div class="input">
|
||||
{!! $setting->edit_value !!}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<footer>
|
||||
<div class="section-title"> </div>
|
||||
<div class="module-actions">
|
||||
<button type="submit"class="button"><i class="fa fa-save"></i><span>Save</span></button>
|
||||
<a href="{{ route('settings.index') }}" class="button"><i class="fa fa-ban"></i><span>Cancel</span></a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</section>
|
52
resources/views/settings/list.blade.php
Normal file
52
resources/views/settings/list.blade.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
@extends('app')
|
||||
|
||||
@section('content')
|
||||
|
||||
@foreach ($groups as $group)
|
||||
<section class="module-container">
|
||||
<header>
|
||||
<div class="section-title">
|
||||
{{ $group->title }}
|
||||
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th style="width: 60%;">Value</th>
|
||||
<th class="text-center" style="width: 75px;">Edit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (count($group->settings) > 0)
|
||||
@foreach ($group->settings as $setting)
|
||||
<tr>
|
||||
<td>{{ $setting->label }}</td>
|
||||
<td>
|
||||
{!! $setting->list_value !!}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
@if((bool)$setting->system !== true)
|
||||
<a href="{!! route('settings.edit', ['id' => $setting->id]) !!}" title="Edit {!! $setting->label !!}" class="secondary"><i class="fa fa-pencil"></i></a>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@else
|
||||
|
||||
<tr>
|
||||
<td colspan="3" class="form-error text-center">
|
||||
<strong>No items found</strong>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
@endforeach
|
||||
|
||||
@endsection
|
|
@ -1,6 +1,8 @@
|
|||
@extends('app')
|
||||
|
||||
@section('content')
|
||||
@include('partials.search')
|
||||
|
||||
@if($apps->first())
|
||||
@include('sortable')
|
||||
@else
|
||||
|
|
|
@ -20,4 +20,24 @@ Route::get('items/pin/{id}', 'ItemController@pin')->name('items.pin');
|
|||
Route::get('items/restore/{id}', 'ItemController@restore')->name('items.restore');
|
||||
Route::get('items/unpin/{id}', 'ItemController@unpin')->name('items.unpin');
|
||||
Route::get('items/pintoggle/{id}/{ajax?}', 'ItemController@pinToggle')->name('items.pintoggle');
|
||||
Route::post('order', 'ItemController@setOrder')->name('items.order');
|
||||
Route::post('order', 'ItemController@setOrder')->name('items.order');
|
||||
|
||||
/**
|
||||
* Settings.
|
||||
*/
|
||||
Route::group([
|
||||
'as' => 'settings.',
|
||||
'prefix' => 'settings',
|
||||
], function () {
|
||||
|
||||
Route::get('/', 'SettingsController@index')
|
||||
->name('index');
|
||||
Route::get('edit/{id}', 'SettingsController@edit')
|
||||
->name('edit');
|
||||
Route::get('clear/{id}', 'SettingsController@clear')
|
||||
->name('clear');
|
||||
|
||||
|
||||
Route::patch('edit/{id}', 'SettingsController@update');
|
||||
|
||||
});
|
5
vendor/composer/autoload_classmap.php
vendored
5
vendor/composer/autoload_classmap.php
vendored
|
@ -14,6 +14,7 @@ return array(
|
|||
'App\\Http\\Controllers\\Auth\\ResetPasswordController' => $baseDir . '/app/Http/Controllers/Auth/ResetPasswordController.php',
|
||||
'App\\Http\\Controllers\\Controller' => $baseDir . '/app/Http/Controllers/Controller.php',
|
||||
'App\\Http\\Controllers\\ItemController' => $baseDir . '/app/Http/Controllers/ItemController.php',
|
||||
'App\\Http\\Controllers\\SettingsController' => $baseDir . '/app/Http/Controllers/SettingsController.php',
|
||||
'App\\Http\\Kernel' => $baseDir . '/app/Http/Kernel.php',
|
||||
'App\\Http\\Middleware\\EncryptCookies' => $baseDir . '/app/Http/Middleware/EncryptCookies.php',
|
||||
'App\\Http\\Middleware\\RedirectIfAuthenticated' => $baseDir . '/app/Http/Middleware/RedirectIfAuthenticated.php',
|
||||
|
@ -26,7 +27,8 @@ return array(
|
|||
'App\\Providers\\BroadcastServiceProvider' => $baseDir . '/app/Providers/BroadcastServiceProvider.php',
|
||||
'App\\Providers\\EventServiceProvider' => $baseDir . '/app/Providers/EventServiceProvider.php',
|
||||
'App\\Providers\\RouteServiceProvider' => $baseDir . '/app/Providers/RouteServiceProvider.php',
|
||||
'App\\Providers\\SupportedServiceProvider' => $baseDir . '/app/Providers/SupportedServiceProvider.php',
|
||||
'App\\Setting' => $baseDir . '/app/Setting.php',
|
||||
'App\\SettingGroup' => $baseDir . '/app/SettingGroup.php',
|
||||
'App\\SupportedApps\\Contracts\\Applications' => $baseDir . '/app/SupportedApps/Contracts/Applications.php',
|
||||
'App\\SupportedApps\\Nzbget' => $baseDir . '/app/SupportedApps/Nzbget.php',
|
||||
'App\\SupportedApps\\Plex' => $baseDir . '/app/SupportedApps/Plex.php',
|
||||
|
@ -2666,6 +2668,7 @@ return array(
|
|||
'SebastianBergmann\\ResourceOperations\\ResourceOperations' => $vendorDir . '/sebastian/resource-operations/src/ResourceOperations.php',
|
||||
'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php',
|
||||
'SessionUpdateTimestampHandlerInterface' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php',
|
||||
'SettingsSeeder' => $baseDir . '/database/seeds/SettingsSeeder.php',
|
||||
'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php',
|
||||
'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php',
|
||||
'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php',
|
||||
|
|
5
vendor/composer/autoload_static.php
vendored
5
vendor/composer/autoload_static.php
vendored
|
@ -325,6 +325,7 @@ class ComposerStaticInit4b6fb9210a1ea37c2db27b8ff53a1ecf
|
|||
'App\\Http\\Controllers\\Auth\\ResetPasswordController' => __DIR__ . '/../..' . '/app/Http/Controllers/Auth/ResetPasswordController.php',
|
||||
'App\\Http\\Controllers\\Controller' => __DIR__ . '/../..' . '/app/Http/Controllers/Controller.php',
|
||||
'App\\Http\\Controllers\\ItemController' => __DIR__ . '/../..' . '/app/Http/Controllers/ItemController.php',
|
||||
'App\\Http\\Controllers\\SettingsController' => __DIR__ . '/../..' . '/app/Http/Controllers/SettingsController.php',
|
||||
'App\\Http\\Kernel' => __DIR__ . '/../..' . '/app/Http/Kernel.php',
|
||||
'App\\Http\\Middleware\\EncryptCookies' => __DIR__ . '/../..' . '/app/Http/Middleware/EncryptCookies.php',
|
||||
'App\\Http\\Middleware\\RedirectIfAuthenticated' => __DIR__ . '/../..' . '/app/Http/Middleware/RedirectIfAuthenticated.php',
|
||||
|
@ -337,7 +338,8 @@ class ComposerStaticInit4b6fb9210a1ea37c2db27b8ff53a1ecf
|
|||
'App\\Providers\\BroadcastServiceProvider' => __DIR__ . '/../..' . '/app/Providers/BroadcastServiceProvider.php',
|
||||
'App\\Providers\\EventServiceProvider' => __DIR__ . '/../..' . '/app/Providers/EventServiceProvider.php',
|
||||
'App\\Providers\\RouteServiceProvider' => __DIR__ . '/../..' . '/app/Providers/RouteServiceProvider.php',
|
||||
'App\\Providers\\SupportedServiceProvider' => __DIR__ . '/../..' . '/app/Providers/SupportedServiceProvider.php',
|
||||
'App\\Setting' => __DIR__ . '/../..' . '/app/Setting.php',
|
||||
'App\\SettingGroup' => __DIR__ . '/../..' . '/app/SettingGroup.php',
|
||||
'App\\SupportedApps\\Contracts\\Applications' => __DIR__ . '/../..' . '/app/SupportedApps/Contracts/Applications.php',
|
||||
'App\\SupportedApps\\Nzbget' => __DIR__ . '/../..' . '/app/SupportedApps/Nzbget.php',
|
||||
'App\\SupportedApps\\Plex' => __DIR__ . '/../..' . '/app/SupportedApps/Plex.php',
|
||||
|
@ -2977,6 +2979,7 @@ class ComposerStaticInit4b6fb9210a1ea37c2db27b8ff53a1ecf
|
|||
'SebastianBergmann\\ResourceOperations\\ResourceOperations' => __DIR__ . '/..' . '/sebastian/resource-operations/src/ResourceOperations.php',
|
||||
'SebastianBergmann\\Version' => __DIR__ . '/..' . '/sebastian/version/src/Version.php',
|
||||
'SessionUpdateTimestampHandlerInterface' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php',
|
||||
'SettingsSeeder' => __DIR__ . '/../..' . '/database/seeds/SettingsSeeder.php',
|
||||
'Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php',
|
||||
'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php',
|
||||
'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php',
|
||||
|
|
Loading…
Add table
Reference in a new issue