Added important news (#1096)
This commit is contained in:
parent
713f8222e4
commit
6fcb656299
|
@ -20,6 +20,7 @@ class NewsFactory extends Factory
|
||||||
'text' => $this->faker->realText(),
|
'text' => $this->faker->realText(),
|
||||||
'is_meeting' => $this->faker->boolean(),
|
'is_meeting' => $this->faker->boolean(),
|
||||||
'is_pinned' => $this->faker->boolean(.1),
|
'is_pinned' => $this->faker->boolean(.1),
|
||||||
|
'is_important' => $this->faker->boolean(.1),
|
||||||
'user_id' => User::factory(),
|
'user_id' => User::factory(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
|
||||||
|
class AddSetNewsFlagImportantPermissions extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')
|
||||||
|
->insert(['name' => 'news.important', 'description' => 'Make News Important']);
|
||||||
|
|
||||||
|
$newsImportant = $db->table('privileges')
|
||||||
|
->where('name', 'news.important')
|
||||||
|
->get(['id'])
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$buerocrat = 80;
|
||||||
|
$db->table('group_privileges')
|
||||||
|
->insertOrIgnore([
|
||||||
|
['group_id' => $buerocrat, 'privilege_id' => $newsImportant->id],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')
|
||||||
|
->where(['name' => 'news.important'])
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AddIsImportantToNews extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('news', function (Blueprint $table): void {
|
||||||
|
$table->boolean('is_important')->default(false)->after('is_pinned');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('news', function (Blueprint $table): void {
|
||||||
|
$table->dropColumn('is_important');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\News;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\ShiftsFilter;
|
use Engelsystem\ShiftsFilter;
|
||||||
|
|
||||||
|
@ -55,9 +56,14 @@ function public_dashboard_controller()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$important_news = News::whereIsImportant(true)
|
||||||
|
->orderBy('updated_at')
|
||||||
|
->limit(1)
|
||||||
|
->get();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
__('Public Dashboard'),
|
__('Public Dashboard'),
|
||||||
public_dashboard_view($stats, $free_shifts),
|
public_dashboard_view($stats, $free_shifts, $important_news),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,27 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Engelsystem\Models\News;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public dashboard (formerly known as angel news hub)
|
* Public dashboard (formerly known as angel news hub)
|
||||||
*
|
*
|
||||||
* @param array $stats
|
* @param array $stats
|
||||||
* @param array[] $free_shifts
|
* @param array[] $free_shifts
|
||||||
|
* @param News[]|Collection $important_news
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function public_dashboard_view($stats, $free_shifts)
|
function public_dashboard_view($stats, $free_shifts, $important_news)
|
||||||
{
|
{
|
||||||
$needed_angels = '';
|
$needed_angels = '';
|
||||||
|
$news = '';
|
||||||
|
if ($important_news->isNotEmpty()) {
|
||||||
|
$first_news = $important_news->first();
|
||||||
|
$news = div('alert alert-warning text-center', [
|
||||||
|
'<a href="' . url('/news/' . $first_news->id) . '"><strong>' . $first_news->title . '</strong></a>',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
if (count($free_shifts) > 0) {
|
if (count($free_shifts) > 0) {
|
||||||
$shift_panels = [
|
$shift_panels = [
|
||||||
'<div class="row">',
|
'<div class="row">',
|
||||||
|
@ -42,6 +54,7 @@ function public_dashboard_view($stats, $free_shifts)
|
||||||
stats(__('Angels currently working'), $stats['angels-working'], 'default'),
|
stats(__('Angels currently working'), $stats['angels-working'], 'default'),
|
||||||
stats(__('Hours to be worked'), $stats['hours-to-work'], 'default'),
|
stats(__('Hours to be worked'), $stats['hours-to-work'], 'default'),
|
||||||
], 'statistics'),
|
], 'statistics'),
|
||||||
|
$news,
|
||||||
$needed_angels,
|
$needed_angels,
|
||||||
], 'public-dashboard'),
|
], 'public-dashboard'),
|
||||||
]),
|
]),
|
||||||
|
|
|
@ -137,6 +137,10 @@ table a > .icon-icon_angel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.public-dashboard .alert a {
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.dashboard-card {
|
.dashboard-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
|
|
@ -2910,6 +2910,9 @@ msgstr "+"
|
||||||
msgid "news.is_meeting"
|
msgid "news.is_meeting"
|
||||||
msgstr "[Treffen]"
|
msgstr "[Treffen]"
|
||||||
|
|
||||||
|
msgid "news.edit.is_important"
|
||||||
|
msgstr "Wichtig"
|
||||||
|
|
||||||
msgid "news.read_more"
|
msgid "news.read_more"
|
||||||
msgstr "Weiterlesen"
|
msgstr "Weiterlesen"
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,9 @@ msgstr "Subject"
|
||||||
msgid "news.edit.is_meeting"
|
msgid "news.edit.is_meeting"
|
||||||
msgstr "Meeting"
|
msgstr "Meeting"
|
||||||
|
|
||||||
|
msgid "news.edit.is_important"
|
||||||
|
msgstr "Important"
|
||||||
|
|
||||||
msgid "news.edit.is_pinned"
|
msgid "news.edit.is_pinned"
|
||||||
msgstr "Pin to top"
|
msgstr "Pin to top"
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
{{ f.checkbox('is_meeting', __('news.edit.is_meeting'), is_meeting) }}
|
{{ f.checkbox('is_meeting', __('news.edit.is_meeting'), is_meeting) }}
|
||||||
{{ f.checkbox('is_pinned', __('news.edit.is_pinned'), is_pinned) }}
|
{{ f.checkbox('is_pinned', __('news.edit.is_pinned'), is_pinned) }}
|
||||||
|
{% if has_permission_to('news.important') %} {{ f.checkbox('is_important', __('news.edit.is_important'), is_important) }}{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<h2>{{ __('form.preview') }}</h2>
|
<h2>{{ __('form.preview') }}</h2>
|
||||||
|
|
||||||
<div class="card {% if news.is_meeting %}bg-info{% else %}{% if theme.type =='light' %}bg-light{% else %}bg-secondary{% endif %}{% endif %} mb-4">
|
<div class="card {% if news.is_important %}bg-warning{% elseif news.is_meeting %}bg-info{% elseif theme.type =='light' %}bg-light{% else %}bg-secondary{% endif %} mb-4">
|
||||||
<div class="card-header {% if news.is_meeting and theme.type == 'dark' %}text-white{% endif %}">
|
<div class="card-header {% if news.is_meeting and theme.type == 'dark' %}text-white{% endif %}">
|
||||||
{% if news.is_meeting %}{{ __('news.is_meeting') }}{% endif %}
|
{% if news.is_meeting %}{{ __('news.is_meeting') }}{% endif %}
|
||||||
{{ news.title }}
|
{{ news.title }}
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% macro news(news, show_comments_link, is_overview) %}
|
{% macro news(news, show_comments_link, is_overview) %}
|
||||||
<div class="card {% if news.is_meeting %}bg-info{% else %}{% if theme.type =='light' %}bg-light{% else %}bg-dark{% endif %}{% endif %} mb-4">
|
<div class="card {% if news.is_important %}bg-warning{% elseif news.is_meeting %}bg-info{% elseif theme.type =='light' %}bg-light{% else %}bg-dark{% endif %} mb-4">
|
||||||
{% if is_overview|default(false) %}
|
{% if is_overview|default(false) %}
|
||||||
<div class="card-header {% if news.is_meeting and theme.type == 'dark' %}text-white{% endif %}">
|
<div class="card-header {% if news.is_meeting and theme.type == 'dark' %}text-white{% endif %}">
|
||||||
<a href="{{ url('news/' ~ news.id) }}" class="text-inherit">
|
<a href="{{ url('news/' ~ news.id) }}" class="text-inherit">
|
||||||
|
|
|
@ -49,6 +49,7 @@ class NewsController extends BaseController
|
||||||
'news' => $news,
|
'news' => $news,
|
||||||
'is_meeting' => $news ? $news->is_meeting : $isMeetingDefault,
|
'is_meeting' => $news ? $news->is_meeting : $isMeetingDefault,
|
||||||
'is_pinned' => $news ? $news->is_pinned : false,
|
'is_pinned' => $news ? $news->is_pinned : false,
|
||||||
|
'is_important' => $news ? $news->is_important : false,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -65,6 +66,7 @@ class NewsController extends BaseController
|
||||||
'text' => 'required',
|
'text' => 'required',
|
||||||
'is_meeting' => 'optional|checked',
|
'is_meeting' => 'optional|checked',
|
||||||
'is_pinned' => 'optional|checked',
|
'is_pinned' => 'optional|checked',
|
||||||
|
'is_important' => 'optional|checked',
|
||||||
'delete' => 'optional|checked',
|
'delete' => 'optional|checked',
|
||||||
'preview' => 'optional|checked',
|
'preview' => 'optional|checked',
|
||||||
]);
|
]);
|
||||||
|
@ -93,6 +95,10 @@ class NewsController extends BaseController
|
||||||
$news->is_meeting = !is_null($data['is_meeting']);
|
$news->is_meeting = !is_null($data['is_meeting']);
|
||||||
$news->is_pinned = !is_null($data['is_pinned']);
|
$news->is_pinned = !is_null($data['is_pinned']);
|
||||||
|
|
||||||
|
if ($this->auth->can('news.important')) {
|
||||||
|
$news->is_important = !is_null($data['is_important']);
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_null($data['preview'])) {
|
if (!is_null($data['preview'])) {
|
||||||
return $this->showEdit($news);
|
return $this->showEdit($news);
|
||||||
}
|
}
|
||||||
|
@ -108,6 +114,7 @@ class NewsController extends BaseController
|
||||||
'Updated {pinned}{type} "{news}": {text}',
|
'Updated {pinned}{type} "{news}": {text}',
|
||||||
[
|
[
|
||||||
'pinned' => $news->is_pinned ? 'pinned ' : '',
|
'pinned' => $news->is_pinned ? 'pinned ' : '',
|
||||||
|
'important' => $news->is_important ? 'important ' : '',
|
||||||
'type' => $news->is_meeting ? 'meeting' : 'news',
|
'type' => $news->is_meeting ? 'meeting' : 'news',
|
||||||
'news' => $news->title,
|
'news' => $news->title,
|
||||||
'text' => $news->text,
|
'text' => $news->text,
|
||||||
|
|
|
@ -134,6 +134,7 @@ class NewsController extends BaseController
|
||||||
->with('user')
|
->with('user')
|
||||||
->withCount('comments')
|
->withCount('comments')
|
||||||
->orderByDesc('is_pinned')
|
->orderByDesc('is_pinned')
|
||||||
|
->orderByDesc('is_important')
|
||||||
->orderByDesc('updated_at')
|
->orderByDesc('updated_at')
|
||||||
->limit($perPage)
|
->limit($perPage)
|
||||||
->offset(($page - 1) * $perPage)
|
->offset(($page - 1) * $perPage)
|
||||||
|
|
|
@ -18,19 +18,21 @@ use Illuminate\Support\Str;
|
||||||
* @property string $text
|
* @property string $text
|
||||||
* @property bool $is_meeting
|
* @property bool $is_meeting
|
||||||
* @property bool $is_pinned
|
* @property bool $is_pinned
|
||||||
|
* @property bool $is_important
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
*
|
*
|
||||||
* @property-read Collection|NewsComment[] $comments
|
* @property-read Collection|NewsComment[] $comments
|
||||||
* @property-read int|null $comments_count
|
* @property-read int|null $comments_count
|
||||||
*
|
*
|
||||||
* @method static QueryBuilder|LogEntry[] whereId($value)
|
* @method static QueryBuilder|News[] whereId($value)
|
||||||
* @method static QueryBuilder|LogEntry[] whereTitle($value)
|
* @method static QueryBuilder|News[] whereTitle($value)
|
||||||
* @method static QueryBuilder|LogEntry[] whereText($value)
|
* @method static QueryBuilder|News[] whereText($value)
|
||||||
* @method static QueryBuilder|LogEntry[] whereIsMeeting($value)
|
* @method static QueryBuilder|News[] whereIsMeeting($value)
|
||||||
* @method static QueryBuilder|LogEntry[] whereIsPinned($value)
|
* @method static QueryBuilder|News[] whereIsPinned($value)
|
||||||
* @method static QueryBuilder|LogEntry[] whereCreatedAt($value)
|
* @method static QueryBuilder|News[] whereIsImportant($value)
|
||||||
* @method static QueryBuilder|LogEntry[] whereUpdatedAt($value)
|
* @method static QueryBuilder|News[] whereCreatedAt($value)
|
||||||
|
* @method static QueryBuilder|News[] whereUpdatedAt($value)
|
||||||
*/
|
*/
|
||||||
class News extends BaseModel
|
class News extends BaseModel
|
||||||
{
|
{
|
||||||
|
@ -45,12 +47,14 @@ class News extends BaseModel
|
||||||
'user_id' => 'integer',
|
'user_id' => 'integer',
|
||||||
'is_meeting' => 'boolean',
|
'is_meeting' => 'boolean',
|
||||||
'is_pinned' => 'boolean',
|
'is_pinned' => 'boolean',
|
||||||
|
'is_important' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var array<string, bool> Default attributes */
|
/** @var array<string, bool> Default attributes */
|
||||||
protected $attributes = [ // phpcs:ignore
|
protected $attributes = [ // phpcs:ignore
|
||||||
'is_meeting' => false,
|
'is_meeting' => false,
|
||||||
'is_pinned' => false,
|
'is_pinned' => false,
|
||||||
|
'is_important' => false,
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var array<string> */
|
/** @var array<string> */
|
||||||
|
@ -59,6 +63,7 @@ class News extends BaseModel
|
||||||
'text',
|
'text',
|
||||||
'is_meeting',
|
'is_meeting',
|
||||||
'is_pinned',
|
'is_pinned',
|
||||||
|
'is_important',
|
||||||
'user_id',
|
'user_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,10 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||||
* @property-read AngelType $angelType
|
* @property-read AngelType $angelType
|
||||||
* @property-read User $confirmUser
|
* @property-read User $confirmUser
|
||||||
*
|
*
|
||||||
* @method static QueryBuilder|AngelType[] whereId($value)
|
* @method static QueryBuilder|UserAngelType[] whereId($value)
|
||||||
* @method static QueryBuilder|AngelType[] whereAngelTypeId($value)
|
* @method static QueryBuilder|UserAngelType[] whereAngelTypeId($value)
|
||||||
* @method static QueryBuilder|AngelType[] whereConfirmUserId($value)
|
* @method static QueryBuilder|UserAngelType[] whereConfirmUserId($value)
|
||||||
* @method static QueryBuilder|AngelType[] whereSupporter($value)
|
* @method static QueryBuilder|UserAngelType[] whereSupporter($value)
|
||||||
*/
|
*/
|
||||||
class UserAngelType extends Pivot
|
class UserAngelType extends Pivot
|
||||||
{
|
{
|
||||||
|
|
|
@ -162,6 +162,7 @@ class NewsControllerTest extends ControllerTest
|
||||||
'text' => 'New text',
|
'text' => 'New text',
|
||||||
'is_meeting' => '1',
|
'is_meeting' => '1',
|
||||||
'is_pinned' => '1',
|
'is_pinned' => '1',
|
||||||
|
'is_important' => '1',
|
||||||
'preview' => '1',
|
'preview' => '1',
|
||||||
]);
|
]);
|
||||||
$this->response->expects($this->once())
|
$this->response->expects($this->once())
|
||||||
|
@ -174,11 +175,16 @@ class NewsControllerTest extends ControllerTest
|
||||||
// Contains new text
|
// Contains new text
|
||||||
$this->assertTrue($news->is_meeting);
|
$this->assertTrue($news->is_meeting);
|
||||||
$this->assertTrue($news->is_pinned);
|
$this->assertTrue($news->is_pinned);
|
||||||
|
$this->assertTrue($news->is_important);
|
||||||
$this->assertEquals('New title', $news->title);
|
$this->assertEquals('New title', $news->title);
|
||||||
$this->assertEquals('New text', $news->text);
|
$this->assertEquals('New text', $news->text);
|
||||||
|
|
||||||
return $this->response;
|
return $this->response;
|
||||||
});
|
});
|
||||||
|
$this->auth->expects($this->atLeastOnce())
|
||||||
|
->method('can')
|
||||||
|
->with('news.important')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
/** @var NewsController $controller */
|
/** @var NewsController $controller */
|
||||||
$controller = $this->app->make(NewsController::class);
|
$controller = $this->app->make(NewsController::class);
|
||||||
|
@ -192,6 +198,7 @@ class NewsControllerTest extends ControllerTest
|
||||||
$this->assertEquals('**foo**', $news->text);
|
$this->assertEquals('**foo**', $news->text);
|
||||||
$this->assertFalse($news->is_meeting);
|
$this->assertFalse($news->is_meeting);
|
||||||
$this->assertFalse($news->is_pinned);
|
$this->assertFalse($news->is_pinned);
|
||||||
|
$this->assertFalse($news->is_important);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -43,6 +43,7 @@ class NewsControllerTest extends ControllerTest
|
||||||
'text' => 'baz',
|
'text' => 'baz',
|
||||||
'is_meeting' => true,
|
'is_meeting' => true,
|
||||||
'is_pinned' => true,
|
'is_pinned' => true,
|
||||||
|
'is_important' => true,
|
||||||
'user_id' => 1,
|
'user_id' => 1,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
|
@ -28,7 +28,7 @@ class PrivilegeTest extends ModelTest
|
||||||
$model->groups()->attach($group2);
|
$model->groups()->attach($group2);
|
||||||
|
|
||||||
/** @var Privilege $savedModel */
|
/** @var Privilege $savedModel */
|
||||||
$savedModel = Privilege::first();
|
$savedModel = Privilege::whereName('Some Privilege')->first();
|
||||||
$this->assertEquals('Some Privilege', $savedModel->name);
|
$this->assertEquals('Some Privilege', $savedModel->name);
|
||||||
$this->assertEquals('Some long description', $savedModel->description);
|
$this->assertEquals('Some long description', $savedModel->description);
|
||||||
$this->assertEquals($group1->name, $savedModel->groups[0]->name);
|
$this->assertEquals($group1->name, $savedModel->groups[0]->name);
|
||||||
|
|
Loading…
Reference in New Issue