mirror of
https://github.com/linuxserver/Heimdall.git
synced 2026-08-07 07:16:13 +00:00
Merge pull request #1572 from linuxserver/feature/default-tag-group
Add a configurable default tag for the dashboard
This commit is contained in:
@@ -123,6 +123,12 @@ class Setting extends Model
|
||||
$options = (array) json_decode($this->options);
|
||||
if ($this->key === 'search_provider') {
|
||||
$options = Search::providers()->pluck('name', 'id')->toArray();
|
||||
} elseif ($this->key === 'default_tag') {
|
||||
$options = [];
|
||||
$tags = Item::where('type', 1)->where('id', '>', 0)->pinned()->orderBy('title', 'asc')->get();
|
||||
foreach ($tags as $tag) {
|
||||
$options[$tag->tag_url] = $tag->title;
|
||||
}
|
||||
}
|
||||
$value = (array_key_exists($this->value, $options))
|
||||
? __($options[$this->value])
|
||||
@@ -190,6 +196,12 @@ class Setting extends Model
|
||||
$options = json_decode($this->options);
|
||||
if ($this->key === 'search_provider') {
|
||||
$options = Search::providers()->pluck('name', 'id');
|
||||
} elseif ($this->key === 'default_tag') {
|
||||
$options = ['' => 'app.options.none'];
|
||||
$tags = Item::where('type', 1)->where('id', '>', 0)->pinned()->orderBy('title', 'asc')->get();
|
||||
foreach ($tags as $tag) {
|
||||
$options[$tag->tag_url] = $tag->title;
|
||||
}
|
||||
}
|
||||
$value = '<select name="value" class="form-control">';
|
||||
foreach ($options as $key => $opt) {
|
||||
|
||||
@@ -349,5 +349,20 @@ class SettingsSeeder extends Seeder
|
||||
$setting->label = 'app.settings.treat_tags_as';
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if (! $setting = Setting::find(15)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 15;
|
||||
$setting->group_id = 4;
|
||||
$setting->key = 'default_tag';
|
||||
$setting->type = 'select';
|
||||
$setting->label = 'app.settings.default_tag';
|
||||
$setting->value = '';
|
||||
$setting->save();
|
||||
} else {
|
||||
$setting->group_id = 4;
|
||||
$setting->label = 'app.settings.default_tag';
|
||||
$setting->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ return array (
|
||||
'settings.custom_css' => 'Custom CSS',
|
||||
'settings.custom_js' => 'Custom JavaScript',
|
||||
'settings.treat_tags_as' => 'Treat Tags As:',
|
||||
'settings.default_tag' => 'Default tag',
|
||||
'settings.folders' => 'Folders',
|
||||
'settings.tags' => 'Tags',
|
||||
'settings.categories' => 'Categories',
|
||||
|
||||
Vendored
+8
@@ -4287,6 +4287,14 @@ $.when($.ready).then(function () {
|
||||
alert("Something went wrong: ".concat(responseData.responseText.substring(0, 100)));
|
||||
});
|
||||
});
|
||||
// Auto-select the configured default tag on load (tags mode only)
|
||||
var taglist = document.getElementById("taglist");
|
||||
if (taglist !== null) {
|
||||
var defaultTag = taglist.getAttribute("data-default-tag");
|
||||
if (typeof defaultTag === "string" && defaultTag !== "") {
|
||||
$("#taglist .tag[data-tag=\"tag-".concat(defaultTag, "\"]")).trigger("click");
|
||||
}
|
||||
}
|
||||
$("#pinlist").on("click", "a", function (e) {
|
||||
e.preventDefault();
|
||||
var current = $(this);
|
||||
|
||||
@@ -334,6 +334,15 @@ $.when($.ready).then(() => {
|
||||
);
|
||||
});
|
||||
});
|
||||
// Auto-select the configured default tag on load (tags mode only)
|
||||
const taglist = document.getElementById("taglist");
|
||||
if (taglist !== null) {
|
||||
const defaultTag = taglist.getAttribute("data-default-tag");
|
||||
if (typeof defaultTag === "string" && defaultTag !== "") {
|
||||
$(`#taglist .tag[data-tag="tag-${defaultTag}"]`).trigger("click");
|
||||
}
|
||||
}
|
||||
|
||||
$("#pinlist").on("click", "a", function (e) {
|
||||
e.preventDefault();
|
||||
const current = $(this);
|
||||
|
||||
@@ -3,7 +3,7 @@ $treat_tags_as = \App\Setting::fetch('treat_tags_as');
|
||||
?>
|
||||
@if( $treat_tags_as == 'tags')
|
||||
@if($taglist->first())
|
||||
<div id="taglist" class="taglist">
|
||||
<div id="taglist" class="taglist" data-default-tag="{{ \App\Setting::fetch('default_tag') }}">
|
||||
<div class="tag white current" data-tag="all">All</div>
|
||||
@foreach($taglist as $tag)
|
||||
<div class="tag link{{ title_color($tag->colour) }}" style="background-color: {{ $tag->colour }}" data-tag="tag-{{ $tag->tag_url }}">{{ $tag->title }}</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Tests\Feature;
|
||||
|
||||
use App\Item;
|
||||
use App\ItemTag;
|
||||
use App\Setting;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
@@ -80,4 +81,25 @@ class DashTest extends TestCase
|
||||
$response->assertSee('Tag 1');
|
||||
$response->assertSee('Tag 2');
|
||||
}
|
||||
|
||||
public function test_dash_exposes_the_configured_default_tag(): void
|
||||
{
|
||||
$this->seed();
|
||||
|
||||
Setting::where('key', 'treat_tags_as')->update(['value' => 'tags']);
|
||||
Setting::where('key', 'default_tag')->update(['value' => 'home-dashboard']);
|
||||
|
||||
Item::factory()->create([
|
||||
'title' => 'Home',
|
||||
'url' => 'home-dashboard',
|
||||
'type' => 1,
|
||||
'pinned' => 1,
|
||||
'user_id' => 0,
|
||||
]);
|
||||
|
||||
$response = $this->get('/');
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertSee('data-default-tag="home-dashboard"', false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
|
||||
namespace Tests\Unit\database\seeders;
|
||||
|
||||
use App\Item;
|
||||
use App\Setting;
|
||||
use Database\Seeders\SettingsSeeder;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SettingsSeederTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/**
|
||||
* All language keys are defined in all languages based on the en language file.
|
||||
*/
|
||||
@@ -18,4 +23,60 @@ class SettingsSeederTest extends TestCase
|
||||
|
||||
$this->assertTrue(count($languageMap) === count($languageDirectories));
|
||||
}
|
||||
|
||||
public function test_seeds_the_default_tag_setting(): void
|
||||
{
|
||||
$this->seed();
|
||||
|
||||
$setting = Setting::where('key', 'default_tag')->first();
|
||||
|
||||
$this->assertNotNull($setting);
|
||||
$this->assertSame('select', $setting->type);
|
||||
$this->assertSame(4, (int) $setting->group_id);
|
||||
}
|
||||
|
||||
public function test_default_tag_edit_value_lists_all_tags_and_a_none_option(): void
|
||||
{
|
||||
$this->seed();
|
||||
|
||||
Item::factory()->create([
|
||||
'title' => 'Home',
|
||||
'url' => 'home-dashboard',
|
||||
'type' => 1,
|
||||
'pinned' => 1,
|
||||
'user_id' => 0,
|
||||
]);
|
||||
Item::factory()->create([
|
||||
'title' => 'Media',
|
||||
'url' => 'media',
|
||||
'type' => 1,
|
||||
'pinned' => 1,
|
||||
'user_id' => 0,
|
||||
]);
|
||||
// An unpinned tag is not rendered in the dashboard taglist, so it must
|
||||
// not be offered as a default (selecting it would silently do nothing).
|
||||
Item::factory()->create([
|
||||
'title' => 'Archive',
|
||||
'url' => 'archive',
|
||||
'type' => 1,
|
||||
'pinned' => 0,
|
||||
'user_id' => 0,
|
||||
]);
|
||||
|
||||
$setting = Setting::where('key', 'default_tag')->first();
|
||||
$editValue = $setting->edit_value;
|
||||
|
||||
// A "none" option with an empty value, using the shared translation key.
|
||||
$this->assertStringContainsString('<option value="" ', $editValue);
|
||||
$this->assertStringContainsString(__('app.options.none'), $editValue);
|
||||
|
||||
// One option per pinned tag: the slug as the value, the raw title as the label.
|
||||
$this->assertStringContainsString('value="home-dashboard"', $editValue);
|
||||
$this->assertStringContainsString('>Home</option>', $editValue);
|
||||
$this->assertStringContainsString('value="media"', $editValue);
|
||||
$this->assertStringContainsString('>Media</option>', $editValue);
|
||||
|
||||
// The unpinned tag is excluded.
|
||||
$this->assertStringNotContainsString('value="archive"', $editValue);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user