add new routing
This commit is contained in:
216
src/components/ArchivePagination.astro
Normal file
216
src/components/ArchivePagination.astro
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
baseUrl: string;
|
||||||
|
page: number;
|
||||||
|
hasNextPage: boolean;
|
||||||
|
window?: number; // сколько страниц вокруг текущей
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
baseUrl,
|
||||||
|
page,
|
||||||
|
hasNextPage,
|
||||||
|
window = 2,
|
||||||
|
} = Astro.props;
|
||||||
|
|
||||||
|
const pageUrl = (p: number) =>
|
||||||
|
p === 1 ? baseUrl : `${baseUrl}/page/${p}`;
|
||||||
|
|
||||||
|
// рассчитываем диапазон
|
||||||
|
const start = Math.max(1, page - window);
|
||||||
|
const end = page + window;
|
||||||
|
---
|
||||||
|
|
||||||
|
<nav class="pagination" aria-label="Pagination">
|
||||||
|
<ul>
|
||||||
|
<!-- prev -->
|
||||||
|
{page > 1 && (
|
||||||
|
<li>
|
||||||
|
<a href={pageUrl(page - 1)} rel="prev">←</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<!-- первая -->
|
||||||
|
{start > 1 && (
|
||||||
|
<>
|
||||||
|
<li><a href={pageUrl(1)}>1</a></li>
|
||||||
|
{start > 2 && <li class="dots">…</li>}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<!-- центральные -->
|
||||||
|
{Array.from({ length: end - start + 1 }, (_, i) => start + i).map(p => (
|
||||||
|
<li class={p === page ? 'active' : ''}>
|
||||||
|
<a
|
||||||
|
href={pageUrl(p)}
|
||||||
|
aria-current={p === page ? 'page' : undefined}
|
||||||
|
>
|
||||||
|
{p}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<!-- следующая -->
|
||||||
|
{hasNextPage && (
|
||||||
|
<>
|
||||||
|
<li class="dots">…</li>
|
||||||
|
<li>
|
||||||
|
<a href={pageUrl(page + window + 1)}>
|
||||||
|
{page + window + 1}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<!-- next -->
|
||||||
|
{hasNextPage && (
|
||||||
|
<li>
|
||||||
|
<a href={pageUrl(page + 1)} rel="next">→</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
/* Базовые стили пагинатора */
|
||||||
|
.pagination {
|
||||||
|
margin: 2rem 0;
|
||||||
|
padding: 1rem 0;
|
||||||
|
border-top: 1px solid #eaeaea;
|
||||||
|
border-bottom: 1px solid #eaeaea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination ul {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Общие стили для элементов пагинации */
|
||||||
|
.pagination li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #2c3e50;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
font-weight: 500;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination a:hover {
|
||||||
|
background-color: #e9ecef;
|
||||||
|
border-color: #d0d7de;
|
||||||
|
color: #1a365d;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Активная страница */
|
||||||
|
.pagination li.active a {
|
||||||
|
background-color: #1a365d;
|
||||||
|
color: white;
|
||||||
|
border-color: #1a365d;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination li.active a:hover {
|
||||||
|
transform: none;
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: #1a365d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Многоточие */
|
||||||
|
.pagination li.dots {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
color: #6c757d;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Стрелки (предыдущая/следующая) */
|
||||||
|
.pagination a[rel="prev"],
|
||||||
|
.pagination a[rel="next"] {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
color: #495057;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
min-width: 46px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination a[rel="prev"]:hover,
|
||||||
|
.pagination a[rel="next"]:hover {
|
||||||
|
background-color: #f1f3f5;
|
||||||
|
color: #1a365d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Для первой и последней страницы (если есть отдельные классы) */
|
||||||
|
.pagination li:first-child a,
|
||||||
|
.pagination li:last-child a {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Адаптивность */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.pagination ul {
|
||||||
|
gap: 0.25rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination a {
|
||||||
|
min-width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination li.dots {
|
||||||
|
min-width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Фокус для доступности */
|
||||||
|
.pagination a:focus {
|
||||||
|
outline: 2px solid #1a365d;
|
||||||
|
outline-offset: 2px;
|
||||||
|
background-color: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Отключенные состояния (если понадобятся в будущем) */
|
||||||
|
.pagination li.disabled a {
|
||||||
|
color: #adb5bd;
|
||||||
|
cursor: not-allowed;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination li.disabled a:hover {
|
||||||
|
transform: none;
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
import FooterMenu from '@components/FooterMenu.astro';
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
publicationName: string;
|
publicationName: string;
|
||||||
organization: string;
|
organization: string;
|
||||||
@@ -90,6 +94,8 @@ const footerId = `footer-profile`;
|
|||||||
<li><a href="">Правила применения рекомендательных технологий</a></li>
|
<li><a href="">Правила применения рекомендательных технологий</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<FooterMenu />
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
import Stores from './LazyStores.astro';
|
import Stores from './LazyStores.astro';
|
||||||
|
import MainMenu from '@components/MainMenu.astro';
|
||||||
|
|
||||||
const MENU_ID = 103245;
|
const MENU_ID = 103245;
|
||||||
let menuItems = [];
|
let menuItems = [];
|
||||||
@@ -14,6 +15,8 @@
|
|||||||
<Stores />
|
<Stores />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<MainMenu menuId={MENU_ID} />
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,71 +1,308 @@
|
|||||||
|
// lib/api/menu-api.ts
|
||||||
|
|
||||||
import { fetchGraphQL } from './graphql-client.js';
|
import { fetchGraphQL } from './graphql-client.js';
|
||||||
|
|
||||||
|
export interface MenuItem {
|
||||||
interface MenuItemNode {
|
id: string;
|
||||||
|
databaseId: number;
|
||||||
uri: string;
|
uri: string;
|
||||||
url: string;
|
url: string;
|
||||||
order: number;
|
order: number;
|
||||||
label: string;
|
label: string;
|
||||||
|
parentId: string | null;
|
||||||
|
target: string;
|
||||||
|
cssClasses: string[];
|
||||||
|
description: string;
|
||||||
|
childItems?: {
|
||||||
|
nodes: MenuItem[];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MenuNode {
|
export interface Menu {
|
||||||
|
id: string;
|
||||||
|
databaseId: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
slug: string;
|
||||||
|
locations: string[];
|
||||||
menuItems: {
|
menuItems: {
|
||||||
nodes: MenuItemNode[];
|
nodes: MenuItem[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MenusResponse {
|
export type MenuIdentifier =
|
||||||
menus: {
|
| { id: number } // По ID меню
|
||||||
nodes: MenuNode[];
|
| { location: string } // По локации
|
||||||
};
|
| { slug: string } // По слагу
|
||||||
|
| { name: string }; // По имени
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить меню по идентификатору
|
||||||
|
*/
|
||||||
|
export async function fetchMenu(identifier: MenuIdentifier): Promise<Menu | null> {
|
||||||
|
try {
|
||||||
|
// Определяем тип запроса на основе переданного идентификатора
|
||||||
|
if ('id' in identifier) {
|
||||||
|
return await fetchMenuById(identifier.id);
|
||||||
|
}
|
||||||
|
if ('location' in identifier) {
|
||||||
|
return await fetchMenuByLocation(identifier.location);
|
||||||
|
}
|
||||||
|
if ('slug' in identifier) {
|
||||||
|
return await fetchMenuBySlug(identifier.slug);
|
||||||
|
}
|
||||||
|
if ('name' in identifier) {
|
||||||
|
return await fetchMenuByName(identifier.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching menu:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get navigation menu from WordPress
|
* Получить меню по ID (самый надежный способ)
|
||||||
*/
|
*/
|
||||||
export async function navQuery(): Promise<MenusResponse> {
|
async function fetchMenuById(id: number): Promise<Menu | null> {
|
||||||
try {
|
const query = `
|
||||||
const query = `{
|
query GetMenuById($id: ID!) {
|
||||||
menus(where: {location: PRIMARY}) {
|
menu(id: $id, idType: DATABASE_ID) {
|
||||||
nodes {
|
id
|
||||||
|
databaseId
|
||||||
name
|
name
|
||||||
menuItems {
|
slug
|
||||||
|
locations
|
||||||
|
menuItems(first: 100) {
|
||||||
nodes {
|
nodes {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
uri
|
uri
|
||||||
url
|
url
|
||||||
order
|
order
|
||||||
label
|
label
|
||||||
|
parentId
|
||||||
|
target
|
||||||
|
cssClasses
|
||||||
|
description
|
||||||
|
childItems(first: 50) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
|
label
|
||||||
|
uri
|
||||||
|
url
|
||||||
|
order
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`;
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
return await executeQuery<MenusResponse>(query, {}, "navigation");
|
const variables = { id };
|
||||||
} catch (error) {
|
const data = await fetchGraphQL(query, variables);
|
||||||
log.error("Error fetching nav: " + error);
|
|
||||||
// Return fallback data for development
|
if (data?.menu) {
|
||||||
return {
|
return {
|
||||||
menus: {
|
...data.menu,
|
||||||
nodes: [
|
menuItems: data.menu.menuItems || { nodes: [] }
|
||||||
{
|
|
||||||
name: "Primary",
|
|
||||||
menuItems: {
|
|
||||||
nodes: [
|
|
||||||
{ uri: "/", url: "/", order: 1, label: "Home" },
|
|
||||||
{ uri: "/about/", url: "/about/", order: 2, label: "About" },
|
|
||||||
{
|
|
||||||
uri: "/contact/",
|
|
||||||
url: "/contact/",
|
|
||||||
order: 3,
|
|
||||||
label: "Contact",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить меню по локации
|
||||||
|
*/
|
||||||
|
async function fetchMenuByLocation(location: string): Promise<Menu | null> {
|
||||||
|
const query = `
|
||||||
|
query GetMenuByLocation($location: MenuLocationEnum!) {
|
||||||
|
menus(where: { location: $location }, first: 1) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
locations
|
||||||
|
menuItems(first: 100) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
|
uri
|
||||||
|
url
|
||||||
|
order
|
||||||
|
label
|
||||||
|
parentId
|
||||||
|
target
|
||||||
|
cssClasses
|
||||||
|
description
|
||||||
|
childItems(first: 50) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
|
label
|
||||||
|
uri
|
||||||
|
url
|
||||||
|
order
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const variables = { location };
|
||||||
|
const data = await fetchGraphQL(query, variables);
|
||||||
|
return data?.menus?.nodes?.[0] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить меню по слагу
|
||||||
|
*/
|
||||||
|
async function fetchMenuBySlug(slug: string): Promise<Menu | null> {
|
||||||
|
const query = `
|
||||||
|
query GetMenuBySlug($slug: String!) {
|
||||||
|
menus(where: { slug: $slug }, first: 1) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
locations
|
||||||
|
menuItems(first: 100) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
|
uri
|
||||||
|
url
|
||||||
|
order
|
||||||
|
label
|
||||||
|
parentId
|
||||||
|
target
|
||||||
|
cssClasses
|
||||||
|
description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const variables = { slug };
|
||||||
|
const data = await fetchGraphQL(query, variables);
|
||||||
|
return data?.menus?.nodes?.[0] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить меню по имени
|
||||||
|
*/
|
||||||
|
async function fetchMenuByName(name: string): Promise<Menu | null> {
|
||||||
|
const query = `
|
||||||
|
query GetMenuByName($name: String!) {
|
||||||
|
menus(where: { name: $name }, first: 1) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
locations
|
||||||
|
menuItems(first: 100) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
databaseId
|
||||||
|
uri
|
||||||
|
url
|
||||||
|
order
|
||||||
|
label
|
||||||
|
parentId
|
||||||
|
target
|
||||||
|
cssClasses
|
||||||
|
description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const variables = { name };
|
||||||
|
const data = await fetchGraphQL(query, variables);
|
||||||
|
return data?.menus?.nodes?.[0] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Преобразовать плоский список элементов меню в иерархическую структуру
|
||||||
|
*/
|
||||||
|
export function buildMenuHierarchy(menuItems: MenuItem[]): MenuItem[] {
|
||||||
|
const itemsMap = new Map<string, MenuItem>();
|
||||||
|
const rootItems: MenuItem[] = [];
|
||||||
|
|
||||||
|
// Создаем map всех элементов
|
||||||
|
menuItems.forEach(item => {
|
||||||
|
itemsMap.set(item.id, {
|
||||||
|
...item,
|
||||||
|
childItems: { nodes: [] }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Строим иерархию
|
||||||
|
menuItems.forEach(item => {
|
||||||
|
const menuItem = itemsMap.get(item.id)!;
|
||||||
|
|
||||||
|
if (item.parentId && itemsMap.has(item.parentId)) {
|
||||||
|
const parent = itemsMap.get(item.parentId)!;
|
||||||
|
if (!parent.childItems) {
|
||||||
|
parent.childItems = { nodes: [] };
|
||||||
|
}
|
||||||
|
parent.childItems.nodes.push(menuItem);
|
||||||
|
} else {
|
||||||
|
rootItems.push(menuItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Сортируем элементы по order
|
||||||
|
const sortByOrder = (items: MenuItem[]) =>
|
||||||
|
items.sort((a, b) => a.order - b.order);
|
||||||
|
|
||||||
|
// Рекурсивно сортируем все уровни
|
||||||
|
function sortRecursive(items: MenuItem[]) {
|
||||||
|
sortByOrder(items);
|
||||||
|
items.forEach(item => {
|
||||||
|
if (item.childItems?.nodes.length) {
|
||||||
|
sortRecursive(item.childItems.nodes);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sortRecursive(rootItems);
|
||||||
|
return rootItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить меню в виде иерархической структуры
|
||||||
|
*/
|
||||||
|
export async function getHierarchicalMenu(identifier: MenuIdentifier): Promise<MenuItem[]> {
|
||||||
|
const menu = await fetchMenu(identifier);
|
||||||
|
if (!menu || !menu.menuItems?.nodes?.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildMenuHierarchy(menu.menuItems.nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить меню в виде плоского списка
|
||||||
|
*/
|
||||||
|
export async function getFlatMenu(identifier: MenuIdentifier): Promise<MenuItem[]> {
|
||||||
|
const menu = await fetchMenu(identifier);
|
||||||
|
if (!menu || !menu.menuItems?.nodes?.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return menu.menuItems.nodes.sort((a, b) => a.order - b.order);
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,9 @@ export async function fetchGraphQL(query, variables = {}) {
|
|||||||
|
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
|
|
||||||
|
console.log("Query:\n", query);
|
||||||
|
console.log("Variables:\n", JSON.stringify(variables, null, 2));
|
||||||
|
|
||||||
if (json.errors) {
|
if (json.errors) {
|
||||||
|
|
||||||
// Выводим полный запрос и переменные для IDE
|
// Выводим полный запрос и переменные для IDE
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
---
|
---
|
||||||
import { fetchCategory } from '@api/categories';
|
|
||||||
|
|
||||||
import MainLayout from '@layouts/MainLayout.astro';
|
import MainLayout from '@layouts/MainLayout.astro';
|
||||||
import CategoryArchive from '@templates/CategoryArchive.astro';
|
import { getNodeByURI, getCategoryPosts } from '@lib/api/all';
|
||||||
import { getCategory } from '@api/categories';
|
|
||||||
import { getArchivePostsById } from '@api/archiveById';
|
|
||||||
|
|
||||||
export const prerender = false; // ISR
|
export const prerender = false;
|
||||||
//export const revalidate = 60;
|
|
||||||
|
|
||||||
const { slug } = Astro.params;
|
const { slug } = Astro.params;
|
||||||
const pathArray = Array.isArray(slug) ? slug : [slug];
|
const uri = slug ? `/${slug}` : '/';
|
||||||
|
|
||||||
|
let response;
|
||||||
|
let node = null;
|
||||||
|
|
||||||
// Получаем категорию по цепочке slug
|
try {
|
||||||
const category = await getCategory(pathArray);
|
response = await getNodeByURI(uri);
|
||||||
if (!category) return Astro.redirect('/404');
|
node = response?.nodeByUri;
|
||||||
|
} catch (error) {
|
||||||
const perPage = 20;
|
console.error('Error fetching node:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISR кэширование
|
||||||
|
//Astro.response.headers.set(
|
||||||
|
// 'Cache-Control',
|
||||||
|
// 'public, s-maxage=3600, stale-while-revalidate=86400'
|
||||||
|
//);
|
||||||
---
|
---
|
||||||
|
|
||||||
<MainLayout title={category.name}>
|
Article
|
||||||
<h1>{category.name}</h1>
|
<p>{uri}</p>
|
||||||
</MainLayout>
|
|
||||||
|
|||||||
30
src/pages/news/[...slug].astro
Normal file
30
src/pages/news/[...slug].astro
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
import MainLayout from '@layouts/MainLayout.astro';
|
||||||
|
import { getNodeByURI, getCategoryPosts } from '@lib/api/all';
|
||||||
|
|
||||||
|
export const prerender = false;
|
||||||
|
|
||||||
|
const { slug } = Astro.params;
|
||||||
|
const uri = slug ? `/${slug}` : '/';
|
||||||
|
|
||||||
|
let response;
|
||||||
|
let node = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
response = await getNodeByURI(uri);
|
||||||
|
node = response?.nodeByUri;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching node:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISR кэширование
|
||||||
|
//Astro.response.headers.set(
|
||||||
|
// 'Cache-Control',
|
||||||
|
// 'public, s-maxage=3600, stale-while-revalidate=86400'
|
||||||
|
//);
|
||||||
|
---
|
||||||
|
|
||||||
|
News
|
||||||
|
|
||||||
|
<p>{uri}</p>
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ body {
|
|||||||
.container{
|
.container{
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 1200px;
|
width: 1200px;
|
||||||
|
padding-bottom: 60px; /* Подберите высоту под ваш свернутый футер */
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-info{
|
.header-info{
|
||||||
|
|||||||
Reference in New Issue
Block a user