forum finished

everything should be finished. except for pagination, but fuck that it can wait.
This commit is contained in:
xander 2022-03-13 17:12:36 -12:00
parent 6a97e9e52c
commit 3ad60c24b7
17 changed files with 395 additions and 52 deletions

View File

@ -98,7 +98,7 @@ class RegisterController extends Controller
setcookie('gtok', $sc, time()+(345600*30), "/", $_POST['host']);
return Response()->json('good');
return Response()->json(['message'=>'Success!', 'badInputs'=>[]]);
}
}

View File

@ -34,14 +34,39 @@ class Controller extends BaseController
$array = $user->toArray();
if ($user->Staff()) $array['power'] = $user->Staff()->power_level;
return Response()->json(["data"=>$array]);
}
public function fetchCategories() {
$categories = Category::get();
public function fetchCategoriesFP() {
if (!isset($_COOKIE['gtok'])) {return Response()->json(["error"=>"No user."]);}
$POST = $_COOKIE['gtok'];
$user = User::where('token', $POST)->first();
if (!$user) {return Response()->json(["error"=>"No user."]);}
if ($user->Staff() && $user->Staff()->power_level >= 2) {$categories = Category::get();}else{$categories = Category::where('staffOnly', '0')->get();}
return Response()->json(["categories"=>$categories]);
}
public function fetchCategories() {
if (!isset($_COOKIE['gtok'])) {return Response()->json(["error"=>"No user."]);}
$POST = $_COOKIE['gtok'];
$user = User::where('token', $POST)->first();
if (!$user) {return Response()->json(["error"=>"No user."]);}
$categories = Category::orderBy('staffOnly', 'desc')->get();
return Response()->json(["categories"=>$categories]);
return Response()->json(["data"=>$categories]);
}
public function fetchCategory($id) {
@ -50,7 +75,7 @@ class Controller extends BaseController
if (!$category) {return Response()->json(false);}
$posts = $category->posts()->paginate(20);
$posts = $category->posts()->orderBy('pinned', 'desc')->orderBy('updated_at', 'desc')->paginate(20);
foreach ($posts as &$post) {
$post['creator'] = User::where('id', $post['creator_id'])->first();
@ -67,9 +92,19 @@ class Controller extends BaseController
$postA = $post->toArray();
$postA['creator'] = User::where('id', $postA['creator_id'])->first();;
$realDate = explode('T', $postA['created_at'])[0];
$replies = $post->replies()->paginate(10);
$postA['created_at'] = $realDate;
$postA['creator'] = User::where('id', $postA['creator_id'])->first();
$replies = $post->replies()->orderBy('pinned', 'desc')->orderBy('created_at', 'asc')->paginate(10);
foreach ($replies as &$reply) {
$creator = User::where('id', $reply['creator_id'])->first();
$reply['created_at'] = explode('T', $reply['created_at'])[0];
$reply['creator_name'] = $creator->username;
}
return Response()->json(["post"=>$postA,"replies"=>$replies]);
}
@ -124,7 +159,7 @@ class Controller extends BaseController
Auth::login($user);
return Response()->json('good');
return Response()->json(['message'=>'Success!', 'badInputs'=>[]]);
}

View File

@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use App\Models\Post;
use App\Models\Reply;
use App\Models\Category;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
@ -20,10 +21,10 @@ class HomeController extends Controller
*
* @return void
*/
public function __construct()
/*public function __construct()
{
$this->middleware('auth');
}
}*/
/**
* Show the application dashboard.
@ -42,6 +43,7 @@ class HomeController extends Controller
$valid = Validator::make($data, [
'title' => ['required', 'string', 'min:3', 'max:38'],
'body' => ['required', 'string', 'min:3', 'max:380'],
'category' => ['required']
]);
if ($valid->stopOnFirstFailure()->fails()) {
@ -56,16 +58,62 @@ class HomeController extends Controller
if (!$user) {return Response()->json(['message'=>'User not found!', 'badInputs'=>['title']]);}
if (!isset($_POST['category'])) {return Response()->json(['message'=>'Category not found!', 'badInputs'=>['category']]);}
$categoryId = $_POST['category'];
$category = Category::where('id', $categoryId)->first();
if ($category->staffOnly == '1' && !$user->Staff()) {return Response()->json(['message'=>'You cant use that category.', 'badInputs'=>['category']]);}
$post = new Post;
$post->title = $_POST['title'];
$post->body = $_POST['body'];
$post->creator_id = $_POST['creator_id'];
//will add category support later
$post->category_id = 1;
$post->category_type = 'App\Models\Category';
$post->save();
$category->posts()->save($post);
return Response()->json('good');
return Response()->json(['message'=>'Success!', 'badInputs'=>[], 'post_id'=>$post->id]);
}
public function createReply($id) {
$data = Request::all();
$valid = Validator::make($data, [
'body' => ['required', 'string', 'min:3', 'max:380'],
]);
if ($valid->stopOnFirstFailure()->fails()) {
$error = $valid->errors()->first();
$messages = $valid->messages()->get('*');
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
}
if (!isset($_COOKIE['gtok'])) {return Response()->json(["error"=>"No user."]);}
$POST = $_COOKIE['gtok'];
$meta = User::where('token', $POST)->first();
if (!isset($_POST['creator_id'])) {return Response()->json(['message'=>'System error', 'badInputs'=>['title']]);}
$user = User::where('id', $_POST['creator_id'])->first();
if (!$user) {return Response()->json(['message'=>'User not found!', 'badInputs'=>['title']]);}
$post = Post::where('id', $id)->first();
if (!$post) {return Response()->json(['message'=>'Post not found!', 'badInputs'=>['body']]);}
if ($post->locked && $user->id != $meta->id) {return Response()->json(['message'=>'This post is locked!', 'badInputs'=>['body']]);}
$reply = new Reply;
$reply->body = $_POST['body'];
$reply->creator_id = $user->id;
$post->replies()->save($reply);
return Response()->json(['message'=>'Success!', 'badInputs'=>[], 'post_id'=>$post->id]);
}
}

14
web/app/Models/Staff.php Normal file
View File

@ -0,0 +1,14 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Staff extends Model
{
use HasFactory;
protected $table = 'staff';
}

View File

@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use App\Models\Staff;
class User extends Authenticatable
{
@ -43,4 +44,10 @@ class User extends Authenticatable
protected $casts = [
'email_verified_at' => 'datetime',
];
public function Staff() {
$staff = Staff::where('user_id', $this->id)->first();
return $staff;
}
}

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateStaffTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('staff', function (Blueprint $table) {
$table->id();
$table->string('power_level')->default(1);
$table->string('user_id');
$table->string('staff_title')->default('Moderator');
/* Obviously this isn't the most elegant way of designing a staff system, but ill revamp it later down the road. */
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('staff');
}
}

View File

@ -2,6 +2,7 @@
// Graphictoria 5
import axios from "axios";
import { useHistory } from "react-router-dom";
import Config from '../config.js';
axios.defaults.withCredentials = true
@ -23,8 +24,9 @@ export function CreateAccount(form)
badInputs=res.badInputs;
resolve({message: res.message, inputs: res.badInputs});
return;
}else{
resolve("good")
}
resolve("good");
}).catch(error=>{console.log(error);});
});
@ -44,8 +46,9 @@ export function LoginToAccount(form) {
badInputs=res.badInputs;
resolve({message: res.message, inputs: res.badInputs});
return;
}else{
resolve("good")
}
resolve("good");
}).catch(error=>{console.log(error);});
});
@ -59,6 +62,7 @@ export function CreateForum(form) {
return new Promise(async (resolve, reject)=>{
axios.post(`${protocol}apis.${url}/api/create/forum`, body, {headers: {'X-CSRF-TOKEN': document.querySelector(`meta[name="csrf-token"]`).content, "X-Requested-With":"XMLHttpRequest"}}).then(data=>{
const history = useHistory();
const res = data.data;
if (res.badInputs.length >= 1) {
badInputs=res.badInputs;
@ -69,7 +73,7 @@ export function CreateForum(form) {
});
}
export function LogoutOfAccount() {
/*export function LogoutOfAccount() {
const body = form;
var badInputs = [];
@ -79,4 +83,4 @@ export function LogoutOfAccount() {
resolve("good");
}).catch(error=>{console.log(error);});
}
}*/

View File

@ -3,7 +3,7 @@ import React from 'react';
import { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { PageTransition } from '@steveeeie/react-page-transition';
import { PageTransition, __esModule } from '@steveeeie/react-page-transition';
import { GuardProvider, GuardedRoute } from 'react-router-guards'
import Config from '../config.js';
@ -32,6 +32,7 @@ import Dashboard from '../pages/Dashboard.js';
import Forum from '../pages/Forum.js';
import Post from '../pages/Post.js';
import CreatePost from '../pages/CreatePost.js';
import CreateReply from '../pages/CreateReply.js';
axios.defaults.withCredentials = true
@ -92,6 +93,9 @@ const App = () => {
}else if (to.meta.guest) {
if (!user) {next();}
next.redirect(`/home`);
}else if (to.meta.staff) {
if (user && user.power) {next();}
next.redirect(`/`);
}
}
@ -145,6 +149,10 @@ const App = () => {
<CreatePost user={user}/>
</GuardedRoute>
<GuardedRoute exact path="/forum/reply/:id" meta={{auth: true}}>
<CreateReply user={user}/>
</GuardedRoute>
<Route exact path="/forum/category/:id">
<Forum user={user}/>
</Route>

View File

@ -6,7 +6,7 @@ import React from 'react';
export const Card = (props) => {
return (
<div className="container graphictoria-center-vh">
<div className="card graphictoria-small-card shadow-sm">
<div className={`card graphictoria-small-card shadow-sm ${props.className}`}>
<div className={`card-body ${props.padding? `p5r` : null} text-center`}>
{ props.children }
</div>

View File

@ -2,7 +2,7 @@
// Graphictoria 5
import React, {useState} from 'react';
import { Link } from 'react-router-dom';
import { Link, useHistory } from 'react-router-dom';
import ReCAPTCHA from 'react-google-recaptcha';
import { CreateAccount, LoginToAccount } from '../../Helpers/Auth';
@ -11,8 +11,8 @@ import Loader from '../../Components/Loader';
const LoginForm = (props) => {
const [waitingForSubmission, setWaitingForSubmission] = useState(false);
const [validity, setValidity] = useState({error: false, message: ``, inputs: []});
const history = useHistory();
async function SubmitLogin(form)
{
@ -22,8 +22,9 @@ const LoginForm = (props) => {
setValidity({error: true, message:res.message, inputs: res.inputs});
setTimeout(()=>{setValidity({...validity, error: false, inputs: res.inputs});}, 4000);
return;
}else{
window.location.replace(`/home`);
}
window.location.reload();
}).catch(error=>console.log(error));
setWaitingForSubmission(false);
}

View File

@ -2,7 +2,7 @@
// Graphictoria 5
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { Link, useHistory } from 'react-router-dom';
import ReCAPTCHA from 'react-google-recaptcha';
@ -34,8 +34,8 @@ const RegisterForm = (props) => {
];
const [waitingForSubmission, setWaitingForSubmission] = useState(false);
const [validity, setValidity] = useState({error: false, message: ``, inputs: []});
const history = useHistory();
async function SubmitRegistration(form)
{
@ -46,8 +46,9 @@ const RegisterForm = (props) => {
setValidity({error: true, message:res.message, inputs: res.inputs});
setTimeout(()=>{setValidity({...validity, error: false, inputs: res.inputs});}, 4000);
return;
}else{
window.location.replace(`/home`);
}
window.location.replace(`/home`);
}).catch(error=>console.log(error));
setWaitingForSubmission(false);
}

View File

@ -1,8 +1,8 @@
// © XlXi 2021
// Graphictoria 5
import React, {useState} from 'react';
import { Link } from 'react-router-dom';
import React, {useEffect, useState} from 'react';
import { Link, useHistory } from 'react-router-dom';
import ReCAPTCHA from 'react-google-recaptcha';
import { CreateAccount, LoginToAccount, CreateForum } from '../Helpers/Auth';
@ -11,6 +11,7 @@ import { getCookie } from '../helpers/utils';
import axios from "axios";
import Config from '../config.js';
import { Card, CardTitle } from '../Layouts/Card';
axios.defaults.withCredentials = true
@ -21,7 +22,16 @@ const CreatePost = (props) => {
const [waitingForSubmission, setWaitingForSubmission] = useState(false);
const [validity, setValidity] = useState({error: false, message: ``, inputs: []});
const [categories, setCategoires] = useState({loading: true, categories: []});
const user = props.user;
const history = useHistory();
useEffect(async()=>{
await axios.get(`${protocol}apis.${url}/fetch/categories/post`, null, {headers: {'X-CSRF-TOKEN': document.querySelector(`meta[name="csrf-token"]`).content, "X-Requested-With":"XMLHttpRequest"}}).then(data=>{
const res = data.data;
setCategoires({loading: false, categories: res.categories});
}).catch(error=>{console.log(error);});
}, []);
async function SubmitForm(form)
{
@ -33,18 +43,18 @@ const CreatePost = (props) => {
if (res.badInputs.length >= 1) {
setValidity({error: true, message:res.message, inputs: res.badInputs});
setTimeout(()=>{setValidity({...validity, error: false, inputs: res.badInputs});}, 4000);
return;
}else{
history.push(`/forum/post/${res.post_id}`);
}
window.location.replace(`/forum`);
}).catch(error=>{console.log(error);});
setWaitingForSubmission(false);
}
return (
waitingForSubmission ? <Loader/> :
<div className={`flex column jcc alc w-100`}>
<div className={`flex card card-body column alc w-40`}>
<div className={`flex row`}>
waitingForSubmission && !categories.loading? <Loader/> :
<Card>
<CardTitle>Create a new Post</CardTitle>
<div className="p-2 row">
<div className="col-md-8 mb-2">
{validity.error?
<div className={`px-5 mb-10`}>
@ -56,6 +66,11 @@ const CreatePost = (props) => {
<form onSubmit={(e)=>{e.preventDefault();SubmitForm(new FormData(e.target));}} class="fs">
<input type="username" className={`form-control mb-4 ${(validity.inputs.find(input=>input == `title`)? `is-invalid` : ``)}`} placeholder="Title" name="title"/>
<textarea type="username" className={`form-control mb-4 ${(validity.inputs.find(input=>input == `body`)? `is-invalid` : ``)}`} placeholder="Body" name="body"></textarea>
<select class="form-select" name={`category`}>
{categories.categories.map(category=>(
<option value={category.id}>{category.title}</option>
))}
</select>
<div className="d-flex mb-3">
<ReCAPTCHA
sitekey="6LeyHsUbAAAAAJ9smf-als-hXqrg7a-lHZ950-fL"
@ -70,8 +85,7 @@ const CreatePost = (props) => {
<p>Before you make a post, be sure to read the <Link to={`/forum/rules`}>rules</Link>.</p>
</div>
</div>
</div>
</div>
</Card>
);
};

88
web/resources/js/pages/CreateReply.js vendored Normal file
View File

@ -0,0 +1,88 @@
// © XlXi 2021
// Graphictoria 5
import React, {useEffect, useState} from 'react';
import { Link, useHistory, useParams } from 'react-router-dom';
import ReCAPTCHA from 'react-google-recaptcha';
import { CreateAccount, LoginToAccount, CreateForum } from '../Helpers/Auth';
import Loader from '../Components/Loader';
import { getCookie } from '../helpers/utils';
import { Card, CardTitle } from '../Layouts/Card';
import axios from "axios";
import Config from '../config.js';
axios.defaults.withCredentials = true
var url = Config.BaseUrl.replace('http://', '');
var protocol = Config.Protocol;
const CreateReply = (props) => {
const [waitingForSubmission, setWaitingForSubmission] = useState(false);
const [validity, setValidity] = useState({error: false, message: ``, inputs: []});
const [post, setPost] = useState({loading: true, post: []});
const user = props.user;
const postId = useParams().id;
const history = useHistory();
useEffect(async()=>{
await axios.get(`${protocol}apis.${url}/fetch/post/${postId}`, {headers: {"X-Requested-With":"XMLHttpRequest"}}).then(data=>{
if (!data.data) {history.push(`/forum`);}
const res = data.data;
setPost({loading: false, post: res.post});
}).catch(error=>{console.log(error);});
}, []);
async function SubmitForm(form)
{
form.append('creator_id', user.id);
setWaitingForSubmission(true);
await axios.post(`${protocol}apis.${url}/api/create/reply/${post.post.id}`, form, {headers: {'X-CSRF-TOKEN': document.querySelector(`meta[name="csrf-token"]`).content, "X-Requested-With":"XMLHttpRequest"}}).then(data=>{
const res = data.data;
console.log(res);
if (res.badInputs.length >= 1) {
setValidity({error: true, message:res.message, inputs: res.badInputs});
setTimeout(()=>{setValidity({...validity, error: false, inputs: res.badInputs});}, 4000);
}else{
history.push(`/forum/post/${res.post_id}`);
}
}).catch(error=>{console.log(error);});
setWaitingForSubmission(false);
}
return (
waitingForSubmission && !post.loading? <Loader/> :
<Card>
<CardTitle>Reply to '{post.post.title}'</CardTitle>
<div className="p-2 row">
<div className="col-md-8 mb-2">
{validity.error?
<div className={`px-5 mb-10`}>
<div className={`error-dialog`}>
<p className={`mb-0`}>{validity.message}</p>
</div>
</div>
: null}
<form onSubmit={(e)=>{e.preventDefault();SubmitForm(new FormData(e.target));}} class="fs">
<textarea type="username" className={`form-control mb-4 ${(validity.inputs.find(input=>input == `body`)? `is-invalid` : ``)}`} placeholder="Body" name="body"></textarea>
<div className="d-flex mb-3">
<ReCAPTCHA
sitekey="6LeyHsUbAAAAAJ9smf-als-hXqrg7a-lHZ950-fL"
className="mx-auto"
/>
</div>
<button className="btn btn-primary px-5" type={`submit`}>REPLY!</button><br/>
</form>
</div>
<div className="col">
<h5><bold>Read the rules before replying!</bold></h5>
<p>Before you make a post, be sure to read the <Link to={`/forum/rules`}>rules</Link>.</p>
</div>
</div>
</Card>
);
};
export default CreateReply;

View File

@ -30,7 +30,7 @@ const Forum = (props) => {
const fetchCategories = async () => {
await axios.get(`${protocol}apis.${url}/fetch/categories`, {headers: {"X-Requested-With":"XMLHttpRequest"}}).then(data=>{
setCategoires(data.data.data);
setCategoires(data.data.categories);
}).catch(error=>{console.log(error);});
}
@ -61,7 +61,7 @@ const Forum = (props) => {
<p>{category.description}</p>
{user?
<div className={`flex row justify-content-center`}>
<Link className={`btn btn-success w-20`} to={`/forum/post`}>Create a post</Link>
{category.staffOnly == 1 && !user.power ? null : <Link className={`btn btn-success w-20`} to={`/forum/post`}>Create a post</Link>}
</div>
: null}
</div>
@ -87,8 +87,8 @@ const Forum = (props) => {
<div className={`flex row m-0`}>
<h5 className={`m-0`}>{post.title}</h5>
<div className={`row fs12`}>
<p>Posted by:</p>
<Link to={`/user/${post.creator.id}`}>{post.creator.username}</Link>
<p className={`w-fit-content`}>Posted by:</p>
<Link to={`/user/${post.creator.id}`} className={`w-fit-content padding-none`}>{post.creator.username}</Link>
</div>
</div>
</Link>

View File

@ -23,11 +23,13 @@ const Post = (props) => {
const [state, setState] = useState({offline: false, loading: true});
const [post, setPost] = useState({post: [], replies: {replies: [], meta: [], currentPage: 0}});
const user = props.user;
const history = useHistory();
const fetchPost = async () => {
await axios.get(`${protocol}apis.${url}/fetch/post/${id}`, {headers: {"X-Requested-With":"XMLHttpRequest"}}).then(data=>{
if (!data.data) {window.location.href=`/forum`;return;}
setPost({post: data.data.post, replies: {replies: data.data.replies.data, meta: data.data.replies, currentPage: 0}});
if (!data.data) {history.push(`/forum`);}
const res = data.data;
setPost({post: res.post, replies: {replies: res.replies.data, meta: res.replies, currentPage: 0}});
}).catch(error=>{console.log(error);});
}
@ -42,18 +44,68 @@ const Post = (props) => {
?
<Loader />
:
<div className={`flex jcc alc w-100 column`}>
<div className={`graphic-post w-40`}>
{/* Time&Date goes here. */}
<div className={`flex w-100`}>
<div className={`flex column mr-15`}>
<p>Posted by:</p>
<Link to={`/user/${post.post.creator.id}`}>{post.post.creator.username}</Link>
<div className={`flex w-100 column jcc alc`}>
{post.post.locked == 1?
<div className={`container`}>
<div className={`error-dialog graphictoria-small-card`}>
<p className={`mb-0`}>This post is locked!</p>
</div>
</div>
:
<div className={`container`}>
<div className={`graphictoria-small-card row`}>
{user && user.username? <Link className="btn btn-primary px-5 w-fit-content mb-15" to={`/forum/reply/${post.post.id}`}>Reply</Link> : <p>Sign in to reply!</p>}
</div>
</div>}
<Card>
<div className={`flex w-100 column`}>
<div className={`flex row fs12`}>
<div className={`row w-fit-content`}>
<p className={`w-fit-content`}>Post Title:</p>
<p className={`w-fit-content padding-none`}><i><strong>'{post.post.title}'</strong></i></p>
</div>
<div className={`row w-fit-content`}>
<p className={`w-fit-content`}>Date posted:</p>
<p className={`w-fit-content padding-none`}>{post.post.created_at}</p>
</div>
</div>
<hr/>
<div className={`flex row`}>
<p className={`m-0`}>{post.post.body}</p>
<div className={`flex column jcc alc col-3`}>
<p className={`mb-10`}>[Avatar.]</p>
<Link to={`/user/${post.post.creator.id}`}>{post.post.creator.username}</Link>
</div>
<div className={`col text-left`}>
<p className={`m-0`}>{post.post.body}</p>
</div>
</div>
</div>
</Card>
<div className={`container`}><hr className={`graphictoria-small-card mt-15 mb-15`}/></div>
{post.replies.replies.length <= 0 && post.post.locked != 1? <p className={`w-100 text-center`}>There isn't any replies to this post yet!</p> : null}
<div className={`flex column w-100`}>
{post.replies.replies.map(reply=>(
<Card>
<div className={`flex w-100 column`}>
<div className={`flex row fs12`}>
<div className={`row w-fit-content`}>
<p className={`w-fit-content`}>Date posted:</p>
<p className={`w-fit-content padding-none`}>{reply.created_at}</p>
</div>
</div>
<hr/>
<div className={`flex row`}>
<div className={`flex column jcc alc col-3`}>
<p className={`mb-10`}>[Avatar.]</p>
<Link to={`/user/${reply.creator_id}`}>{reply.creator_name}</Link>
</div>
<div className={`col text-left`}>
<p className={`m-0`}>{reply.body}</p>
</div>
</div>
</div>
</Card>
))}
</div>
</div>
);

View File

@ -898,6 +898,14 @@ a.list-group-item {
flex-direction: column;
}
.w-fit-content {
width: fit-content !important;
}
.h-fit-content {
height: fit-content !important;
}
.mr-15 {
margin-right: 15px;
}
@ -914,6 +922,30 @@ p {
font-size: 12px !important;
}
.padding-none {
padding: 0px !important
}
.text-left {
text-align: left !important;
}
.text-center {
text-align: center !important;
}
.text-right {
text-align: right !important;
}
.mt-15 {
margin-top: 15px !important;
}
.mb-15 {
margin-bottom: 15px !important;
}
.graphic-post {
padding: 1rem 1rem;
text-align: start;

View File

@ -29,6 +29,8 @@ Route::get('/games/metadata', 'GamesController@isAvailable');
Route::get('/fetch/categories', 'Controller@fetchCategories');
Route::get('/fetch/categories/post', 'Controller@fetchCategoriesFP');
Route::get('/fetch/category/{id}', 'Controller@fetchCategory');
Route::get('/fetch/posts/{id}', 'Controller@fetchPosts');
@ -45,6 +47,8 @@ Route::post('/account/login', 'Controller@login');
Route::post('/api/create/forum', 'HomeController@createPost');
Route::post('/api/create/reply/{id}', 'HomeController@createReply');
Route::fallback(function(){
return response('{"errors":[{"code":404,"message":"NotFound"}]}', 404)
->header('Cache-Control', 'private')