From 6fcb6562993ea4001bc0bf01d26550b99d1e979b Mon Sep 17 00:00:00 2001 From: xuwhite <73076134+xuwhite@users.noreply.github.com> Date: Mon, 13 Feb 2023 21:19:45 +0100 Subject: [PATCH] Added important news (#1096) --- db/factories/NewsFactory.php | 11 ++--- ...dd_set_news_flag_important_permissions.php | 42 +++++++++++++++++++ ..._02_06_000000_add_is_important_to_news.php | 31 ++++++++++++++ .../public_dashboard_controller.php | 8 +++- includes/view/PublicDashboard_view.php | 19 +++++++-- resources/assets/themes/base.scss | 4 ++ resources/lang/de_DE/default.po | 3 ++ resources/lang/en_US/default.po | 3 ++ resources/views/pages/news/edit.twig | 3 +- resources/views/pages/news/overview.twig | 2 +- src/Controllers/Admin/NewsController.php | 33 +++++++++------ src/Controllers/NewsController.php | 1 + src/Models/News.php | 29 +++++++------ src/Models/UserAngelType.php | 8 ++-- .../Controllers/Admin/NewsControllerTest.php | 17 +++++--- tests/Unit/Controllers/NewsControllerTest.php | 11 ++--- tests/Unit/Models/PrivilegeTest.php | 2 +- 17 files changed, 176 insertions(+), 51 deletions(-) create mode 100644 db/migrations/2023_02_03_000000_add_set_news_flag_important_permissions.php create mode 100644 db/migrations/2023_02_06_000000_add_is_important_to_news.php diff --git a/db/factories/NewsFactory.php b/db/factories/NewsFactory.php index ae1c54b2..54b39d36 100644 --- a/db/factories/NewsFactory.php +++ b/db/factories/NewsFactory.php @@ -16,11 +16,12 @@ class NewsFactory extends Factory public function definition(): array { return [ - 'title' => $this->faker->text(50), - 'text' => $this->faker->realText(), - 'is_meeting' => $this->faker->boolean(), - 'is_pinned' => $this->faker->boolean(.1), - 'user_id' => User::factory(), + 'title' => $this->faker->text(50), + 'text' => $this->faker->realText(), + 'is_meeting' => $this->faker->boolean(), + 'is_pinned' => $this->faker->boolean(.1), + 'is_important' => $this->faker->boolean(.1), + 'user_id' => User::factory(), ]; } } diff --git a/db/migrations/2023_02_03_000000_add_set_news_flag_important_permissions.php b/db/migrations/2023_02_03_000000_add_set_news_flag_important_permissions.php new file mode 100644 index 00000000..f75747a5 --- /dev/null +++ b/db/migrations/2023_02_03_000000_add_set_news_flag_important_permissions.php @@ -0,0 +1,42 @@ +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(); + } +} diff --git a/db/migrations/2023_02_06_000000_add_is_important_to_news.php b/db/migrations/2023_02_06_000000_add_is_important_to_news.php new file mode 100644 index 00000000..1d280efb --- /dev/null +++ b/db/migrations/2023_02_06_000000_add_is_important_to_news.php @@ -0,0 +1,31 @@ +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'); + }); + } +} diff --git a/includes/controller/public_dashboard_controller.php b/includes/controller/public_dashboard_controller.php index 114a5fd3..47476262 100644 --- a/includes/controller/public_dashboard_controller.php +++ b/includes/controller/public_dashboard_controller.php @@ -1,6 +1,7 @@ orderBy('updated_at') + ->limit(1) + ->get(); + return [ __('Public Dashboard'), - public_dashboard_view($stats, $free_shifts), + public_dashboard_view($stats, $free_shifts, $important_news), ]; } diff --git a/includes/view/PublicDashboard_view.php b/includes/view/PublicDashboard_view.php index eaadb0e2..29837176 100644 --- a/includes/view/PublicDashboard_view.php +++ b/includes/view/PublicDashboard_view.php @@ -1,15 +1,27 @@ isNotEmpty()) { + $first_news = $important_news->first(); + $news = div('alert alert-warning text-center', [ + '' . $first_news->title . '', + ]); + } + if (count($free_shifts) > 0) { $shift_panels = [ '
', @@ -42,6 +54,7 @@ function public_dashboard_view($stats, $free_shifts) stats(__('Angels currently working'), $stats['angels-working'], 'default'), stats(__('Hours to be worked'), $stats['hours-to-work'], 'default'), ], 'statistics'), + $news, $needed_angels, ], 'public-dashboard'), ]), diff --git a/resources/assets/themes/base.scss b/resources/assets/themes/base.scss index 8b7e6ec4..636719be 100644 --- a/resources/assets/themes/base.scss +++ b/resources/assets/themes/base.scss @@ -137,6 +137,10 @@ table a > .icon-icon_angel { } } +.public-dashboard .alert a { + text-decoration: inherit; +} + .dashboard-card { position: relative; font-size: 20px; diff --git a/resources/lang/de_DE/default.po b/resources/lang/de_DE/default.po index c71b4946..11360467 100644 --- a/resources/lang/de_DE/default.po +++ b/resources/lang/de_DE/default.po @@ -2910,6 +2910,9 @@ msgstr "+" msgid "news.is_meeting" msgstr "[Treffen]" +msgid "news.edit.is_important" +msgstr "Wichtig" + msgid "news.read_more" msgstr "Weiterlesen" diff --git a/resources/lang/en_US/default.po b/resources/lang/en_US/default.po index 7417fdc2..07663f04 100644 --- a/resources/lang/en_US/default.po +++ b/resources/lang/en_US/default.po @@ -187,6 +187,9 @@ msgstr "Subject" msgid "news.edit.is_meeting" msgstr "Meeting" +msgid "news.edit.is_important" +msgstr "Important" + msgid "news.edit.is_pinned" msgstr "Pin to top" diff --git a/resources/views/pages/news/edit.twig b/resources/views/pages/news/edit.twig index 6fd1617c..3ca73e7a 100644 --- a/resources/views/pages/news/edit.twig +++ b/resources/views/pages/news/edit.twig @@ -43,6 +43,7 @@
{{ f.checkbox('is_meeting', __('news.edit.is_meeting'), is_meeting) }} {{ 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 %}
@@ -67,7 +68,7 @@

{{ __('form.preview') }}

-
+
{% if news.is_meeting %}{{ __('news.is_meeting') }}{% endif %} {{ news.title }} diff --git a/resources/views/pages/news/overview.twig b/resources/views/pages/news/overview.twig index 1f8b6372..be8961e3 100644 --- a/resources/views/pages/news/overview.twig +++ b/resources/views/pages/news/overview.twig @@ -48,7 +48,7 @@ {% endblock %} {% macro news(news, show_comments_link, is_overview) %} -
+
{% if is_overview|default(false) %}
diff --git a/src/Controllers/Admin/NewsController.php b/src/Controllers/Admin/NewsController.php index 19adac9f..848b259d 100644 --- a/src/Controllers/Admin/NewsController.php +++ b/src/Controllers/Admin/NewsController.php @@ -46,9 +46,10 @@ class NewsController extends BaseController return $this->response->withView( 'pages/news/edit.twig', [ - 'news' => $news, - 'is_meeting' => $news ? $news->is_meeting : $isMeetingDefault, - 'is_pinned' => $news ? $news->is_pinned : false, + 'news' => $news, + 'is_meeting' => $news ? $news->is_meeting : $isMeetingDefault, + 'is_pinned' => $news ? $news->is_pinned : false, + 'is_important' => $news ? $news->is_important : false, ], ); } @@ -61,12 +62,13 @@ class NewsController extends BaseController $news = $this->news->findOrNew($newsId); $data = $this->validate($request, [ - 'title' => 'required', - 'text' => 'required', - 'is_meeting' => 'optional|checked', - 'is_pinned' => 'optional|checked', - 'delete' => 'optional|checked', - 'preview' => 'optional|checked', + 'title' => 'required', + 'text' => 'required', + 'is_meeting' => 'optional|checked', + 'is_pinned' => 'optional|checked', + 'is_important' => 'optional|checked', + 'delete' => 'optional|checked', + 'preview' => 'optional|checked', ]); if (!is_null($data['delete'])) { @@ -93,6 +95,10 @@ class NewsController extends BaseController $news->is_meeting = !is_null($data['is_meeting']); $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'])) { return $this->showEdit($news); } @@ -107,10 +113,11 @@ class NewsController extends BaseController $this->log->info( 'Updated {pinned}{type} "{news}": {text}', [ - 'pinned' => $news->is_pinned ? 'pinned ' : '', - 'type' => $news->is_meeting ? 'meeting' : 'news', - 'news' => $news->title, - 'text' => $news->text, + 'pinned' => $news->is_pinned ? 'pinned ' : '', + 'important' => $news->is_important ? 'important ' : '', + 'type' => $news->is_meeting ? 'meeting' : 'news', + 'news' => $news->title, + 'text' => $news->text, ] ); diff --git a/src/Controllers/NewsController.php b/src/Controllers/NewsController.php index 5dfb1828..c2c35761 100644 --- a/src/Controllers/NewsController.php +++ b/src/Controllers/NewsController.php @@ -134,6 +134,7 @@ class NewsController extends BaseController ->with('user') ->withCount('comments') ->orderByDesc('is_pinned') + ->orderByDesc('is_important') ->orderByDesc('updated_at') ->limit($perPage) ->offset(($page - 1) * $perPage) diff --git a/src/Models/News.php b/src/Models/News.php index d0bf3a43..0bcd42dc 100644 --- a/src/Models/News.php +++ b/src/Models/News.php @@ -18,19 +18,21 @@ use Illuminate\Support\Str; * @property string $text * @property bool $is_meeting * @property bool $is_pinned + * @property bool $is_important * @property Carbon|null $created_at * @property Carbon|null $updated_at * * @property-read Collection|NewsComment[] $comments * @property-read int|null $comments_count * - * @method static QueryBuilder|LogEntry[] whereId($value) - * @method static QueryBuilder|LogEntry[] whereTitle($value) - * @method static QueryBuilder|LogEntry[] whereText($value) - * @method static QueryBuilder|LogEntry[] whereIsMeeting($value) - * @method static QueryBuilder|LogEntry[] whereIsPinned($value) - * @method static QueryBuilder|LogEntry[] whereCreatedAt($value) - * @method static QueryBuilder|LogEntry[] whereUpdatedAt($value) + * @method static QueryBuilder|News[] whereId($value) + * @method static QueryBuilder|News[] whereTitle($value) + * @method static QueryBuilder|News[] whereText($value) + * @method static QueryBuilder|News[] whereIsMeeting($value) + * @method static QueryBuilder|News[] whereIsPinned($value) + * @method static QueryBuilder|News[] whereIsImportant($value) + * @method static QueryBuilder|News[] whereCreatedAt($value) + * @method static QueryBuilder|News[] whereUpdatedAt($value) */ class News extends BaseModel { @@ -42,15 +44,17 @@ class News extends BaseModel /** @var array */ protected $casts = [ // phpcs:ignore - 'user_id' => 'integer', - 'is_meeting' => 'boolean', - 'is_pinned' => 'boolean', + 'user_id' => 'integer', + 'is_meeting' => 'boolean', + 'is_pinned' => 'boolean', + 'is_important' => 'boolean', ]; /** @var array Default attributes */ protected $attributes = [ // phpcs:ignore - 'is_meeting' => false, - 'is_pinned' => false, + 'is_meeting' => false, + 'is_pinned' => false, + 'is_important' => false, ]; /** @var array */ @@ -59,6 +63,7 @@ class News extends BaseModel 'text', 'is_meeting', 'is_pinned', + 'is_important', 'user_id', ]; diff --git a/src/Models/UserAngelType.php b/src/Models/UserAngelType.php index 556a0a19..83fcbecd 100644 --- a/src/Models/UserAngelType.php +++ b/src/Models/UserAngelType.php @@ -23,10 +23,10 @@ use Illuminate\Database\Query\Builder as QueryBuilder; * @property-read AngelType $angelType * @property-read User $confirmUser * - * @method static QueryBuilder|AngelType[] whereId($value) - * @method static QueryBuilder|AngelType[] whereAngelTypeId($value) - * @method static QueryBuilder|AngelType[] whereConfirmUserId($value) - * @method static QueryBuilder|AngelType[] whereSupporter($value) + * @method static QueryBuilder|UserAngelType[] whereId($value) + * @method static QueryBuilder|UserAngelType[] whereAngelTypeId($value) + * @method static QueryBuilder|UserAngelType[] whereConfirmUserId($value) + * @method static QueryBuilder|UserAngelType[] whereSupporter($value) */ class UserAngelType extends Pivot { diff --git a/tests/Unit/Controllers/Admin/NewsControllerTest.php b/tests/Unit/Controllers/Admin/NewsControllerTest.php index 6b236b24..3943aa14 100644 --- a/tests/Unit/Controllers/Admin/NewsControllerTest.php +++ b/tests/Unit/Controllers/Admin/NewsControllerTest.php @@ -158,11 +158,12 @@ class NewsControllerTest extends ControllerTest { $this->request->attributes->set('news_id', 1); $this->request = $this->request->withParsedBody([ - 'title' => 'New title', - 'text' => 'New text', - 'is_meeting' => '1', - 'is_pinned' => '1', - 'preview' => '1', + 'title' => 'New title', + 'text' => 'New text', + 'is_meeting' => '1', + 'is_pinned' => '1', + 'is_important' => '1', + 'preview' => '1', ]); $this->response->expects($this->once()) ->method('withView') @@ -174,11 +175,16 @@ class NewsControllerTest extends ControllerTest // Contains new text $this->assertTrue($news->is_meeting); $this->assertTrue($news->is_pinned); + $this->assertTrue($news->is_important); $this->assertEquals('New title', $news->title); $this->assertEquals('New text', $news->text); return $this->response; }); + $this->auth->expects($this->atLeastOnce()) + ->method('can') + ->with('news.important') + ->willReturn(true); /** @var NewsController $controller */ $controller = $this->app->make(NewsController::class); @@ -192,6 +198,7 @@ class NewsControllerTest extends ControllerTest $this->assertEquals('**foo**', $news->text); $this->assertFalse($news->is_meeting); $this->assertFalse($news->is_pinned); + $this->assertFalse($news->is_important); } /** diff --git a/tests/Unit/Controllers/NewsControllerTest.php b/tests/Unit/Controllers/NewsControllerTest.php index bf3e5a5a..329a68a0 100644 --- a/tests/Unit/Controllers/NewsControllerTest.php +++ b/tests/Unit/Controllers/NewsControllerTest.php @@ -39,11 +39,12 @@ class NewsControllerTest extends ControllerTest 'user_id' => 1, ], [ - 'title' => 'baz', - 'text' => 'baz', - 'is_meeting' => true, - 'is_pinned' => true, - 'user_id' => 1, + 'title' => 'baz', + 'text' => 'baz', + 'is_meeting' => true, + 'is_pinned' => true, + 'is_important' => true, + 'user_id' => 1, ], [ 'title' => 'Lorem', diff --git a/tests/Unit/Models/PrivilegeTest.php b/tests/Unit/Models/PrivilegeTest.php index 4805a1d5..7a3b4c4a 100644 --- a/tests/Unit/Models/PrivilegeTest.php +++ b/tests/Unit/Models/PrivilegeTest.php @@ -28,7 +28,7 @@ class PrivilegeTest extends ModelTest $model->groups()->attach($group2); /** @var Privilege $savedModel */ - $savedModel = Privilege::first(); + $savedModel = Privilege::whereName('Some Privilege')->first(); $this->assertEquals('Some Privilege', $savedModel->name); $this->assertEquals('Some long description', $savedModel->description); $this->assertEquals($group1->name, $savedModel->groups[0]->name);