All checks were successful
Frontend CI / build (push) Successful in 1m26s
### Description #### Backend - String and interger can be pass as `id` to `GET` `/post/{id}` - For the posts existed, the default `semantic_id` for them will be `_id`. (e.g. `_1`, `_2`) - Semantic ID should follow the rules: 1. It shouldn't be an integer 1. It should match the pattern: `^[0-9a-zA-Z_\-]+$` <br> |Semantic ID|Result|Note| |-|-|-| |12|X|against with `i`| |-3|X|against with `i`| |3.14|X|against with `ii`| |hello world|X|against with `ii`| |*EMPTY*|X|against with `ii`| |12_34-56|O|| #### Frontend - The href of post preview card becomes the semantic ID. ### Package Changes ```toml regex = "1.12.1" ``` ### Screenshots  ### Reference Resolves #125. ### Checklist - [x] A milestone is set - [x] The related issuse has been linked to this branch Reviewed-on: #134 Co-authored-by: SquidSpirit <squid@squidspirit.com> Co-committed-by: SquidSpirit <squid@squidspirit.com>
93 lines
2.5 KiB
TypeScript
93 lines
2.5 KiB
TypeScript
import {
|
|
LabelViewModel,
|
|
type DehydratedLabelProps,
|
|
} from '$lib/post/adapter/presenter/labelViewModel';
|
|
import type { PostInfo } from '$lib/post/domain/entity/postInfo';
|
|
|
|
export class PostInfoViewModel {
|
|
readonly id: number;
|
|
readonly semanticId: string;
|
|
readonly title: string;
|
|
readonly description: string;
|
|
readonly previewImageUrl: URL;
|
|
readonly labels: readonly LabelViewModel[];
|
|
readonly publishedTime: Date | null;
|
|
|
|
private constructor(props: {
|
|
id: number;
|
|
semanticId: string;
|
|
title: string;
|
|
description: string;
|
|
previewImageUrl: URL;
|
|
labels: readonly LabelViewModel[];
|
|
publishedTime: Date | null;
|
|
}) {
|
|
this.id = props.id;
|
|
this.semanticId = props.semanticId;
|
|
this.title = props.title;
|
|
this.description = props.description;
|
|
this.previewImageUrl = props.previewImageUrl;
|
|
this.labels = props.labels;
|
|
this.publishedTime = props.publishedTime;
|
|
}
|
|
|
|
static fromEntity(postInfo: PostInfo): PostInfoViewModel {
|
|
return new PostInfoViewModel({
|
|
id: postInfo.id,
|
|
semanticId: postInfo.semanticId,
|
|
title: postInfo.title,
|
|
description: postInfo.description,
|
|
previewImageUrl: postInfo.previewImageUrl,
|
|
labels: postInfo.labels.map((label) => LabelViewModel.fromEntity(label)),
|
|
publishedTime: postInfo.publishedTime,
|
|
});
|
|
}
|
|
|
|
static rehydrate(props: DehydratedPostInfoProps): PostInfoViewModel {
|
|
let publishedTime: Date | null = null;
|
|
if (props.publishedTime !== null) {
|
|
publishedTime = new Date(props.publishedTime);
|
|
}
|
|
|
|
return new PostInfoViewModel({
|
|
id: props.id,
|
|
semanticId: props.semanticId,
|
|
title: props.title,
|
|
description: props.description,
|
|
previewImageUrl: new URL(props.previewImageUrl),
|
|
labels: props.labels.map((label) => LabelViewModel.rehydrate(label)),
|
|
publishedTime: publishedTime,
|
|
});
|
|
}
|
|
|
|
get isPublished(): boolean {
|
|
return this.publishedTime !== null;
|
|
}
|
|
|
|
get formattedPublishedTime(): string | null {
|
|
return this.publishedTime?.toISOString().slice(0, 10) ?? null;
|
|
}
|
|
|
|
dehydrate(): DehydratedPostInfoProps {
|
|
return {
|
|
id: this.id,
|
|
semanticId: this.semanticId,
|
|
title: this.title,
|
|
description: this.description,
|
|
previewImageUrl: this.previewImageUrl.href,
|
|
labels: this.labels.map((label) => label.dehydrate()),
|
|
publishedTime: this.publishedTime?.getTime() ?? null,
|
|
};
|
|
}
|
|
}
|
|
|
|
export interface DehydratedPostInfoProps {
|
|
id: number;
|
|
semanticId: string;
|
|
title: string;
|
|
description: string;
|
|
previewImageUrl: string;
|
|
labels: DehydratedLabelProps[];
|
|
publishedTime: number | null;
|
|
}
|