mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-23 06:51:27 +00:00
Merge pull request #1903 from pixelfed/staging
Add Announcements/Newsroom feature
This commit is contained in:
commit
d4d85634fb
24 changed files with 938 additions and 62 deletions
|
@ -9,6 +9,7 @@ use App\{
|
||||||
Instance,
|
Instance,
|
||||||
Media,
|
Media,
|
||||||
Like,
|
Like,
|
||||||
|
Newsroom,
|
||||||
OauthClient,
|
OauthClient,
|
||||||
Profile,
|
Profile,
|
||||||
Report,
|
Report,
|
||||||
|
@ -258,4 +259,153 @@ class AdminController extends Controller
|
||||||
$message->save();
|
$message->save();
|
||||||
return;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
94
app/Http/Controllers/NewsroomController.php
Normal file
94
app/Http/Controllers/NewsroomController.php
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Auth;
|
||||||
|
use App\Newsroom;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
|
||||||
|
class NewsroomController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
if(Auth::check()) {
|
||||||
|
$posts = Newsroom::whereNotNull('published_at')->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]);
|
||||||
|
}
|
||||||
|
}
|
27
app/Newsroom.php
Normal file
27
app/Newsroom.php
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Newsroom extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'newsroom';
|
||||||
|
protected $fillable = ['title'];
|
||||||
|
|
||||||
|
protected $dates = ['published_at'];
|
||||||
|
|
||||||
|
public function permalink()
|
||||||
|
{
|
||||||
|
$year = $this->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}");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateNewsroomTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('newsroom', function (Blueprint $table) {
|
||||||
|
$table->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');
|
||||||
|
}
|
||||||
|
}
|
BIN
public/js/compose-classic.js
vendored
BIN
public/js/compose-classic.js
vendored
Binary file not shown.
BIN
public/js/compose.js
vendored
BIN
public/js/compose.js
vendored
Binary file not shown.
BIN
public/js/profile.js
vendored
BIN
public/js/profile.js
vendored
Binary file not shown.
BIN
public/js/status.js
vendored
BIN
public/js/status.js
vendored
Binary file not shown.
BIN
public/js/timeline.js
vendored
BIN
public/js/timeline.js
vendored
Binary file not shown.
Binary file not shown.
155
resources/assets/js/components/AnnouncementsCard.vue
Normal file
155
resources/assets/js/components/AnnouncementsCard.vue
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<transition name="fade">
|
||||||
|
<div v-if="announcements.length" class="card border shadow-none mb-3" style="max-width: 18rem;">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title mb-0">
|
||||||
|
<span class="font-weight-bold">{{announcement.title}}</span>
|
||||||
|
<span class="float-right cursor-pointer" title="Close" @click="close"><i class="fas fa-times text-lighter"></i></span>
|
||||||
|
</div>
|
||||||
|
<p class="card-text">
|
||||||
|
<span style="font-size:13px;">{{announcement.summary}}</span>
|
||||||
|
</p>
|
||||||
|
<p class="d-flex align-items-center justify-content-between mb-0">
|
||||||
|
<a v-if="announcement.url" :href="announcement.url" class="small font-weight-bold mb-0">Read more</a>
|
||||||
|
<span v-else></span>
|
||||||
|
<span>
|
||||||
|
<span :class="[showPrev ? 'btn btn-outline-secondary btn-sm py-0':'btn btn-outline-secondary btn-sm py-0 disabled']" :disabled="showPrev == false" @click="loadPrev()">
|
||||||
|
<i class="fas fa-chevron-left fa-sm"></i>
|
||||||
|
</span>
|
||||||
|
<span class="btn btn-outline-success btn-sm py-0 mx-1" title="Mark as Read" data-toggle="tooltip" data-placement="bottom" @click="markAsRead()">
|
||||||
|
<i class="fas fa-check fa-sm"></i>
|
||||||
|
</span>
|
||||||
|
<span :class="[showNext ? 'btn btn-outline-secondary btn-sm py-0':'btn btn-outline-secondary btn-sm py-0 disabled']" :disabled="showNext == false" @click="loadNext()">
|
||||||
|
<i class="fas fa-chevron-right fa-sm"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style type="text/css" scoped>
|
||||||
|
.fade-enter-active, .fade-leave-active {
|
||||||
|
transition: opacity .5s;
|
||||||
|
}
|
||||||
|
.fade-enter, .fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
announcements: [],
|
||||||
|
announcement: {},
|
||||||
|
cursor: 0,
|
||||||
|
showNext: true,
|
||||||
|
showPrev: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.fetchAnnouncements();
|
||||||
|
},
|
||||||
|
|
||||||
|
updated() {
|
||||||
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
fetchAnnouncements() {
|
||||||
|
let self = this;
|
||||||
|
let key = 'metro-tips-closed';
|
||||||
|
let cached = JSON.parse(window.localStorage.getItem(key));
|
||||||
|
axios.get('/api/pixelfed/v1/newsroom/timeline')
|
||||||
|
.then(res => {
|
||||||
|
self.announcements = res.data.filter(p => {
|
||||||
|
if(cached) {
|
||||||
|
return cached.indexOf(p.id) == -1;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.announcement = self.announcements[0]
|
||||||
|
if(self.announcements.length == 1) {
|
||||||
|
self.showNext = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
loadNext() {
|
||||||
|
if(!this.showNext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.cursor += 1;
|
||||||
|
this.announcement = this.announcements[this.cursor];
|
||||||
|
if((this.cursor + 1) == this.announcements.length) {
|
||||||
|
this.showNext = false;
|
||||||
|
}
|
||||||
|
if(this.cursor >= 1) {
|
||||||
|
this.showPrev = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loadPrev() {
|
||||||
|
if(!this.showPrev) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.cursor -= 1;
|
||||||
|
this.announcement = this.announcements[this.cursor];
|
||||||
|
if(this.cursor == 0) {
|
||||||
|
this.showPrev = false;
|
||||||
|
}
|
||||||
|
if(this.cursor < this.announcements.length) {
|
||||||
|
this.showNext = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
closeNewsroomPost(id, index) {
|
||||||
|
let key = 'metro-tips-closed';
|
||||||
|
let ctx = [];
|
||||||
|
let cached = window.localStorage.getItem(key);
|
||||||
|
if(cached) {
|
||||||
|
ctx = JSON.parse(cached);
|
||||||
|
}
|
||||||
|
ctx.push(id);
|
||||||
|
window.localStorage.setItem(key, JSON.stringify(ctx));
|
||||||
|
this.newsroomPosts = this.newsroomPosts.filter(res => {
|
||||||
|
return res.id !== id
|
||||||
|
});
|
||||||
|
if(this.newsroomPosts.length == 0) {
|
||||||
|
this.showTips = false;
|
||||||
|
} else {
|
||||||
|
this.newsroomPost = [ this.newsroomPosts[0] ];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
close() {
|
||||||
|
window.localStorage.setItem('metro-tips', false);
|
||||||
|
this.$emit('show-tips', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
markAsRead() {
|
||||||
|
let vm = this;
|
||||||
|
axios.post('/api/pixelfed/v1/newsroom/markasread', {
|
||||||
|
id: this.announcement.id
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
let cur = vm.cursor;
|
||||||
|
vm.announcements.splice(cur, 1);
|
||||||
|
vm.announcement = vm.announcements[0];
|
||||||
|
vm.cursor = 0;
|
||||||
|
vm.showPrev = false;
|
||||||
|
vm.showNext = vm.announcements.length > 1;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
swal('Oops, Something went wrong', 'There was a problem with your request, please try again later.', 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<transition name="fade">
|
||||||
<div class="card notification-card shadow-none border">
|
<div class="card notification-card shadow-none border">
|
||||||
<div class="card-header bg-white">
|
<div class="card-header bg-white">
|
||||||
<p class="mb-0 d-flex align-items-center justify-content-between">
|
<p class="mb-0 d-flex align-items-center justify-content-between">
|
||||||
|
@ -57,7 +58,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</transition>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style type="text/css" scoped></style>
|
<style type="text/css" scoped></style>
|
||||||
|
|
|
@ -90,41 +90,6 @@
|
||||||
<button class="btn btn-link text-dark py-0" type="button" @click="ctxMenu(status)">
|
<button class="btn btn-link text-dark py-0" type="button" @click="ctxMenu(status)">
|
||||||
<span class="fas fa-ellipsis-h text-lighter"></span>
|
<span class="fas fa-ellipsis-h text-lighter"></span>
|
||||||
</button>
|
</button>
|
||||||
<!-- <div class="dropdown-menu dropdown-menu-right">
|
|
||||||
<a class="dropdown-item font-weight-bold" :href="status.url">Go to post</a>
|
|
||||||
<!-- <a class="dropdown-item font-weight-bold" href="#">Share</a>
|
|
||||||
<a class="dropdown-item font-weight-bold" href="#">Embed</a> ->
|
|
||||||
<span v-if="statusOwner(status) == false">
|
|
||||||
<a class="dropdown-item font-weight-bold" :href="reportUrl(status)">Report</a>
|
|
||||||
<a class="dropdown-item font-weight-bold" v-on:click="muteProfile(status)">Mute Profile</a>
|
|
||||||
<a class="dropdown-item font-weight-bold" v-on:click="blockProfile(status)">Block Profile</a>
|
|
||||||
</span>
|
|
||||||
<span v-if="statusOwner(status) == true">
|
|
||||||
<a class="dropdown-item font-weight-bold text-danger" v-on:click="deletePost(status)">Delete</a>
|
|
||||||
</span>
|
|
||||||
<span v-if="profile.is_admin == true && modes.mod == true">
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a v-if="!statusOwner(status)" class="dropdown-item font-weight-bold text-danger" v-on:click="deletePost(status)">Delete</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<h6 class="dropdown-header">Mod Tools</h6>
|
|
||||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'autocw')">
|
|
||||||
<p class="mb-0" data-toggle="tooltip" data-placement="bottom" title="Adds a CW to every post made by this account.">Enforce CW</p>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'noautolink')">
|
|
||||||
<p class="mb-0" title="Do not transform mentions, hashtags or urls into HTML.">No Autolinking</p>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'unlisted')">
|
|
||||||
<p class="mb-0" title="Removes account from public/network timelines.">Unlisted Posts</p>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'disable')">
|
|
||||||
<p class="mb-0" title="Temporarily disable account until next time user log in.">Disable Account</p>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'suspend')">
|
|
||||||
<p class="mb-0" title="This prevents any new interactions, without deleting existing data.">Suspend Account</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -281,21 +246,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<a class="btn btn-light btn-block btn-sm font-weight-bold text-dark mb-3 border" href="/i/compose" data-toggle="modal" data-target="#composeModal"><i class="far fa-plus-square pr-3 fa-lg pt-1"></i> Compose Post</a>
|
<a class="btn btn-light btn-block btn-sm font-weight-bold text-dark mb-3 border bg-white" href="/i/compose" data-toggle="modal" data-target="#composeModal">
|
||||||
|
<i class="far fa-plus-square pr-3 fa-lg pt-1"></i> Compose Post
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="showTips" class="mb-4 card-tips">
|
<div v-if="showTips && !loading" class="mb-4 card-tips">
|
||||||
<div class="card border shadow-none mb-3" style="max-width: 18rem;">
|
<announcements-card v-on:show-tips="showTips = $event"></announcements-card>
|
||||||
<div class="card-body">
|
|
||||||
<div class="card-title">
|
|
||||||
<span class="font-weight-bold">Tip: Hide follower counts</span>
|
|
||||||
<span class="float-right cursor-pointer" @click.prevent="hideTips()"><i class="fas fa-times text-lighter"></i></span>
|
|
||||||
</div>
|
|
||||||
<p class="card-text">
|
|
||||||
<span style="font-size:13px;">You can hide followers or following count and lists on your profile.</span>
|
|
||||||
<br><a href="/settings/privacy/" class="small font-weight-bold">Privacy Settings</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="modes.notify == true && !loading" class="mb-4">
|
<div v-show="modes.notify == true && !loading" class="mb-4">
|
||||||
|
@ -565,7 +522,6 @@
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
this.fetchProfile();
|
this.fetchProfile();
|
||||||
this.fetchTimelineApi();
|
this.fetchTimelineApi();
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -1359,11 +1315,6 @@
|
||||||
this.$refs.ctxModModal.hide();
|
this.$refs.ctxModModal.hide();
|
||||||
},
|
},
|
||||||
|
|
||||||
hideTips() {
|
|
||||||
this.showTips = false;
|
|
||||||
window.localStorage.setItem('metro-tips', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
formatCount(count) {
|
formatCount(count) {
|
||||||
return App.util.format.count(count);
|
return App.util.format.count(count);
|
||||||
},
|
},
|
||||||
|
@ -1431,7 +1382,7 @@
|
||||||
return _.truncate(caption, {
|
return _.truncate(caption, {
|
||||||
length: len
|
length: len
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
5
resources/assets/js/timeline.js
vendored
5
resources/assets/js/timeline.js
vendored
|
@ -37,3 +37,8 @@ Vue.component(
|
||||||
'timeline',
|
'timeline',
|
||||||
require('./components/Timeline.vue').default
|
require('./components/Timeline.vue').default
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Vue.component(
|
||||||
|
'announcements-card',
|
||||||
|
require('./components/AnnouncementsCard.vue').default
|
||||||
|
);
|
135
resources/views/admin/newsroom/create.blade.php
Normal file
135
resources/views/admin/newsroom/create.blade.php
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
@extends('admin.partial.template-full')
|
||||||
|
|
||||||
|
@section('section')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
|
||||||
|
<div class="title">
|
||||||
|
<p class="h1 font-weight-bold">Newsroom</p>
|
||||||
|
<p class="lead mb-0">Create Announcement</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-outline-secondary px-2" style="font-size:13px;" href="{{route('admin.newsroom.home')}}"><i class="fas fa-chevron-left fa-sm text-lighter mr-1"></i> Back to Newsroom </a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-7 border-right">
|
||||||
|
<div>
|
||||||
|
<form method="post">
|
||||||
|
@csrf
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="small font-weight-bold text-muted text-uppercase">Title</label>
|
||||||
|
<input type="text" class="form-control" id="title" name="title">
|
||||||
|
<p class="help-text mb-0 small font-weight-bold text-lighter">We recommend titles shorter than 80 characters.</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="summary" class="small font-weight-bold text-muted text-uppercase">Summary</label>
|
||||||
|
<textarea class="form-control" id="summary" name="summary" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="body" class="small font-weight-bold text-muted text-uppercase">Body</label>
|
||||||
|
<textarea class="form-control" id="body" name="body" rows="6"></textarea>
|
||||||
|
<p class="help-text mb-0 small font-weight-bold text-lighter">Click <a href="#">here</a> to enable the rich text editor.</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="category" class="small font-weight-bold text-muted text-uppercase">Category</label>
|
||||||
|
<input type="text" class="form-control" id="category" name="category" value="update">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<label class="small font-weight-bold text-muted text-uppercase">Preview</label>
|
||||||
|
<div class="card border shadow-none mb-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title mb-0">
|
||||||
|
<span class="font-weight-bold" id="preview_title">Untitled</span>
|
||||||
|
<span class="float-right cursor-pointer" title="Close"><i class="fas fa-times text-lighter"></i></span>
|
||||||
|
</div>
|
||||||
|
<p class="card-text">
|
||||||
|
<span style="font-size:13px;" id="preview_summary">Add a summary</span>
|
||||||
|
</p>
|
||||||
|
<p class="d-flex align-items-center justify-content-between mb-0">
|
||||||
|
<a href="#" class="small font-weight-bold mb-0">Read more</a>
|
||||||
|
<span>
|
||||||
|
<span class="btn btn-outline-secondary btn-sm py-0 disabled">
|
||||||
|
<i class="fas fa-chevron-left fa-sm"></i>
|
||||||
|
</span>
|
||||||
|
<span class="btn btn-outline-success btn-sm py-0 mx-1" title="Mark as Read" data-toggle="tooltip" data-placement="bottom">
|
||||||
|
<i class="fas fa-check fa-sm"></i>
|
||||||
|
</span>
|
||||||
|
<span class="btn btn-outline-secondary btn-sm py-0">
|
||||||
|
<i class="fas fa-chevron-right fa-sm"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<p class="mt-3">
|
||||||
|
<button type="submit" class="btn btn-primary btn-block font-weight-bold py-1 px-4">Save</button>
|
||||||
|
</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="published" name="published">
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="published">Published</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="show_timeline" name="show_timeline">
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="show_timeline">Show On Timelines</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="auth_only" name="auth_only">
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="auth_only">Logged in users only</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="show_link" name="show_link">
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="show_link">Show Read More Link</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{-- <div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="force_modal" name="force_modal">
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="force_modal">Show Modal on timelines</label>
|
||||||
|
</div>
|
||||||
|
</div> --}}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form id="delete-form" method="post">
|
||||||
|
@method('delete')
|
||||||
|
@csrf
|
||||||
|
</form>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
$('#title').on('change keyup paste',function(e) {
|
||||||
|
let el = $(this);
|
||||||
|
let title = el.val()
|
||||||
|
$('#preview_title').text(title);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#summary').on('change keyup paste',function(e) {
|
||||||
|
let el = $(this);
|
||||||
|
let title = el.val()
|
||||||
|
$('#preview_summary').text(title);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#btn-delete').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if(window.confirm('Are you sure you want to delete this post?') == true) {
|
||||||
|
document.getElementById('delete-form').submit();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
@endpush
|
141
resources/views/admin/newsroom/edit.blade.php
Normal file
141
resources/views/admin/newsroom/edit.blade.php
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
@extends('admin.partial.template-full')
|
||||||
|
|
||||||
|
@section('section')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
|
||||||
|
<div class="title">
|
||||||
|
<p class="h1 font-weight-bold">Newsroom</p>
|
||||||
|
<p class="lead mb-0">Edit Announcement</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-outline-secondary px-2" style="font-size:13px;" href="{{route('admin.newsroom.home')}}"><i class="fas fa-chevron-left fa-sm text-lighter mr-1"></i> Back to Newsroom </a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-7 border-right">
|
||||||
|
<div>
|
||||||
|
<form method="post">
|
||||||
|
@csrf
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="small font-weight-bold text-muted text-uppercase">Title</label>
|
||||||
|
<input type="text" class="form-control" id="title" name="title" value="{{$news->title}}">
|
||||||
|
<p class="help-text mb-0 small font-weight-bold text-lighter">We recommend titles shorter than 80 characters.</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="summary" class="small font-weight-bold text-muted text-uppercase">Summary</label>
|
||||||
|
<textarea class="form-control" id="summary" name="summary" rows="3">{{$news->summary}}</textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="body" class="small font-weight-bold text-muted text-uppercase">Body</label>
|
||||||
|
<textarea class="form-control" id="body" name="body" rows="6">{{$news->body}}</textarea>
|
||||||
|
<p class="help-text mb-0 small font-weight-bold text-lighter">Click <a href="#">here</a> to enable the rich text editor.</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="category" class="small font-weight-bold text-muted text-uppercase">Category</label>
|
||||||
|
<input type="text" class="form-control" id="category" name="category" value="{{$news->category}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<label class="small font-weight-bold text-muted text-uppercase">Preview</label>
|
||||||
|
<div class="card border shadow-none mb-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title mb-0">
|
||||||
|
<span class="font-weight-bold" id="preview_title">{{$news->title}}</span>
|
||||||
|
<span class="float-right cursor-pointer" title="Close"><i class="fas fa-times text-lighter"></i></span>
|
||||||
|
</div>
|
||||||
|
<p class="card-text">
|
||||||
|
<span style="font-size:13px;" id="preview_summary">{{$news->summary}}</span>
|
||||||
|
</p>
|
||||||
|
<p class="d-flex align-items-center justify-content-between mb-0">
|
||||||
|
<a href="#" class="small font-weight-bold mb-0">Read more</a>
|
||||||
|
<span>
|
||||||
|
<span class="btn btn-outline-secondary btn-sm py-0 disabled">
|
||||||
|
<i class="fas fa-chevron-left fa-sm"></i>
|
||||||
|
</span>
|
||||||
|
<span class="btn btn-outline-success btn-sm py-0 mx-1" title="Mark as Read" data-toggle="tooltip" data-placement="bottom">
|
||||||
|
<i class="fas fa-check fa-sm"></i>
|
||||||
|
</span>
|
||||||
|
<span class="btn btn-outline-secondary btn-sm py-0">
|
||||||
|
<i class="fas fa-chevron-right fa-sm"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<p class="mt-3">
|
||||||
|
<button type="submit" class="btn btn-primary btn-block font-weight-bold py-1 px-4">Save</button>
|
||||||
|
</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="published" name="published" {{$news->published_at ? 'checked="checked"' : ''}}>
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="published">Published</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="show_timeline" name="show_timeline" {{$news->show_timeline ? 'checked="checked"' : ''}}>
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="show_timeline">Show On Timelines</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="auth_only" name="auth_only" {{$news->auth_only ? 'checked="checked"' : ''}}>
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="auth_only">Logged in users only</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="show_link" name="show_link" {{$news->show_link ? 'checked="checked"' : ''}}>
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="show_link">Show Read More Link</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{-- <div class="form-group">
|
||||||
|
<div class="custom-control custom-switch">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="force_modal" name="force_modal" {{$news->force_modal ? 'checked="checked"' : ''}}>
|
||||||
|
<label class="custom-control-label font-weight-bold text-uppercase text-muted" for="force_modal">Show Modal on timelines</label>
|
||||||
|
</div>
|
||||||
|
</div> --}}
|
||||||
|
<hr>
|
||||||
|
</form>
|
||||||
|
<p class="mt-1 d-flex justify-content-between">
|
||||||
|
<button type="button" class="btn btn-outline-secondary btn-sm font-weight-bold py-1 px-3">Preview</button>
|
||||||
|
<button type="button" class="btn btn-outline-danger btn-sm font-weight-bold py-1 px-3" id="btn-delete">Delete</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form id="delete-form" method="post">
|
||||||
|
@method('delete')
|
||||||
|
@csrf
|
||||||
|
</form>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
$('#title').on('change keyup paste',function(e) {
|
||||||
|
let el = $(this);
|
||||||
|
let title = el.val()
|
||||||
|
$('#preview_title').text(title);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#summary').on('change keyup paste',function(e) {
|
||||||
|
let el = $(this);
|
||||||
|
let title = el.val()
|
||||||
|
$('#preview_summary').text(title);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#btn-delete').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if(window.confirm('Are you sure you want to delete this post?') == true) {
|
||||||
|
document.getElementById('delete-form').submit();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
@endpush
|
62
resources/views/admin/newsroom/home.blade.php
Normal file
62
resources/views/admin/newsroom/home.blade.php
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
@extends('admin.partial.template-full')
|
||||||
|
|
||||||
|
@section('section')
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
|
||||||
|
<div class="title">
|
||||||
|
<p class="h1 font-weight-bold">Newsroom</p>
|
||||||
|
<p class="lead mb-0">Manage News and Platform Tips</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-outline-success px-4" style="font-size:13px;" href="{{route('admin.newsroom.create')}}">New Announcement</a>
|
||||||
|
<a class="btn btn-outline-secondary px-2 mr-3" style="font-size:13px;" href="/site/newsroom">View Newsroom <i class="fas fa-chevron-right fa-sm text-lighter ml-1"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="my-5 row">
|
||||||
|
<div class="col-md-8 offset-md-2">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header bg-light lead font-weight-bold">
|
||||||
|
Announcements
|
||||||
|
</div>
|
||||||
|
@if($newsroom->count() > 0)
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
@foreach($newsroom as $news)
|
||||||
|
<li class="list-group-item d-flex align-items-center justify-content-between">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0 font-weight-bold">{{str_limit($news->title,30)}}</p>
|
||||||
|
<p class="mb-0 small">{{str_limit($news->summary, 40)}}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
@if($news->published_at != null)
|
||||||
|
<span class="btn btn-success btn-sm px-2 py-0 font-weight-bold mr-3">PUBLISHED</span>
|
||||||
|
@else
|
||||||
|
<span class="btn btn-outline-secondary btn-sm px-2 py-0 font-weight-bold mr-3">DRAFT</span>
|
||||||
|
@endif
|
||||||
|
<a class="btn btn-outline-lighter btn-sm mr-2" title="Edit Post" data-toggle="tooltip" data-placement="bottom" href="{{$news->editUrl()}}">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
|
@if($news->published_at)
|
||||||
|
<a class="btn btn-outline-lighter btn-sm" title="View Post" data-toggle="tooltip" data-placement="bottom" href="{{$news->permalink()}}">
|
||||||
|
<i class="fas fa-eye"></i>
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
@else
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<p class="lead mb-0 p-5">No Announcements Found!</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center mt-4">
|
||||||
|
{!!$newsroom->links()!!}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
|
@ -1,4 +1,4 @@
|
||||||
<nav class="navbar navbar-expand-lg navbar-light bg-white">
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#topbarNav" aria-controls="topbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#topbarNav" aria-controls="topbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
@ -11,9 +11,6 @@
|
||||||
<li class="nav-item mx-2 {{request()->is('*messages*')?'active':''}}">
|
<li class="nav-item mx-2 {{request()->is('*messages*')?'active':''}}">
|
||||||
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.messages')}}">Messages</a>
|
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.messages')}}">Messages</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item mx-2 {{request()->is('*hashtags*')?'active':''}}">
|
|
||||||
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.hashtags')}}">Hashtags</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item mx-2 {{request()->is('*instances*')?'active':''}}">
|
<li class="nav-item mx-2 {{request()->is('*instances*')?'active':''}}">
|
||||||
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.instances')}}">Instances</a>
|
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.instances')}}">Instances</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -32,13 +29,15 @@
|
||||||
<li class="nav-item mx-2 {{request()->is('*users*')?'active':''}}">
|
<li class="nav-item mx-2 {{request()->is('*users*')?'active':''}}">
|
||||||
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.users')}}">Users</a>
|
<a class="nav-link font-weight-lighter text-muted" href="{{route('admin.users')}}">Users</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item dropdown mx-2 {{request()->is(['*settings*','*discover*'])?'active':''}}">
|
<li class="nav-item dropdown mx-2 {{request()->is(['*settings*','*discover*', '*site-news*'])?'active':''}}">
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
More
|
More
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
|
||||||
<a class="dropdown-item font-weight-bold {{request()->is('*apps*')?'active':''}}" href="{{route('admin.apps')}}">Apps</a>
|
<a class="dropdown-item font-weight-bold {{request()->is('*apps*')?'active':''}}" href="{{route('admin.apps')}}">Apps</a>
|
||||||
<a class="dropdown-item font-weight-bold {{request()->is('*discover*')?'active':''}}" href="{{route('admin.discover')}}">Discover</a>
|
<a class="dropdown-item font-weight-bold {{request()->is('*discover*')?'active':''}}" href="{{route('admin.discover')}}">Discover</a>
|
||||||
|
<a class="dropdown-item font-weight-bold {{request()->is('*hashtags*')?'active':''}}" href="{{route('admin.hashtags')}}">Hashtags</a>
|
||||||
|
<a class="dropdown-item font-weight-bold {{request()->is('*site-news*')?'active':''}}" href="/i/admin/site-news">Newsroom</a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a class="dropdown-item font-weight-bold" href="/horizon">Horizon</a>
|
<a class="dropdown-item font-weight-bold" href="/horizon">Horizon</a>
|
||||||
{{-- <a class="dropdown-item font-weight-bold" href="#">Websockets</a> --}}
|
{{-- <a class="dropdown-item font-weight-bold" href="#">Websockets</a> --}}
|
||||||
|
|
7
resources/views/site/news/archive/index.blade.php
Normal file
7
resources/views/site/news/archive/index.blade.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
@extends('site.news.partial.layout')
|
||||||
|
|
||||||
|
@section('body')
|
||||||
|
<div class="container">
|
||||||
|
<p class="text-center">Archive here</p>
|
||||||
|
</div>
|
||||||
|
@endsection
|
26
resources/views/site/news/home.blade.php
Normal file
26
resources/views/site/news/home.blade.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
@extends('site.news.partial.layout')
|
||||||
|
|
||||||
|
@section('body')
|
||||||
|
<div class="container">
|
||||||
|
<div class="row px-3">
|
||||||
|
@foreach($posts->slice(0,1) as $post)
|
||||||
|
<div class="col-12 bg-light d-flex justify-content-center align-items-center mt-2 mb-4" style="height:300px;">
|
||||||
|
<div class="mx-5">
|
||||||
|
<p class="small text-danger mb-0 text-uppercase">{{$post->category}}</p>
|
||||||
|
<p class="small text-muted">{{$post->published_at->format('F d, Y')}}</p>
|
||||||
|
<p class="h1" style="font-size: 2.6rem;font-weight: 700;"><a class="text-dark text-decoration-none" href="{{$post->permalink()}}">{{$post->title}}</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
@foreach($posts->slice(1) as $post)
|
||||||
|
<div class="col-6 bg-light d-flex justify-content-center align-items-center mt-3 px-5" style="height:300px;">
|
||||||
|
<div class="mx-0">
|
||||||
|
<p class="small text-danger mb-0 text-uppercase">{{$post->category}}</p>
|
||||||
|
<p class="small text-muted">{{$post->published_at->format('F d, Y')}}</p>
|
||||||
|
<p class="h1" style="font-size: 2rem;font-weight: 700;"><a class="text-dark text-decoration-none" href="{{$post->permalink()}}">{{$post->title}}</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
17
resources/views/site/news/partial/layout.blade.php
Normal file
17
resources/views/site/news/partial/layout.blade.php
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
@extends('layouts.anon')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
@include('site.news.partial.nav')
|
||||||
|
@yield('body');
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('styles')
|
||||||
|
<style type="text/css">
|
||||||
|
html, body {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.navbar-laravel {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@endpush
|
14
resources/views/site/news/partial/nav.blade.php
Normal file
14
resources/views/site/news/partial/nav.blade.php
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<div class="container py-4">
|
||||||
|
<div class="col-12 d-flex justify-content-between border-bottom align-items-center pb-3 px-0">
|
||||||
|
<div>
|
||||||
|
<p class="h4 mb-0"><a href="/site/newsroom" class="text-dark text-decoration-none">Newsroom</a></p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-outline-secondary btn-sm py-1" href="/"><i class="fas fa-chevron-left fa-sm text-lighter mr-2"></i> Back to Pixelfed</a>
|
||||||
|
</div>
|
||||||
|
{{-- <div>
|
||||||
|
<a href="/site/newsroom/search" class="small text-muted mr-4 text-decoration-none">Search Newsroom</a>
|
||||||
|
<a href="/site/newsroom/archive" class="small text-muted text-decoration-none">Archive</a>
|
||||||
|
</div> --}}
|
||||||
|
</div>
|
||||||
|
</div>
|
33
resources/views/site/news/post/show.blade.php
Normal file
33
resources/views/site/news/post/show.blade.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
@extends('site.news.partial.layout')
|
||||||
|
|
||||||
|
@section('body')
|
||||||
|
<div class="container mt-3">
|
||||||
|
<div class="row px-3">
|
||||||
|
<div class="col-12 bg-light d-flex justify-content-center align-items-center" style="min-height: 400px">
|
||||||
|
<div style="max-width: 550px;">
|
||||||
|
<p class="small text-danger mb-0 text-uppercase">{{$post->category}}</p>
|
||||||
|
<p class="small text-muted">{{$post->published_at->format('F d, Y')}}</p>
|
||||||
|
<p class="h1" style="font-size: 2.6rem;font-weight: 700;">{{$post->title}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 mt-4">
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<p class="lead text-center py-5" style="font-size:25px; font-weight: 200; max-width: 550px;">
|
||||||
|
{{$post->summary}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if($post->body)
|
||||||
|
<div class="col-12 mt-4">
|
||||||
|
<div class="d-flex justify-content-center border-top">
|
||||||
|
<p class="lead py-5" style="max-width: 550px;">
|
||||||
|
{!!$post->body!!}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="col-12 mt-4"></div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
|
@ -52,6 +52,13 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio
|
||||||
Route::get('messages/home', 'AdminController@messagesHome')->name('admin.messages');
|
Route::get('messages/home', 'AdminController@messagesHome')->name('admin.messages');
|
||||||
Route::get('messages/show/{id}', 'AdminController@messagesShow');
|
Route::get('messages/show/{id}', 'AdminController@messagesShow');
|
||||||
Route::post('messages/mark-read', 'AdminController@messagesMarkRead');
|
Route::post('messages/mark-read', 'AdminController@messagesMarkRead');
|
||||||
|
Route::redirect('site-news', '/i/admin/newsroom');
|
||||||
|
Route::get('newsroom', 'AdminController@newsroomHome')->name('admin.newsroom.home');
|
||||||
|
Route::get('newsroom/create', 'AdminController@newsroomCreate')->name('admin.newsroom.create');
|
||||||
|
Route::get('newsroom/edit/{id}', 'AdminController@newsroomEdit');
|
||||||
|
Route::post('newsroom/edit/{id}', 'AdminController@newsroomUpdate');
|
||||||
|
Route::delete('newsroom/edit/{id}', 'AdminController@newsroomDelete');
|
||||||
|
Route::post('newsroom/create', 'AdminController@newsroomStore');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofactor', 'localization'])->group(function () {
|
Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofactor', 'localization'])->group(function () {
|
||||||
|
@ -113,6 +120,8 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
||||||
Route::get('notifications', 'ApiController@notifications');
|
Route::get('notifications', 'ApiController@notifications');
|
||||||
Route::get('timelines/public', 'PublicApiController@publicTimelineApi');
|
Route::get('timelines/public', 'PublicApiController@publicTimelineApi');
|
||||||
Route::get('timelines/home', 'PublicApiController@homeTimelineApi');
|
Route::get('timelines/home', 'PublicApiController@homeTimelineApi');
|
||||||
|
Route::get('newsroom/timeline', 'NewsroomController@timelineApi');
|
||||||
|
Route::post('newsroom/markasread', 'NewsroomController@markAsRead');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group(['prefix' => 'v2'], function() {
|
Route::group(['prefix' => 'v2'], function() {
|
||||||
|
@ -360,6 +369,10 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
||||||
Route::view('report-something', 'site.help.report-something')->name('help.report-something');
|
Route::view('report-something', 'site.help.report-something')->name('help.report-something');
|
||||||
Route::view('data-policy', 'site.help.data-policy')->name('help.data-policy');
|
Route::view('data-policy', 'site.help.data-policy')->name('help.data-policy');
|
||||||
});
|
});
|
||||||
|
Route::get('newsroom/{year}/{month}/{slug}', 'NewsroomController@show');
|
||||||
|
Route::get('newsroom/archive', 'NewsroomController@archive');
|
||||||
|
Route::get('newsroom/search', 'NewsroomController@search');
|
||||||
|
Route::get('newsroom', 'NewsroomController@index');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group(['prefix' => 'timeline'], function () {
|
Route::group(['prefix' => 'timeline'], function () {
|
||||||
|
|
Loading…
Reference in a new issue