Skip to content

Commit 11f6a14

Browse files
codercatdevAlex Patterson
andauthored
Feature/pro course preview (CodingCatDev#490)
* include pro drafts * show drafts * update pro settings * fix color on pro --------- Co-authored-by: Alex Patterson <alex.patterson@fusionauth.io>
1 parent e4ce111 commit 11f6a14

15 files changed

Lines changed: 453 additions & 180 deletions

File tree

apps/codingcatdev/src/lib/server/content.ts

Lines changed: 108 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,67 @@ import { ContentType, ContentPublished, type Podcast } from '$lib/types';
22
import type { Content, Course } from '$lib/types';
33
import { env } from '$env/dynamic/private';
44
import { fileURLToPath } from 'url';
5-
import { opendirSync } from "fs";
5+
import { opendirSync } from 'fs';
66

77
const LIMIT = 20;
88

99
// Force PREVIEW off by setting false in .env
1010
// Will show for vercel previews unless forced to false
11-
export const preview = env.PREVIEW === "false" ? false : env.VERCEL_ENV === "preview" || import.meta.env.DEV;
11+
export const preview =
12+
env.PREVIEW === 'false' ? false : env.VERCEL_ENV === 'preview' || import.meta.env.DEV;
1213
const prod = import.meta.env.PROD;
1314
const prefix = prod ? '../entries/pages/' : '../../routes/';
1415
const suffix = prod ? '_page.md.js' : '+page.md';
1516

1617
// While developing locally this allows you to see pages without setting up firebase.
17-
export const allowLocal = env.PREVIEW === "false" ? false : import.meta.env.DEV;
18+
export const allowLocal = env.PREVIEW === 'false' ? false : import.meta.env.DEV;
1819

1920
export const getRootPath = (contentType: ContentType, courseDir?: string) => {
20-
2121
// Normal Files
22-
let root = fileURLToPath(new URL(`${prefix}(content-single)/(non-course)/${contentType}`, import.meta.url));
22+
let root = fileURLToPath(
23+
new URL(`${prefix}(content-single)/(non-course)/${contentType}`, import.meta.url)
24+
);
2325
if (contentType === ContentType.course) {
2426
root = fileURLToPath(new URL(`${prefix}(content-single)/${contentType}`, import.meta.url));
2527
}
2628
if (contentType === ContentType.lesson && courseDir) {
27-
root = fileURLToPath(new URL(`${prefix}(content-single)/course/${courseDir}/${contentType}`, import.meta.url));
29+
root = fileURLToPath(
30+
new URL(`${prefix}(content-single)/course/${courseDir}/${contentType}`, import.meta.url)
31+
);
2832
}
2933
return root;
30-
}
34+
};
3135

32-
export const getContentTypeDirectory = async <T>(contentType: ContentType, courseDir?: string, render = false) => {
36+
export const getContentTypeDirectory = async <T>(
37+
contentType: ContentType,
38+
courseDir?: string,
39+
render = false
40+
) => {
3341
const contentList: T[] = [];
3442
const dirs = opendirSync(getRootPath(contentType, courseDir));
3543
for await (const dir of dirs) {
3644
if (dir.isFile()) continue;
37-
const parsed = await parseContentType<T>(`${getRootPath(contentType, courseDir)}/${dir.name}/${suffix}`, render) as T;
45+
const parsed = (await parseContentType<T>(
46+
`${getRootPath(contentType, courseDir)}/${dir.name}/${suffix}`,
47+
render
48+
)) as T;
3849
contentList.push(parsed);
3950
}
4051
return contentList;
41-
}
52+
};
4253

43-
export const getContentTypePath = async <T>(contentType: ContentType, path: string, courseDir?: string, render = false) => {
54+
export const getContentTypePath = async <T>(
55+
contentType: ContentType,
56+
path: string,
57+
courseDir?: string,
58+
render = false,
59+
userPreview = false
60+
) => {
4461
const root = getRootPath(contentType, courseDir);
45-
return await parseContentType<T>(`${root}/${path}/${suffix}`, render) as T;
46-
}
62+
return (await parseContentType<T>(`${root}/${path}/${suffix}`, render, userPreview)) as T;
63+
};
4764

48-
export const parseContentType = (async <T>(path: string, render = false) => {
65+
export const parseContentType = async <T>(path: string, render = false, userPreview = false) => {
4966
const { metadata, default: page } = await import(/* @vite-ignore */ path);
5067
const frontmatter = metadata;
5168

@@ -69,19 +86,21 @@ export const parseContentType = (async <T>(path: string, render = false) => {
6986
content = {
7087
...content,
7188
html: page?.render()?.html
72-
}
89+
};
7390
}
7491

7592
if (frontmatter.type === ContentType.course) {
76-
const lesson = (await listContent<Content>({
77-
contentItems: await getContentTypeDirectory<Content>(ContentType.lesson, frontmatter.slug),
78-
limit: 10000
79-
})).content
93+
const lesson = (
94+
await listContent<Content>({
95+
contentItems: await getContentTypeDirectory<Content>(ContentType.lesson, frontmatter.slug),
96+
limit: 10000,
97+
userPreview
98+
})
99+
).content;
80100
return { ...content, lesson } as T;
81101
}
82-
return { ...content, } as T;
83-
})
84-
102+
return { ...content } as T;
103+
};
85104

86105
/**
87106
* List all content from specified content type
@@ -91,15 +110,17 @@ export const listContent = async <T extends Content>({
91110
contentItems,
92111
after,
93112
limit,
113+
userPreview
94114
}: {
95-
contentItems: T[]
115+
contentItems: T[];
96116
after?: number;
97117
limit?: number;
118+
userPreview?: boolean;
98119
}) => {
99120
const theLimit = limit || LIMIT;
100121
const theAfter = after || 0;
101122

102-
const fullContent = await filterContent<T>({ contentItems })
123+
const fullContent = await filterContent<T>({ contentItems, userPreview });
103124

104125
const content = fullContent.slice(0 + theAfter, theLimit + theAfter);
105126
const total = fullContent.length;
@@ -110,109 +131,109 @@ export const listContent = async <T extends Content>({
110131
};
111132
};
112133

113-
114134
export const filterContent = async <T extends Content>({
115135
contentItems,
136+
userPreview
116137
}: {
117138
contentItems: T[];
139+
userPreview?: boolean;
118140
}) => {
119141
const doc = contentItems
120142
?.filter(
121-
preview ?
122-
() => true
123-
:
124-
(c) => c.published === ContentPublished.published &&
125-
c?.start ? new Date(c.start) <= new Date() : false
126-
143+
preview || userPreview
144+
? () => true
145+
: (c) =>
146+
c.published === ContentPublished.published && c?.start
147+
? new Date(c.start) <= new Date()
148+
: false
149+
)
150+
?.sort(
151+
(a, b) => a?.start && b?.start && new Date(b.start).valueOf() - new Date(a.start).valueOf()
127152
)
128-
?.sort((a, b) => a?.start && b?.start && new Date(b.start).valueOf() - new Date(a.start).valueOf())
129153
?.map((c: Course) => {
130154
return {
131155
...c,
132156
lesson: c?.lesson
133157
?.filter(
134-
preview ?
135-
() => true
136-
:
137-
(l) => l.published === ContentPublished.published && new Date(l.start) <= new Date()
158+
preview || userPreview
159+
? () => true
160+
: (l) => l.published === ContentPublished.published && new Date(l.start) <= new Date()
138161
)
139-
.sort((a, b) => a.weight && b.weight ? a.weight - b.weight : -1)
162+
.sort((a, b) => (a.weight && b.weight ? a.weight - b.weight : -1))
140163
};
141164
}) as unknown as T[];
142165

143166
return [...doc];
144167
};
145168

146-
147169
/**
148170
* List all content from specified content type by author
149171
* */
150-
export const listContentByAuthor = async <T extends Content>({ authorSlug, contentItems }:
151-
{
152-
authorSlug: string,
153-
contentItems: T[];
154-
}) => {
172+
export const listContentByAuthor = async <T extends Content>({
173+
authorSlug,
174+
contentItems
175+
}: {
176+
authorSlug: string;
177+
contentItems: T[];
178+
}) => {
155179
const content = contentItems.filter(
156-
preview ?
157-
(c) =>
158-
c.authors?.filter((g) => g == authorSlug)?.length
159-
:
160-
(c) =>
161-
c.authors?.filter((g) => g == authorSlug)?.length &&
180+
preview
181+
? (c) => c.authors?.filter((g) => g == authorSlug)?.length
182+
: (c) =>
183+
c.authors?.filter((g) => g == authorSlug)?.length &&
162184
c.published === ContentPublished.published &&
163-
c?.start ? new Date(c.start) <= new Date() : false
164-
165-
)
166-
return [
167-
...content,
168-
];
185+
c?.start
186+
? new Date(c.start) <= new Date()
187+
: false
188+
);
189+
return [...content];
169190
};
170191

171192
/**
172193
* List all content from specified content type by sponsor
173194
* */
174-
export const listContentBySponsor = async <T extends Content>({ sponsorSlug, contentItems }:
175-
{
176-
sponsorSlug: string,
177-
contentItems: T[];
178-
}) => {
195+
export const listContentBySponsor = async <T extends Content>({
196+
sponsorSlug,
197+
contentItems
198+
}: {
199+
sponsorSlug: string;
200+
contentItems: T[];
201+
}) => {
179202
const content = contentItems.filter(
180-
preview ?
181-
(c) =>
182-
c.sponsors?.filter((g) => g == sponsorSlug)?.length
183-
:
184-
(c) =>
185-
c.sponsors?.filter((g) => g == sponsorSlug)?.length &&
203+
preview
204+
? (c) => c.sponsors?.filter((g) => g == sponsorSlug)?.length
205+
: (c) =>
206+
c.sponsors?.filter((g) => g == sponsorSlug)?.length &&
186207
c.published === ContentPublished.published &&
187-
c?.start ? new Date(c.start) <= new Date() : false
188-
)
189-
return [
190-
...content,
191-
];
208+
c?.start
209+
? new Date(c.start) <= new Date()
210+
: false
211+
);
212+
return [...content];
192213
};
193214

194215
/**
195216
* Get podcast by guest slug
196217
* */
197-
export const listContentByGuest = async ({ slug, podcastItems }:
198-
{
199-
slug: string,
200-
podcastItems: Podcast[];
201-
}) => {
218+
export const listContentByGuest = async ({
219+
slug,
220+
podcastItems
221+
}: {
222+
slug: string;
223+
podcastItems: Podcast[];
224+
}) => {
202225
const podcasts = podcastItems
203226
.filter(
204-
preview ?
205-
(c) =>
206-
c.guests?.filter((g) => g == slug)?.length
207-
:
208-
(c) =>
209-
c.guests?.filter((g) => g == slug)?.length &&
227+
preview
228+
? (c) => c.guests?.filter((g) => g == slug)?.length
229+
: (c) =>
230+
c.guests?.filter((g) => g == slug)?.length &&
210231
c.published === ContentPublished.published &&
211-
c?.start ? new Date(c.start) <= new Date() : false
232+
c?.start
233+
? new Date(c.start) <= new Date()
234+
: false
212235
)
213-
.sort((a, b) => new Date(b.start).valueOf() - new Date(a.start).valueOf())
236+
.sort((a, b) => new Date(b.start).valueOf() - new Date(a.start).valueOf());
214237

215-
return [
216-
...podcasts,
217-
];
238+
return [...podcasts];
218239
};

0 commit comments

Comments
 (0)