Типы блог-постов
This commit is contained in:
parent
0643f48189
commit
451d064dea
4 changed files with 50 additions and 6 deletions
5
src/app.d.ts
vendored
5
src/app.d.ts
vendored
|
|
@ -18,13 +18,18 @@ declare global {
|
||||||
|
|
||||||
type MdsvexResolver = () => Promise<MdsvexFile>;
|
type MdsvexResolver = () => Promise<MdsvexFile>;
|
||||||
|
|
||||||
|
type BlogPostType = 'article' | 'update' | 'event';
|
||||||
|
|
||||||
interface BlogPost {
|
interface BlogPost {
|
||||||
slug: string;
|
slug: string;
|
||||||
|
type?: BlogPostType;
|
||||||
title: string;
|
title: string;
|
||||||
thumbnail?: string;
|
thumbnail?: string;
|
||||||
thumbnailAlt?: string;
|
thumbnailAlt?: string;
|
||||||
date?: string;
|
date?: string;
|
||||||
dateChanged?: string;
|
dateChanged?: string;
|
||||||
|
dateEventFrom?: string;
|
||||||
|
dateEventTo?: string;
|
||||||
description: string;
|
description: string;
|
||||||
publisher: string;
|
publisher: string;
|
||||||
published?: boolean;
|
published?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -7,18 +7,25 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { BLOG_POST_FRESHNESS_MILLIS } from '$lib/util/Blogs';
|
import {
|
||||||
|
BLOG_POST_FRESHNESS_MILLIS,
|
||||||
|
blogPostTypeToIcon,
|
||||||
|
blogPostTypeToString
|
||||||
|
} from '$lib/util/Blogs';
|
||||||
import DateWidget from '$lib/components/DateWidget.svelte';
|
import DateWidget from '$lib/components/DateWidget.svelte';
|
||||||
|
import Icon from '@iconify/svelte';
|
||||||
|
|
||||||
export let post: App.BlogPost;
|
export let post: App.BlogPost;
|
||||||
export let size: BlogCardSize = BlogCardSize.Both;
|
export let size: BlogCardSize = BlogCardSize.Both;
|
||||||
|
|
||||||
|
const type: App.BlogPostType = post.type ?? 'article';
|
||||||
const dateNow = new Date().valueOf();
|
const dateNow = new Date().valueOf();
|
||||||
const isPostNew = dateNow - new Date(post.date!).valueOf() <= BLOG_POST_FRESHNESS_MILLIS;
|
const isPostNew = dateNow - new Date(post.date!).valueOf() <= BLOG_POST_FRESHNESS_MILLIS;
|
||||||
const isPostUpdated =
|
const isPostUpdated =
|
||||||
post.dateChanged != null &&
|
post.dateChanged != null &&
|
||||||
dateNow - new Date(post.dateChanged).valueOf() <= BLOG_POST_FRESHNESS_MILLIS;
|
dateNow - new Date(post.dateChanged).valueOf() <= BLOG_POST_FRESHNESS_MILLIS;
|
||||||
const isPostFresh = isPostNew || isPostUpdated;
|
const isPostFresh = isPostNew || isPostUpdated;
|
||||||
|
// TODO: rndtrash: события и их актуальность
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rndtrash: пришлось дублировать классы с модификатором и без, потому что Tailwind просто не понимает,
|
* rndtrash: пришлось дублировать классы с модификатором и без, потому что Tailwind просто не понимает,
|
||||||
|
|
@ -59,7 +66,7 @@
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="relative w-full basis-auto overflow-hidden
|
class="relative w-full basis-auto overflow-hidden
|
||||||
{shortClass('h-32')}
|
{shortClass('h-32 md:h-48')}
|
||||||
{fullClass('h-auto basis-1/3', 'sm:h-auto sm:basis-1/3')}"
|
{fullClass('h-auto basis-1/3', 'sm:h-auto sm:basis-1/3')}"
|
||||||
>
|
>
|
||||||
{#if post.thumbnail}
|
{#if post.thumbnail}
|
||||||
|
|
@ -79,7 +86,7 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex w-full flex-col justify-center p-4 break-words md:p-8">
|
<div class="flex w-full flex-col justify-center p-4 break-words">
|
||||||
<div class="flex flex-row flex-wrap justify-start gap-4 pb-2">
|
<div class="flex flex-row flex-wrap justify-start gap-4 pb-2">
|
||||||
<DateWidget
|
<DateWidget
|
||||||
class={post.dateChanged ? shortClass('hidden', 'not-sm:hidden') : ''}
|
class={post.dateChanged ? shortClass('hidden', 'not-sm:hidden') : ''}
|
||||||
|
|
@ -94,6 +101,12 @@
|
||||||
highlight={isPostUpdated}
|
highlight={isPostUpdated}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
<div class="flex items-center gap-2 p-1 text-lg font-bold">
|
||||||
|
<Icon icon={blogPostTypeToIcon(type)} width={28} height={28} />
|
||||||
|
<span>
|
||||||
|
{blogPostTypeToString(type)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="text-3xl font-bold">{post.title}</h2>
|
<h2 class="text-3xl font-bold">{post.title}</h2>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import path from 'path';
|
|
||||||
|
|
||||||
export const THUMBNAIL_DEFAULT = "https://teasanctuary.ru/common/background-day.webp";
|
export const THUMBNAIL_DEFAULT = "https://teasanctuary.ru/common/background-day.webp";
|
||||||
export const BLOG_POST_FRESHNESS_MILLIS = 3 * 24 * 60 * 60 * 1000; // 3 дня
|
export const BLOG_POST_FRESHNESS_MILLIS = 3 * 24 * 60 * 60 * 1000; // 3 дня
|
||||||
|
|
||||||
|
|
@ -60,4 +58,24 @@ export function resolveBlogPath(slug?: string, src?: string) {
|
||||||
return src.startsWith('http://') || src.startsWith('https://')
|
return src.startsWith('http://') || src.startsWith('https://')
|
||||||
? src
|
? src
|
||||||
: `/blog/${slug}/${src}`;
|
: `/blog/${slug}/${src}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bptToString: Record<App.BlogPostType, string> = {
|
||||||
|
'article': 'Заметка',
|
||||||
|
'event': 'Событие',
|
||||||
|
'update': 'Обновление'
|
||||||
|
};
|
||||||
|
|
||||||
|
const bptToIcon: Record<App.BlogPostType, string> = {
|
||||||
|
'article': 'material-symbols:article',
|
||||||
|
'event': 'material-symbols:event',
|
||||||
|
'update': 'material-symbols:autorenew'
|
||||||
|
};
|
||||||
|
|
||||||
|
export function blogPostTypeToString(type: App.BlogPostType): string {
|
||||||
|
return bptToString[type] ?? bptToString['article'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function blogPostTypeToIcon(type: App.BlogPostType): string {
|
||||||
|
return bptToIcon[type] ?? bptToIcon['article'];
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
import InfoBlock from '$src/lib/components/InfoBlock.svelte';
|
import InfoBlock from '$src/lib/components/InfoBlock.svelte';
|
||||||
import Icon from '@iconify/svelte';
|
import Icon from '@iconify/svelte';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
import { blogPostTypeToIcon, blogPostTypeToString } from '$src/lib/util/Blogs';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
|
|
@ -14,6 +15,7 @@
|
||||||
: typeof data.blogPost.authors === 'string'
|
: typeof data.blogPost.authors === 'string'
|
||||||
? [data.blogPost.authors]
|
? [data.blogPost.authors]
|
||||||
: data.blogPost.authors;
|
: data.blogPost.authors;
|
||||||
|
const type: App.BlogPostType = data.blogPost.type ?? 'article';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<base target="_blank" />
|
<base target="_blank" />
|
||||||
|
|
@ -44,6 +46,12 @@
|
||||||
{#if data.blogPost.dateChanged}
|
{#if data.blogPost.dateChanged}
|
||||||
<DateWidget dateString={data.blogPost.dateChanged} type="updated" />
|
<DateWidget dateString={data.blogPost.dateChanged} type="updated" />
|
||||||
{/if}
|
{/if}
|
||||||
|
<div class="flex items-center gap-2 p-1 text-lg font-bold">
|
||||||
|
<Icon icon={blogPostTypeToIcon(type)} width={28} height={28} />
|
||||||
|
<span>
|
||||||
|
{blogPostTypeToString(type)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
{#each authors as author}
|
{#each authors as author}
|
||||||
<!-- TODO: rndtrash: из-за 404 не даёт собрать сайт. href="/team/{author}" -->
|
<!-- TODO: rndtrash: из-за 404 не даёт собрать сайт. href="/team/{author}" -->
|
||||||
<a class="flex items-center gap-2 p-1 text-lg font-bold" href="#">
|
<a class="flex items-center gap-2 p-1 text-lg font-bold" href="#">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue