Add (jsonld)
This commit is contained in:
@@ -2,10 +2,9 @@
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Http\Request;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
@@ -36,7 +35,7 @@ public function register()
|
||||
$this->renderable(function (NotFoundHttpException $e, $request) {
|
||||
if ($request->is('api/*')) {
|
||||
return response()->json([
|
||||
'status' => -1
|
||||
'status' => -1,
|
||||
], 404);
|
||||
}
|
||||
});
|
||||
@@ -52,21 +51,15 @@ public function register()
|
||||
public function render($request, Throwable $exception)
|
||||
{
|
||||
|
||||
if ($exception instanceof NotFoundHttpException)
|
||||
{
|
||||
if ($exception instanceof NotFoundHttpException) {
|
||||
|
||||
}
|
||||
else if ($exception instanceof AuthenticationException)
|
||||
{
|
||||
} elseif ($exception instanceof AuthenticationException) {
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
inspector()->reportException($exception);
|
||||
}
|
||||
}
|
||||
|
||||
//default laravel response
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,12 +4,9 @@
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
|
||||
class OpenAI
|
||||
{
|
||||
public static function writeArticle($title, $description, $article_type, $min, $max)
|
||||
@@ -62,7 +59,6 @@ public static function createNewArticleTitle($current_title, $supporting_data)
|
||||
|
||||
return in following json format {\"main_keyword\":\"(Main Keyword)\",\"title\":\"(Title in 90-130 letters)\",\"short_title\":\"(Short Title in 30-40 letters)\",\"article_type\":\"(How-tos|Guides|Interview|Review|Commentary|Feature|News|Editorial|Report|Research|Case-study|Overview|Tutorial|Update|Spotlight|Insights)\",\"description\":\"(Cliffhanger SEO description based on main keyword, do not start with action verb)\",\"photo_keywords\":[\"photo keyword 1\",\"photo keyword 2\"]}";
|
||||
|
||||
|
||||
$supporting_data = Str::substr($supporting_data, 0, 2100);
|
||||
|
||||
$user_prompt = "Article Title: {$current_title}\n Article Description: {$supporting_data}\n";
|
||||
@@ -103,29 +99,26 @@ public static function suggestArticleTitles($current_title, $supporting_data, $s
|
||||
public static function chatCompletion($system_prompt, $user_prompt, $model, $max_token = 2500)
|
||||
{
|
||||
try {
|
||||
$response = Http::timeout(800)->withToken(config('platform.ai.openai.api_key'))
|
||||
->post('https://api.openai.com/v1/chat/completions', [
|
||||
'model' => $model,
|
||||
'max_tokens' => $max_token,
|
||||
'messages' => [
|
||||
['role' => 'system', 'content' => $system_prompt],
|
||||
['role' => 'user', 'content' => $user_prompt],
|
||||
],
|
||||
]);
|
||||
$response = Http::timeout(800)->withToken(config('platform.ai.openai.api_key'))
|
||||
->post('https://api.openai.com/v1/chat/completions', [
|
||||
'model' => $model,
|
||||
'max_tokens' => $max_token,
|
||||
'messages' => [
|
||||
['role' => 'system', 'content' => $system_prompt],
|
||||
['role' => 'user', 'content' => $user_prompt],
|
||||
],
|
||||
]);
|
||||
|
||||
$json_response = json_decode($response->body());
|
||||
|
||||
$json_response = json_decode($response->body());
|
||||
$reply = $json_response?->choices[0]?->message?->content;
|
||||
|
||||
$reply = $json_response?->choices[0]?->message?->content;
|
||||
|
||||
return $reply;
|
||||
return $reply;
|
||||
} catch (Exception $e) {
|
||||
Log::error($response->body());
|
||||
inspector()->reportException($e);
|
||||
throw ($e);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
Log::error($response->body());
|
||||
inspector()->reportException($e);
|
||||
throw($e);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
|
||||
|
||||
@@ -5,13 +5,19 @@
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Category;
|
||||
use App\Models\Post;
|
||||
use App\Models\PostCategory;
|
||||
use Artesaos\SEOTools\Facades\SEOTools;
|
||||
use Illuminate\Http\Request;
|
||||
use JsonLd\Context;
|
||||
|
||||
class FrontListController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$breadcrumbs = collect([
|
||||
['name' => 'Home', 'url' => route('front.home')],
|
||||
['name' => 'Latest News', 'url' => null], // or you can set a route for Latest News if there's a specific one
|
||||
]);
|
||||
|
||||
$title = 'Latest News from EchoScoop';
|
||||
|
||||
@@ -23,23 +29,69 @@ public function index(Request $request)
|
||||
|
||||
$posts = Post::where('status', 'publish')->orderBy('published_at', 'desc')->simplePaginate(10) ?? collect();
|
||||
|
||||
return view('front.post_list', compact('posts'));
|
||||
// breadcrumb json ld
|
||||
$listItems = [];
|
||||
|
||||
foreach ($breadcrumbs as $index => $breadcrumb) {
|
||||
$listItems[] = [
|
||||
'name' => $breadcrumb['name'],
|
||||
'url' => $breadcrumb['url'],
|
||||
];
|
||||
}
|
||||
|
||||
$breadcrumb_context = Context::create('breadcrumb_list', [
|
||||
'itemListElement' => $listItems,
|
||||
]);
|
||||
|
||||
return view('front.post_list', compact('posts', 'breadcrumbs', 'breadcrumb_context'));
|
||||
}
|
||||
|
||||
public function category(Request $request, $category_slug)
|
||||
{
|
||||
// Fetch the category by slug
|
||||
$category = Category::where('slug', $category_slug)->first();
|
||||
|
||||
$posts = $category?->posts()->where('status', 'publish')->orderBy('published_at', 'desc')->simplePaginate(10) ?? collect();
|
||||
// Check if the category exists
|
||||
if (! $category) {
|
||||
abort(404, 'Category not found');
|
||||
}
|
||||
|
||||
// Breadcrumb logic
|
||||
$breadcrumbs = collect([['name' => 'Home', 'url' => route('front.home')]]);
|
||||
foreach ($category->ancestors as $ancestor) {
|
||||
$breadcrumbs->push(['name' => $ancestor->name, 'url' => route('front.category', $ancestor->slug)]);
|
||||
}
|
||||
$breadcrumbs->push(['name' => $category->name, 'url' => route('front.category', $category->slug)]);
|
||||
|
||||
// Get the IDs of the category and its descendants
|
||||
$categoryIds = $category->descendants->pluck('id')->push($category->id);
|
||||
|
||||
// Get the posts associated with these category IDs
|
||||
$postIds = PostCategory::whereIn('category_id', $categoryIds)->pluck('post_id');
|
||||
$posts = Post::whereIn('id', $postIds)->where('status', 'publish')->orderBy('published_at', 'desc')->simplePaginate(10);
|
||||
|
||||
$title = $category->name.' News from EchoScoop';
|
||||
|
||||
SEOTools::metatags();
|
||||
SEOTools::twitter();
|
||||
SEOTools::opengraph();
|
||||
SEOTools::jsonLd();
|
||||
SEOTools::setTitle($title, false);
|
||||
SEOTools::jsonLd();
|
||||
|
||||
return view('front.post_list', compact('category', 'posts'));
|
||||
// breadcrumb json ld
|
||||
$listItems = [];
|
||||
|
||||
foreach ($breadcrumbs as $index => $breadcrumb) {
|
||||
$listItems[] = [
|
||||
'name' => $breadcrumb['name'],
|
||||
'url' => $breadcrumb['url'],
|
||||
];
|
||||
}
|
||||
|
||||
$breadcrumb_context = Context::create('breadcrumb_list', [
|
||||
'itemListElement' => $listItems,
|
||||
]);
|
||||
|
||||
return view('front.post_list', compact('category', 'posts', 'breadcrumbs', 'breadcrumb_context'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
use Artesaos\SEOTools\Facades\SEOMeta;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
use Illuminate\Http\Request;
|
||||
use JsonLd\Context;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class FrontPostController extends Controller
|
||||
@@ -25,11 +26,36 @@ public function index(Request $request, $slug)
|
||||
|
||||
//dd($content);
|
||||
$content = $this->injectBootstrapClasses($content);
|
||||
$content = $this->injectTableOfContents($content);
|
||||
$content = $this->injectFeaturedImage($post, $content);
|
||||
$content = $this->injectPublishDateAndAuthor($post, $content);
|
||||
$content = $this->injectTableOfContents($content);
|
||||
|
||||
$post_description = $post->excerpt.' '.$post->title.' by EchoScoop.';
|
||||
|
||||
// Generate breadcrumb data
|
||||
$breadcrumbs = collect([
|
||||
['name' => 'Home', 'url' => route('front.home')],
|
||||
]);
|
||||
|
||||
if ($post->category) {
|
||||
foreach ($post->category->ancestors as $ancestor) {
|
||||
$breadcrumbs->push([
|
||||
'name' => $ancestor->name,
|
||||
'url' => route('front.category', $ancestor->slug),
|
||||
]);
|
||||
}
|
||||
|
||||
$breadcrumbs->push([
|
||||
'name' => $post->category->name,
|
||||
'url' => route('front.category', $post->category->slug),
|
||||
]);
|
||||
}
|
||||
|
||||
$breadcrumbs->push([
|
||||
'name' => $post->title,
|
||||
'url' => url()->current(), // The current page URL; the breadcrumb is not clickable
|
||||
]);
|
||||
|
||||
SEOMeta::setTitle($post->title, false);
|
||||
SEOMeta::setDescription($post_description);
|
||||
SEOMeta::addMeta('article:published_time', $post->published_at->format('Y-m-d'), 'property');
|
||||
@@ -68,7 +94,21 @@ public function index(Request $request, $slug)
|
||||
->addValue('description', $post_description)
|
||||
->addValue('articleBody', trim(preg_replace('/\s\s+/', ' ', strip_tags($content))));
|
||||
|
||||
return view('front.single_post', compact('post', 'content'));
|
||||
// breadcrumb json ld
|
||||
$listItems = [];
|
||||
|
||||
foreach ($breadcrumbs as $index => $breadcrumb) {
|
||||
$listItems[] = [
|
||||
'name' => $breadcrumb['name'],
|
||||
'url' => $breadcrumb['url'],
|
||||
];
|
||||
}
|
||||
|
||||
$breadcrumb_context = Context::create('breadcrumb_list', [
|
||||
'itemListElement' => $listItems,
|
||||
]);
|
||||
|
||||
return view('front.single_post', compact('post', 'content', 'breadcrumbs', 'breadcrumb_context'));
|
||||
}
|
||||
|
||||
private function injectBootstrapClasses($content)
|
||||
@@ -77,7 +117,7 @@ private function injectBootstrapClasses($content)
|
||||
|
||||
// Handle Headings
|
||||
$crawler->filter('h1')->each(function (Crawler $node) {
|
||||
$node->getNode(0)->setAttribute('class', trim($node->attr('class').' display-6 fw-bolder mt-3 mb-4'));
|
||||
$node->getNode(0)->setAttribute('class', trim($node->attr('class').' display-6 fw-bolder mt-3 mb-2'));
|
||||
});
|
||||
|
||||
$crawler->filter('h2')->each(function (Crawler $node) {
|
||||
@@ -171,6 +211,20 @@ private function injectTableOfContents($html)
|
||||
return $updatedHtml;
|
||||
}
|
||||
|
||||
private function injectPublishDateAndAuthor($post, $content)
|
||||
{
|
||||
$publishedAtFormatted = $post->published_at->format('F j, Y');
|
||||
$authorName = $post->author->name;
|
||||
|
||||
// Create the HTML structure for publish date and author
|
||||
$publishInfo = "<div class=\"mb-4\"><span class=\"text-secondary small\">Published on {$publishedAtFormatted} by {$authorName}</span></div>";
|
||||
|
||||
// Inject the publish date and author information after the `h1` tag
|
||||
$content = preg_replace('/(<\/h1>)/', '$1'.$publishInfo, $content, 1);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function injectFeaturedImage($post, $content)
|
||||
{
|
||||
if (! empty($post->featured_image)) {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"spatie/laravel-sitemap": "^6.3",
|
||||
"symfony/dom-crawler": "^6.3",
|
||||
"tightenco/ziggy": "^1.6",
|
||||
"torann/json-ld": "^0.0.19",
|
||||
"watson/active": "^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
|
||||
57
composer.lock
generated
57
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "ac19e61afee15da0e8592f2bfb9acf73",
|
||||
"content-hash": "fb76a666f8ab1204f862fedada072f42",
|
||||
"packages": [
|
||||
{
|
||||
"name": "artesaos/seotools",
|
||||
@@ -7352,6 +7352,61 @@
|
||||
},
|
||||
"time": "2023-01-03T09:29:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "torann/json-ld",
|
||||
"version": "0.0.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Torann/json-ld.git",
|
||||
"reference": "45738178c8eeea28a30925826537e87c3020de5a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Torann/json-ld/zipball/45738178c8eeea28a30925826537e87c3020de5a",
|
||||
"reference": "45738178c8eeea28a30925826537e87c3020de5a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^0.9.4",
|
||||
"phpunit/phpunit": "~5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"JsonLd\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-2-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Daniel Stainback",
|
||||
"email": "torann@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Extremely simple JSON-LD markup generator.",
|
||||
"keywords": [
|
||||
"JSON-LD",
|
||||
"generator",
|
||||
"schema",
|
||||
"structured-data"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Torann/json-ld/issues",
|
||||
"source": "https://github.com/Torann/json-ld/tree/0.0.19"
|
||||
},
|
||||
"time": "2020-03-10T17:25:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "vlucas/phpdotenv",
|
||||
"version": "v5.5.0",
|
||||
|
||||
@@ -185,6 +185,7 @@
|
||||
*/
|
||||
|
||||
'aliases' => Facade::defaultAliases()->merge([
|
||||
'SEOTools' => Artesaos\SEOTools\Facades\SEOTools::class,
|
||||
'SEOMeta' => Artesaos\SEOTools\Facades\SEOMeta::class,
|
||||
'OpenGraph' => Artesaos\SEOTools\Facades\OpenGraph::class,
|
||||
'Twitter' => Artesaos\SEOTools\Facades\TwitterCard::class,
|
||||
|
||||
@@ -12,10 +12,10 @@ class NewCategorySeeder extends Seeder
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$node = Category::create(['name' => 'AI', 'short_name' => 'AI']);
|
||||
$node = Category::create(['name' => 'AI', 'short_name' => 'AI']);
|
||||
|
||||
$parent = Category::find(37);
|
||||
$parent = Category::find(37);
|
||||
|
||||
$node->appendToNode($parent)->save();
|
||||
$node->appendToNode($parent)->save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
import{_ as i}from"./vue-8b92bff6.js";const n={name:"LqipLoader",mounted(){this.initLqipLoading()},methods:{initLqipLoading(){const e=document.getElementsByTagName("img");for(let t=0;t<e.length;t++)e[t].getAttribute("data-src")&&(e[t].onload=function(){this.classList.remove("lqip-blur")},e[t].setAttribute("src",e[t].getAttribute("data-src")))}}};function o(e,t,r,s,a,c){return null}const m=i(n,[["render",o]]);export{m as default};
|
||||
import{_ as i}from"./vue-7fd555b6.js";const n={name:"LqipLoader",mounted(){this.initLqipLoading()},methods:{initLqipLoading(){const e=document.getElementsByTagName("img");for(let t=0;t<e.length;t++)e[t].getAttribute("data-src")&&(e[t].onload=function(){this.classList.remove("lqip-blur")},e[t].setAttribute("src",e[t].getAttribute("data-src")))}}};function o(e,t,r,s,a,c){return null}const m=i(n,[["render",o]]);export{m as default};
|
||||
@@ -1 +1 @@
|
||||
import{_ as o,o as p,c,a as r,b as u,p as i,d as m,e as g,f as _,g as d,v as f,Z as n,h as l}from"./vue-8b92bff6.js";const A={name:"AppAuth"};function $(s,a,t,Z,w,x){return p(),c("div")}const h=o(A,[["render",$]]),e=r({AppAuth:h}),v=Object.assign({});e.use(u());e.use(i,m);e.use(g);e.use(_);e.use(d);e.use(f.ZiggyVue,n);window.Ziggy=n;Object.entries({...v}).forEach(([s,a])=>{const t=s.split("/").pop().replace(/\.\w+$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();e.component(t,l(a))});e.mount("#app");
|
||||
import{_ as o,o as p,c,a as r,b as u,p as i,d as m,e as g,f as _,g as d,v as f,Z as n,h as l}from"./vue-7fd555b6.js";const A={name:"AppAuth"};function $(s,a,t,Z,w,x){return p(),c("div")}const h=o(A,[["render",$]]),e=r({AppAuth:h}),v=Object.assign({});e.use(u());e.use(i,m);e.use(g);e.use(_);e.use(d);e.use(f.ZiggyVue,n);window.Ziggy=n;Object.entries({...v}).forEach(([s,a])=>{const t=s.split("/").pop().replace(/\.\w+$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();e.component(t,l(a))});e.mount("#app");
|
||||
File diff suppressed because one or more lines are too long
BIN
public/build/assets/app-front-98ac14b0.js.gz
Normal file
BIN
public/build/assets/app-front-98ac14b0.js.gz
Normal file
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"_vue-8b92bff6.js": {
|
||||
"_vue-7fd555b6.js": {
|
||||
"css": [
|
||||
"assets/vue-935fc652.css"
|
||||
],
|
||||
"file": "assets/vue-8b92bff6.js"
|
||||
"file": "assets/vue-7fd555b6.js"
|
||||
},
|
||||
"node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff": {
|
||||
"file": "assets/bootstrap-icons-4d4572ef.woff",
|
||||
@@ -50,9 +50,9 @@
|
||||
"src": "resources/fonts/Inter/Inter-Thin.ttf"
|
||||
},
|
||||
"resources/js/app-auth.js": {
|
||||
"file": "assets/app-auth-4b2e1a84.js",
|
||||
"file": "assets/app-auth-f0ef52f1.js",
|
||||
"imports": [
|
||||
"_vue-8b92bff6.js"
|
||||
"_vue-7fd555b6.js"
|
||||
],
|
||||
"isEntry": true,
|
||||
"src": "resources/js/app-auth.js"
|
||||
@@ -61,17 +61,17 @@
|
||||
"dynamicImports": [
|
||||
"resources/js/vue/front/LqipLoader.vue"
|
||||
],
|
||||
"file": "assets/app-front-c970ee86.js",
|
||||
"file": "assets/app-front-98ac14b0.js",
|
||||
"imports": [
|
||||
"_vue-8b92bff6.js"
|
||||
"_vue-7fd555b6.js"
|
||||
],
|
||||
"isEntry": true,
|
||||
"src": "resources/js/app-front.js"
|
||||
},
|
||||
"resources/js/vue/front/LqipLoader.vue": {
|
||||
"file": "assets/LqipLoader-2067e882.js",
|
||||
"file": "assets/LqipLoader-c6f23121.js",
|
||||
"imports": [
|
||||
"_vue-8b92bff6.js"
|
||||
"_vue-7fd555b6.js"
|
||||
],
|
||||
"isDynamicEntry": true,
|
||||
"src": "resources/js/vue/front/LqipLoader.vue"
|
||||
|
||||
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
const Ziggy = {"url":"https:\/\/echoscoop.com","port":null,"defaults":{},"routes":{"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"laravelpwa.manifest":{"uri":"manifest.json","methods":["GET","HEAD"]},"laravelpwa.":{"uri":"offline","methods":["GET","HEAD"]},"ignition.healthCheck":{"uri":"_ignition\/health-check","methods":["GET","HEAD"]},"ignition.executeSolution":{"uri":"_ignition\/execute-solution","methods":["POST"]},"ignition.updateConfig":{"uri":"_ignition\/update-config","methods":["POST"]},"feeds.main":{"uri":"feeds\/posts-feed","methods":["GET","HEAD"]},"front.home":{"uri":"\/","methods":["GET","HEAD"]},"front.terms":{"uri":"terms","methods":["GET","HEAD"]},"front.privacy":{"uri":"privacy","methods":["GET","HEAD"]},"front.disclaimer":{"uri":"disclaimer","methods":["GET","HEAD"]},"front.all":{"uri":"news","methods":["GET","HEAD"]},"front.post":{"uri":"news\/{slug}","methods":["GET","HEAD"]},"front.category":{"uri":"{category_slug}","methods":["GET","HEAD"]}}};
|
||||
const Ziggy = {"url":"https:\/\/echoscoop.com","port":null,"defaults":{},"routes":{"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"laravelpwa.manifest":{"uri":"manifest.json","methods":["GET","HEAD"]},"laravelpwa.":{"uri":"offline","methods":["GET","HEAD"]},"ignition.healthCheck":{"uri":"_ignition\/health-check","methods":["GET","HEAD"]},"ignition.executeSolution":{"uri":"_ignition\/execute-solution","methods":["POST"]},"ignition.updateConfig":{"uri":"_ignition\/update-config","methods":["POST"]},"feeds.main":{"uri":"feeds\/posts-feed","methods":["GET","HEAD"]},"front.home":{"uri":"\/","methods":["GET","HEAD"]},"front.terms":{"uri":"terms","methods":["GET","HEAD"]},"front.privacy":{"uri":"privacy","methods":["GET","HEAD"]},"front.disclaimer":{"uri":"disclaimer","methods":["GET","HEAD"]},"front.all":{"uri":"news","methods":["GET","HEAD"]},"front.post":{"uri":"news\/{slug}","methods":["GET","HEAD"]},"front.category":{"uri":"{category_slug}","methods":["GET","HEAD"],"wheres":{"category_slug":"^(automotive|business|trading|information-technology|marketing|office|telecommunications|food-drink|collectibles|pets|photography|hobbies-gifts|hunting-fishing|law|politics|home-garden|shopping|fashion-clothing|real-estate|family|wedding|immigration|society|education|languages|health|beauty|psychology|wellness|religion-spirituality|tips-tricks|how-to|holiday|world-festivals|travel|outdoors|computer|phones|gadgets|technology|social-networks|ai)$"}}}};
|
||||
|
||||
if (typeof window !== 'undefined' && typeof window.Ziggy !== 'undefined') {
|
||||
Object.assign(Ziggy.routes, window.Ziggy.routes);
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
{!! SEOMeta::generate() !!}
|
||||
{!! OpenGraph::generate() !!}
|
||||
{!! Twitter::generate() !!}
|
||||
{!! JsonLd::generate() !!}
|
||||
{!! JsonLdMulti::generate() !!}
|
||||
{!! SEOTools::generate() !!}
|
||||
<meta property="fb:app_id" content="{{ config('seotools.fb_app_id') }}" />
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
@@ -15,3 +17,4 @@
|
||||
@vite(['resources/sass/app-front.scss', 'resources/js/app-front.js'])
|
||||
@laravelPWA
|
||||
@include('googletagmanager::head')
|
||||
@stack('top_head')
|
||||
|
||||
12
resources/views/front/partials/breadcrumbs.blade.php
Normal file
12
resources/views/front/partials/breadcrumbs.blade.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<nav style="--bs-breadcrumb-divider: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='%236c757d'/%3E%3C/svg%3E");"
|
||||
aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
@foreach ($breadcrumbs as $breadcrumb)
|
||||
@if ($loop->last)
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ $breadcrumb['name'] }}</li>
|
||||
@else
|
||||
<li class="breadcrumb-item"><a href="{{ $breadcrumb['url'] }}">{{ $breadcrumb['name'] }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
</ol>
|
||||
</nav>
|
||||
@@ -1,18 +1,9 @@
|
||||
@extends('front.layouts.app')
|
||||
@section('content')
|
||||
<main class="container">
|
||||
<nav style="--bs-breadcrumb-divider: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='%236c757d'/%3E%3C/svg%3E");"
|
||||
aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{{ route('front.home') }}">Home</a></li>
|
||||
|
||||
@if (isset($category) && !is_null($category))
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ $category->name }}</li>
|
||||
@else
|
||||
<li class="breadcrumb-item active" aria-current="page">Latest News</li>
|
||||
@endif
|
||||
</ol>
|
||||
</nav>
|
||||
@include('front.partials.breadcrumbs')
|
||||
|
||||
<div class="row g-5">
|
||||
<div class="col-md-8">
|
||||
<h1 class="pb-2 fw-normal h2">
|
||||
@@ -47,3 +38,7 @@
|
||||
</div>
|
||||
</main>
|
||||
@endsection
|
||||
|
||||
@push('top_head')
|
||||
{!! $breadcrumb_context !!}
|
||||
@endpush
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
@extends('front.layouts.app')
|
||||
@section('content')
|
||||
<main class="container">
|
||||
<nav style="--bs-breadcrumb-divider: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='%236c757d'/%3E%3C/svg%3E");"
|
||||
aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{{ route('front.home') }}">Home</a></li>
|
||||
|
||||
<li class="breadcrumb-item"><a
|
||||
href="{{ route('front.category', ['category_slug' => $post->category->slug]) }}">{{ $post->category->name }}</a>
|
||||
</li>
|
||||
@include('front.partials.breadcrumbs')
|
||||
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ $post->title }}</li>
|
||||
|
||||
</ol>
|
||||
</nav>
|
||||
<div class="row g-5">
|
||||
<div class="col-md-8">
|
||||
|
||||
@@ -31,3 +21,7 @@
|
||||
</div>
|
||||
</main>
|
||||
@endsection
|
||||
|
||||
@push('top_head')
|
||||
{!! $breadcrumb_context !!}
|
||||
@endpush
|
||||
|
||||
@@ -28,5 +28,5 @@
|
||||
Route::get('/news/{slug}', [App\Http\Controllers\Front\FrontPostController::class, 'index'])->name('front.post');
|
||||
|
||||
Route::get('/{category_slug}', [App\Http\Controllers\Front\FrontListController::class, 'category'])
|
||||
->where('category_slug', '^(automotive|business|trading|information-technology|marketing|office|telecommunications|food-drink|collectibles|pets|photography|hobbies-gifts|hunting-fishing|law|politics|home-garden|shopping|fashion-clothing|real-estate|family|wedding|immigration|society|education|languages|health|beauty|psychology|wellness|religion-spirituality|tips-tricks|how-to|holiday|world-festivals|travel|outdoors|computer|phones|gadgets|technology|social-networks|ai)$')
|
||||
->name('front.category');
|
||||
->where('category_slug', '^(automotive|business|trading|information-technology|marketing|office|telecommunications|food-drink|collectibles|pets|photography|hobbies-gifts|hunting-fishing|law|politics|home-garden|shopping|fashion-clothing|real-estate|family|wedding|immigration|society|education|languages|health|beauty|psychology|wellness|religion-spirituality|tips-tricks|how-to|holiday|world-festivals|travel|outdoors|computer|phones|gadgets|technology|social-networks|ai)$')
|
||||
->name('front.category');
|
||||
|
||||
Reference in New Issue
Block a user