mirror of
https://github.com/prurigro/hypothetical.git
synced 2024-11-09 11:16:39 -05:00
Amalgamate the api route controller functionality into a single ApiController, and implement both vue component and traditional blade versions of a blog page on the public facing part of the site
This commit is contained in:
parent
b83213c16e
commit
a9aca7d4fe
12 changed files with 283 additions and 40 deletions
|
@ -1,11 +1,45 @@
|
||||||
<?php namespace App\Http\Controllers;
|
<?php namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Newsletter;
|
|
||||||
use Log;
|
use Log;
|
||||||
|
use Mail;
|
||||||
|
use Newsletter;
|
||||||
|
use App\Models\Blog;
|
||||||
|
use App\Models\Contact;
|
||||||
use App\Models\Subscriptions;
|
use App\Models\Subscriptions;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class SubscriptionController extends Controller {
|
class ApiController extends Controller {
|
||||||
|
|
||||||
|
public function getBlogEntries()
|
||||||
|
{
|
||||||
|
return Blog::getBlogEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postContactSubmit(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'name' => 'required',
|
||||||
|
'email' => 'required|email',
|
||||||
|
'message' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$contact = new Contact;
|
||||||
|
$contact->name = $request['name'];
|
||||||
|
$contact->email = $request['email'];
|
||||||
|
$contact->message = $request['message'];
|
||||||
|
$contact->save();
|
||||||
|
|
||||||
|
// Send the email if the MAIL_SENDTO variable is set
|
||||||
|
if (env('MAIL_SENDTO') != null) {
|
||||||
|
Mail::send('email.contact', [ 'contact' => $contact ], function($mail) use ($contact) {
|
||||||
|
$mail->from(env('MAIL_SENDFROM'), env('APP_NAME'))
|
||||||
|
->to(env('MAIL_SENDTO'))
|
||||||
|
->subject('Contact form submission');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'success';
|
||||||
|
}
|
||||||
|
|
||||||
public function postSubscriptionSubmit(Request $request)
|
public function postSubscriptionSubmit(Request $request)
|
||||||
{
|
{
|
|
@ -1,35 +0,0 @@
|
||||||
<?php namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use Mail;
|
|
||||||
use App\Models\Contact;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class ContactController extends Controller {
|
|
||||||
|
|
||||||
public function postContactSubmit(Request $request)
|
|
||||||
{
|
|
||||||
$this->validate($request, [
|
|
||||||
'name' => 'required',
|
|
||||||
'email' => 'required|email',
|
|
||||||
'message' => 'required'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$contact = new Contact;
|
|
||||||
$contact->name = $request['name'];
|
|
||||||
$contact->email = $request['email'];
|
|
||||||
$contact->message = $request['message'];
|
|
||||||
$contact->save();
|
|
||||||
|
|
||||||
// Send the email if the MAIL_SENDTO variable is set
|
|
||||||
if (env('MAIL_SENDTO') != null) {
|
|
||||||
Mail::send('email.contact', [ 'contact' => $contact ], function($mail) use ($contact) {
|
|
||||||
$mail->from(env('MAIL_SENDFROM'), env('APP_NAME'))
|
|
||||||
->to(env('MAIL_SENDTO'))
|
|
||||||
->subject('Contact form submission');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'success';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Parsedown;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use App\User;
|
||||||
|
|
||||||
class Blog extends DashboardModel
|
class Blog extends DashboardModel
|
||||||
{
|
{
|
||||||
|
@ -22,4 +24,38 @@ class Blog extends DashboardModel
|
||||||
[ 'name' => 'tags', 'type' => 'text' ],
|
[ 'name' => 'tags', 'type' => 'text' ],
|
||||||
[ 'name' => 'header-image', 'title' => 'Header Image', 'type' => 'image', 'delete' => true ]
|
[ 'name' => 'header-image', 'title' => 'Header Image', 'type' => 'image', 'delete' => true ]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public static function getBlogEntries()
|
||||||
|
{
|
||||||
|
$blog_entries = [];
|
||||||
|
|
||||||
|
foreach (self::orderBy(self::$dashboard_sort_column, self::$dashboard_sort_direction)->get() as $blog_entry) {
|
||||||
|
// Add the name of the user that created the post
|
||||||
|
$blog_entry['username'] = User::find($blog_entry->user_id)->name;
|
||||||
|
|
||||||
|
// Add a string with the date and time the post was made
|
||||||
|
$blog_entry['date'] = date('M j, Y @ g:iA', strtotime($blog_entry->created_at));
|
||||||
|
|
||||||
|
// Convert the markdown in the body to html
|
||||||
|
$blog_entry['body'] = Parsedown::instance()->setBreaksEnabled(true)->setMarkupEscaped(true)->parse($blog_entry['body']);
|
||||||
|
|
||||||
|
// Replace the tags string with an array
|
||||||
|
$tags = [];
|
||||||
|
|
||||||
|
foreach (explode(';', $blog_entry['tags']) as $tag) {
|
||||||
|
array_push($tags, $tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
$blog_entry['tags'] = $tags;
|
||||||
|
|
||||||
|
// Add the header image if one exists
|
||||||
|
$header_image_path = '/uploads/blog/img/' . $blog_entry->id . '-header-image.jpg';
|
||||||
|
$blog_entry['headerimage'] = file_exists(base_path() . '/public' . $header_image_path) ? $header_image_path : '';
|
||||||
|
|
||||||
|
// Add the processed blog entry to the array
|
||||||
|
array_push($blog_entries, $blog_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $blog_entries;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
2
resources/assets/js/app.js
vendored
2
resources/assets/js/app.js
vendored
|
@ -17,6 +17,7 @@ Vue.http.headers.common["X-CSRF-TOKEN"] = env.csrfToken;
|
||||||
|
|
||||||
// Import page components
|
// Import page components
|
||||||
import HomePage from "pages/home.vue";
|
import HomePage from "pages/home.vue";
|
||||||
|
import BlogPage from "pages/blog.vue";
|
||||||
import ContactPage from "pages/contact.vue";
|
import ContactPage from "pages/contact.vue";
|
||||||
import Error404Page from "pages/error404.vue";
|
import Error404Page from "pages/error404.vue";
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ const router = new VueRouter({
|
||||||
|
|
||||||
routes: [
|
routes: [
|
||||||
{ path: "/", component: HomePage },
|
{ path: "/", component: HomePage },
|
||||||
|
{ path: "/blog", component: BlogPage },
|
||||||
{ path: "/contact", component: ContactPage },
|
{ path: "/contact", component: ContactPage },
|
||||||
{ path: "/*", component: Error404Page }
|
{ path: "/*", component: Error404Page }
|
||||||
],
|
],
|
||||||
|
|
2
resources/assets/sass/_var.scss
vendored
2
resources/assets/sass/_var.scss
vendored
|
@ -28,7 +28,7 @@ $c-accent: #fa7921; // accent
|
||||||
$c-error: #fa2036; // error
|
$c-error: #fa2036; // error
|
||||||
|
|
||||||
// Values
|
// Values
|
||||||
$nav-link-count: 2;
|
$nav-link-count: 3;
|
||||||
|
|
||||||
// Sizes
|
// Sizes
|
||||||
$nav-height-desktop: 60px;
|
$nav-height-desktop: 60px;
|
||||||
|
|
81
resources/assets/sass/pages/_blog.scss
vendored
Normal file
81
resources/assets/sass/pages/_blog.scss
vendored
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
.blog-page-component {
|
||||||
|
padding: $grid-gutter-width 0px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-bottom: $grid-gutter-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-entry {
|
||||||
|
border: 1px solid lighten($c-base, 75%);
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: $grid-gutter-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-header-image {
|
||||||
|
background-position: center center;
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
|
||||||
|
@include media-breakpoint-down(sm) {
|
||||||
|
@include aspect-ratio(3, 1);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
width: 35%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
padding: 25px;
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
@include font-sans-semibold;
|
||||||
|
margin-bottom: $grid-gutter-width;
|
||||||
|
font-size: 25px;
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-info {
|
||||||
|
color: lighten($c-text, 30%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-body {
|
||||||
|
margin: ($grid-gutter-width / 2) 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-taglist {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
margin-right: 5px;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: $c-accent;
|
||||||
|
color: $c-text-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
resources/components/pages/blog.vue
Normal file
66
resources/components/pages/blog.vue
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<template>
|
||||||
|
<div class="blog-page-component">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-lg-10 offset-lg-1 col-xl-8 offset-xl-2 col-xxl-6 offset-xxl-3">
|
||||||
|
<h1>Blog</h1>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-for="entry in blogEntries"
|
||||||
|
class="blog-entry">
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="entry.headerimage !== ''"
|
||||||
|
class="blog-entry-header-image"
|
||||||
|
:style="{ backgroundImage: 'url(' + entry.headerimage + ')' }">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="blog-entry-content">
|
||||||
|
<h2 class="blog-entry-content-title">{{ entry.title }}</h2>
|
||||||
|
|
||||||
|
<div class="blog-entry-content-info">
|
||||||
|
<span class="blog-entry-content-info-name">{{ entry.username }}</span> |
|
||||||
|
<span class="blog-entry-content-info-date">{{ entry.date }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="blog-entry-content-body" v-html="entry.body"></p>
|
||||||
|
|
||||||
|
<div class="blog-entry-content-taglist">
|
||||||
|
<span
|
||||||
|
v-for="tag in entry.tags"
|
||||||
|
class="blog-entry-content-taglist-item">
|
||||||
|
|
||||||
|
{{ tag }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
blogEntries: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
populateBlogEntries() {
|
||||||
|
this.$http.get("/api/blog-entries" + env.apiToken).then((response) => {
|
||||||
|
this.blogEntries = response.body;
|
||||||
|
}, (response) => {
|
||||||
|
console.log("Failed to retrieve blog entries");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.populateBlogEntries();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
navLinks: [
|
navLinks: [
|
||||||
{ path: "/", title: "Home" },
|
{ path: "/", title: "Home" },
|
||||||
|
{ path: "/blog", title: "Blog" },
|
||||||
{ path: "/contact", title: "Contact" }
|
{ path: "/contact", title: "Contact" }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,11 +17,19 @@ Route::middleware('auth:api')->get('/user', function(Request $request) {
|
||||||
return $request->user();
|
return $request->user();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Get Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
Route::get('/blog-entries', 'ApiController@getBlogEntries');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Post Routes
|
| Post Routes
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route::post('/contact-submit', 'ContactController@postContactSubmit');
|
Route::post('/contact-submit', 'ApiController@postContactSubmit');
|
||||||
Route::post('/subscription-submit', 'SubscriptionController@postSubscriptionSubmit');
|
Route::post('/subscription-submit', 'ApiController@postSubscriptionSubmit');
|
||||||
|
|
45
traditional-bootstrap/resources/views/pages/blog.blade.php
Normal file
45
traditional-bootstrap/resources/views/pages/blog.blade.php
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
@extends('templates.public', [ 'title' => 'Blog' ])
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="blog-page-component">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-lg-10 offset-lg-1 col-xl-8 offset-xl-2 col-xxl-6 offset-xxl-3">
|
||||||
|
<h1>Blog</h1>
|
||||||
|
|
||||||
|
@foreach(App\Models\Blog::getBlogEntries() as $entry)
|
||||||
|
<div class="blog-entry">
|
||||||
|
@if($entry['headerimage'] != '')
|
||||||
|
<div
|
||||||
|
class="blog-entry-header-image"
|
||||||
|
style="background-image: url({{ $entry['headerimage'] }})">
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="blog-entry-content">
|
||||||
|
<h2 class="blog-entry-content-title">{{ $entry['title'] }}</h2>
|
||||||
|
|
||||||
|
<div class="blog-entry-content-info">
|
||||||
|
<span class="blog-entry-content-info-name">{{ $entry['username'] }}</span> |
|
||||||
|
<span class="blog-entry-content-info-date">{{ $entry['date'] }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="blog-entry-content-body">
|
||||||
|
{!! $entry['body'] !!}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="blog-entry-content-taglist">
|
||||||
|
@foreach($entry['tags'] as $tag)
|
||||||
|
<span class="blog-entry-content-taglist-item">
|
||||||
|
{{ $tag }}
|
||||||
|
</span>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
|
@ -11,6 +11,7 @@
|
||||||
<div class="nav-section-component-links" :class="{ open: openNav }">
|
<div class="nav-section-component-links" :class="{ open: openNav }">
|
||||||
<div class="nav-section-component-links-wrapper">
|
<div class="nav-section-component-links-wrapper">
|
||||||
<a class="navlink" href="/"><span>Home</span></a>
|
<a class="navlink" href="/"><span>Home</span></a>
|
||||||
|
<a class="navlink" href="/blog"><span>Blog</span></a>
|
||||||
<a class="navlink" href="/contact"><span>Contact</span></a>
|
<a class="navlink" href="/contact"><span>Contact</span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -69,6 +69,10 @@ Route::get('/', function() {
|
||||||
return view('pages.index');
|
return view('pages.index');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::get('/blog', function() {
|
||||||
|
return view('pages.blog');
|
||||||
|
});
|
||||||
|
|
||||||
Route::get('/contact', function() {
|
Route::get('/contact', function() {
|
||||||
return view('pages.contact');
|
return view('pages.contact');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue