Fix Jumpstart Dashboard, API, and Fetchers to support real-time generation

This commit is contained in:
cawcenter
2025-12-13 08:52:02 -05:00
parent ad1e1705b7
commit 5380476d07
17 changed files with 911 additions and 134 deletions

View File

@@ -78,7 +78,7 @@ export async function fetchSiteGlobals(siteId: string): Promise<Globals | null>
/**
* Fetch site navigation
*/
export async function fetchNavigation(siteId: string): Promise<Navigation[]> {
export async function fetchNavigation(siteId: string): Promise<Partial<Navigation>[]> {
try {
const nav = await directus.request(
readItems('navigation', {
@@ -100,7 +100,7 @@ export async function fetchNavigation(siteId: string): Promise<Navigation[]> {
export async function fetchPosts(
siteId: string,
options?: { limit?: number; page?: number; category?: string }
): Promise<{ posts: Post[]; total: number }> {
): Promise<{ posts: Partial<Post>[]; total: number }> {
const limit = options?.limit || 10;
const page = options?.page || 1;
const offset = (page - 1) * limit;
@@ -130,7 +130,10 @@ export async function fetchPosts(
'featured_image',
'published_at',
'category',
'author'
'author',
'site',
'status',
'content'
]
})
),
@@ -143,7 +146,7 @@ export async function fetchPosts(
]);
return {
posts: posts || [],
posts: (posts as Partial<Post>[]) || [],
total: Number(countResult?.[0]?.count || 0)
};
} catch (err) {
@@ -193,7 +196,7 @@ export async function fetchGeneratedArticles(
const [articles, countResult] = await Promise.all([
directus.request(
readItems('generated_articles', {
filter: { site: { _eq: siteId } },
filter: { site_id: { _eq: Number(siteId) } },
limit,
offset,
sort: ['-date_created'],
@@ -203,7 +206,7 @@ export async function fetchGeneratedArticles(
directus.request(
aggregate('generated_articles', {
aggregate: { count: '*' },
query: { filter: { site: { _eq: siteId } } }
query: { filter: { site_id: { _eq: Number(siteId) } } }
})
)
]);
@@ -231,7 +234,7 @@ export async function fetchGeneratedArticleBySlug(
filter: {
_and: [
{ slug: { _eq: slug } },
{ site: { _eq: siteId } },
{ site_id: { _eq: Number(siteId) } },
{ is_published: { _eq: true } }
]
},
@@ -279,7 +282,7 @@ export async function fetchStates() {
return directus.request(
readItems('locations_states', {
sort: ['name'],
fields: ['id', 'name', 'code']
fields: ['*']
})
);
}
@@ -289,7 +292,7 @@ export async function fetchCountiesByState(stateId: string) {
readItems('locations_counties', {
filter: { state: { _eq: stateId } },
sort: ['name'],
fields: ['id', 'name', 'fips_code', 'population']
fields: ['*']
})
);
}
@@ -300,7 +303,7 @@ export async function fetchCitiesByCounty(countyId: string, limit = 50) {
filter: { county: { _eq: countyId } },
sort: ['-population'],
limit,
fields: ['id', 'name', 'population', 'lat', 'lng', 'postal_code']
fields: ['*']
})
);
}

View File

@@ -47,11 +47,62 @@ export class WordPressClient {
return this.fetchCollection(url);
}
async getPosts(limit = 100): Promise<WPPost[]> {
const url = `${this.baseUrl}/wp-json/wp/v2/posts?per_page=${limit}`;
async getPosts(limit = 100, page = 1): Promise<WPPost[]> {
const url = `${this.baseUrl}/wp-json/wp/v2/posts?per_page=${limit}&page=${page}`;
return this.fetchCollection(url);
}
async getAllPosts(): Promise<WPPost[]> {
let allPosts: WPPost[] = [];
let page = 1;
let totalPages = 1;
// First fetch to get total pages
const url = `${this.baseUrl}/wp-json/wp/v2/posts?per_page=100&page=${page}`;
try {
const res = await fetch(url);
if (!res.ok) throw new Error(`WP API Error: ${res.status}`);
const totalPagesHeader = res.headers.get('X-WP-TotalPages');
if (totalPagesHeader) {
totalPages = parseInt(totalPagesHeader, 10);
}
const data = await res.json();
allPosts = [...allPosts, ...data];
// Loop remaining pages
// Process in parallel chunks if too many, but for now sequential is safer to avoid rate limits
// or perform simple Promise.all for batches.
// Let's do batches of 5 to speed it up.
const remainingPages = [];
for (let p = 2; p <= totalPages; p++) {
remainingPages.push(p);
}
// Batch fetch
const batchSize = 5;
for (let i = 0; i < remainingPages.length; i += batchSize) {
const batch = remainingPages.slice(i, i + batchSize);
const promises = batch.map(p =>
fetch(`${this.baseUrl}/wp-json/wp/v2/posts?per_page=100&page=${p}`)
.then(r => r.json())
);
const results = await Promise.all(promises);
results.forEach(posts => {
allPosts = [...allPosts, ...posts];
});
}
} catch (e) {
console.error("Fetch Error", e);
throw e;
}
return allPosts;
}
async getCategories(): Promise<any[]> {
// Fetch all categories
return this.fetchCollection(`${this.baseUrl}/wp-json/wp/v2/categories?per_page=100`);