diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php
index 80d096fb9..642e6d220 100644
--- a/app/Http/Controllers/AdminController.php
+++ b/app/Http/Controllers/AdminController.php
@@ -9,6 +9,7 @@ use App\{
Instance,
Media,
Like,
+ Newsroom,
OauthClient,
Profile,
Report,
@@ -258,4 +259,153 @@ class AdminController extends Controller
$message->save();
return;
}
+
+ public function newsroomHome(Request $request)
+ {
+ $newsroom = Newsroom::latest()->paginate(10);
+ return view('admin.newsroom.home', compact('newsroom'));
+ }
+
+ public function newsroomCreate(Request $request)
+ {
+ return view('admin.newsroom.create');
+ }
+
+ public function newsroomEdit(Request $request, $id)
+ {
+ $news = Newsroom::findOrFail($id);
+ return view('admin.newsroom.edit', compact('news'));
+ }
+
+ public function newsroomDelete(Request $request, $id)
+ {
+ $news = Newsroom::findOrFail($id);
+ $news->delete();
+ return redirect('/i/admin/newsroom');
+ }
+
+ public function newsroomUpdate(Request $request, $id)
+ {
+ $this->validate($request, [
+ 'title' => 'required|string|min:1|max:100',
+ 'summary' => 'nullable|string|max:200',
+ 'body' => 'nullable|string'
+ ]);
+ $changed = false;
+ $changedFields = [];
+ $news = Newsroom::findOrFail($id);
+ $fields = [
+ 'title' => 'string',
+ 'summary' => 'string',
+ 'body' => 'string',
+ 'category' => 'string',
+ 'show_timeline' => 'boolean',
+ 'auth_only' => 'boolean',
+ 'show_link' => 'boolean',
+ 'force_modal' => 'boolean',
+ 'published' => 'published'
+ ];
+ foreach($fields as $field => $type) {
+ switch ($type) {
+ case 'string':
+ if($request->{$field} != $news->{$field}) {
+ if($field == 'title') {
+ $news->slug = str_slug($request->{$field});
+ }
+ $news->{$field} = $request->{$field};
+ $changed = true;
+ array_push($changedFields, $field);
+ }
+ break;
+
+ case 'boolean':
+ $state = $request->{$field} == 'on' ? true : false;
+ if($state != $news->{$field}) {
+ $news->{$field} = $state;
+ $changed = true;
+ array_push($changedFields, $field);
+ }
+ break;
+ case 'published':
+ $state = $request->{$field} == 'on' ? true : false;
+ $published = $news->published_at != null;
+ if($state != $published) {
+ $news->published_at = $state ? now() : null;
+ $changed = true;
+ array_push($changedFields, $field);
+ }
+ break;
+
+ }
+ }
+
+ if($changed) {
+ $news->save();
+ }
+ $redirect = $news->published_at ? $news->permalink() : $news->editUrl();
+ return redirect($redirect);
+ }
+
+
+ public function newsroomStore(Request $request)
+ {
+ $this->validate($request, [
+ 'title' => 'required|string|min:1|max:100',
+ 'summary' => 'nullable|string|max:200',
+ 'body' => 'nullable|string'
+ ]);
+ $changed = false;
+ $changedFields = [];
+ $news = new Newsroom();
+ $fields = [
+ 'title' => 'string',
+ 'summary' => 'string',
+ 'body' => 'string',
+ 'category' => 'string',
+ 'show_timeline' => 'boolean',
+ 'auth_only' => 'boolean',
+ 'show_link' => 'boolean',
+ 'force_modal' => 'boolean',
+ 'published' => 'published'
+ ];
+ foreach($fields as $field => $type) {
+ switch ($type) {
+ case 'string':
+ if($request->{$field} != $news->{$field}) {
+ if($field == 'title') {
+ $news->slug = str_slug($request->{$field});
+ }
+ $news->{$field} = $request->{$field};
+ $changed = true;
+ array_push($changedFields, $field);
+ }
+ break;
+
+ case 'boolean':
+ $state = $request->{$field} == 'on' ? true : false;
+ if($state != $news->{$field}) {
+ $news->{$field} = $state;
+ $changed = true;
+ array_push($changedFields, $field);
+ }
+ break;
+ case 'published':
+ $state = $request->{$field} == 'on' ? true : false;
+ $published = $news->published_at != null;
+ if($state != $published) {
+ $news->published_at = $state ? now() : null;
+ $changed = true;
+ array_push($changedFields, $field);
+ }
+ break;
+
+ }
+ }
+
+ if($changed) {
+ $news->save();
+ }
+ $redirect = $news->published_at ? $news->permalink() : $news->editUrl();
+ return redirect($redirect);
+ }
}
diff --git a/app/Http/Controllers/NewsroomController.php b/app/Http/Controllers/NewsroomController.php
new file mode 100644
index 000000000..7c2f7adbc
--- /dev/null
+++ b/app/Http/Controllers/NewsroomController.php
@@ -0,0 +1,94 @@
+latest()->paginate(9);
+ } else {
+ $posts = Newsroom::whereNotNull('published_at')
+ ->whereAuthOnly(false)
+ ->latest()
+ ->paginate(3);
+ }
+ return view('site.news.home', compact('posts'));
+ }
+
+ public function show(Request $request, $year, $month, $slug)
+ {
+ $post = Newsroom::whereNotNull('published_at')
+ ->whereSlug($slug)
+ ->whereYear('published_at', $year)
+ ->whereMonth('published_at', $month)
+ ->firstOrFail();
+ abort_if($post->auth_only && !$request->user(), 404);
+ return view('site.news.post.show', compact('post'));
+ }
+
+ public function search(Request $request)
+ {
+ abort(404);
+ $this->validate($request, [
+ 'q' => 'nullable'
+ ]);
+ }
+
+ public function archive(Request $request)
+ {
+ abort(404);
+ return view('site.news.archive.index');
+ }
+
+ public function timelineApi(Request $request)
+ {
+ abort_if(!Auth::check(), 404);
+
+ $key = 'newsroom:read:profileid:' . $request->user()->profile_id;
+ $read = Redis::smembers($key);
+
+ $posts = Newsroom::whereNotNull('published_at')
+ ->whereShowTimeline(true)
+ ->whereNotIn('id', $read)
+ ->orderBy('id', 'desc')
+ ->take(9)
+ ->get()
+ ->map(function($post) {
+ return [
+ 'id' => $post->id,
+ 'title' => Str::limit($post->title, 25),
+ 'summary' => $post->summary,
+ 'url' => $post->show_link ? $post->permalink() : null,
+ 'published_at' => $post->published_at->format('F m, Y')
+ ];
+ });
+ return response()->json($posts, 200, [], JSON_PRETTY_PRINT);
+ }
+
+ public function markAsRead(Request $request)
+ {
+ abort_if(!Auth::check(), 404);
+
+ $this->validate($request, [
+ 'id' => 'required|integer|min:1'
+ ]);
+
+ $news = Newsroom::whereNotNull('published_at')
+ ->findOrFail($request->input('id'));
+
+ $key = 'newsroom:read:profileid:' . $request->user()->profile_id;
+
+ Redis::sadd($key, $news->id);
+
+ return response()->json(['code' => 200]);
+ }
+}
diff --git a/app/Newsroom.php b/app/Newsroom.php
new file mode 100644
index 000000000..eca57eafc
--- /dev/null
+++ b/app/Newsroom.php
@@ -0,0 +1,27 @@
+published_at->year;
+ $month = $this->published_at->format('m');
+ $slug = $this->slug;
+
+ return url("/site/newsroom/{$year}/{$month}/{$slug}");
+ }
+
+ public function editUrl()
+ {
+ return url("/i/admin/newsroom/edit/{$this->id}");
+ }
+}
diff --git a/database/migrations/2019_12_10_023604_create_newsroom_table.php b/database/migrations/2019_12_10_023604_create_newsroom_table.php
new file mode 100644
index 000000000..2651d5c4d
--- /dev/null
+++ b/database/migrations/2019_12_10_023604_create_newsroom_table.php
@@ -0,0 +1,45 @@
+bigIncrements('id');
+ $table->bigInteger('user_id')->unsigned()->nullable();
+ $table->string('header_photo_url')->nullable();
+ $table->string('title')->nullable();
+ $table->string('slug')->nullable()->unique()->index();
+ $table->string('category')->default('update');
+ $table->text('summary')->nullable();
+ $table->text('body')->nullable();
+ $table->text('body_rendered')->nullable();
+ $table->string('link')->nullable();
+ $table->boolean('force_modal')->default(false);
+ $table->boolean('show_timeline')->default(false);
+ $table->boolean('show_link')->default(false);
+ $table->boolean('auth_only')->default(true);
+ $table->timestamp('published_at')->nullable();
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('site_news');
+ }
+}
diff --git a/public/js/compose-classic.js b/public/js/compose-classic.js
index 3c11c0415..143ef3f48 100644
Binary files a/public/js/compose-classic.js and b/public/js/compose-classic.js differ
diff --git a/public/js/compose.js b/public/js/compose.js
index fd66f001c..9e69d9c66 100644
Binary files a/public/js/compose.js and b/public/js/compose.js differ
diff --git a/public/js/profile.js b/public/js/profile.js
index 36e38d798..cc260afe2 100644
Binary files a/public/js/profile.js and b/public/js/profile.js differ
diff --git a/public/js/status.js b/public/js/status.js
index 1c6ce543f..88d8baef6 100644
Binary files a/public/js/status.js and b/public/js/status.js differ
diff --git a/public/js/timeline.js b/public/js/timeline.js
index 5162342d8..c3e02488f 100644
Binary files a/public/js/timeline.js and b/public/js/timeline.js differ
diff --git a/public/mix-manifest.json b/public/mix-manifest.json
index cc4135fe0..a5fc352f1 100644
Binary files a/public/mix-manifest.json and b/public/mix-manifest.json differ
diff --git a/resources/assets/js/components/AnnouncementsCard.vue b/resources/assets/js/components/AnnouncementsCard.vue
new file mode 100644
index 000000000..4e43b4857
--- /dev/null
+++ b/resources/assets/js/components/AnnouncementsCard.vue
@@ -0,0 +1,155 @@
+
+
+ {{announcement.summary}}
+
+ Read more
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,7 +58,8 @@
- You can hide followers or following count and lists on your profile.
-
Privacy Settings
Newsroom
+Create Announcement
++ +
+Newsroom
+Edit Announcement
++ +
++ + +
+ +Newsroom
+Manage News and Platform Tips
+{{str_limit($news->title,30)}}
+{{str_limit($news->summary, 40)}}
+No Announcements Found!
+