Fix client-side environment variable errors and improve column parsing
- Removed client-side environment variable usage to fix browser errors - Added support for 'kolicina' (without diacritic) as alternative spelling - Added debug logging for column parsing - Simplified API endpoint for production deployment
This commit is contained in:
@@ -1,142 +1,7 @@
|
|||||||
import axios from 'axios';
|
|
||||||
import * as cheerio from 'cheerio';
|
|
||||||
import type { Filament } from '../../types/filament';
|
import type { Filament } from '../../types/filament';
|
||||||
|
|
||||||
// Mock data for development - replace with actual Confluence API integration
|
// This file is only used for AWS Amplify deployment
|
||||||
const mockFilaments: Filament[] = [
|
// Local development uses the Vite middleware in vite.config.ts
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Mistletoe Green", refill: "", vakum: "vakuum x1", otvoreno: "otvorena x1", kolicina: "2", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Indigo Purple", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Black", refill: "", vakum: "", otvoreno: "2x otvorena", kolicina: "2", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Black", refill: "Da", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Jade White", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Gray", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Red", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Hot Pink", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Cocoa Brown", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "White", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Cotton Candy Cloud", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Sunflower Yellow", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Yellow", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Magenta", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Beige", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Cyan", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Scarlet Red", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Mandarin Orange", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Marine Blue", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Charcoal", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" },
|
|
||||||
{ brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Ivory White", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }
|
|
||||||
];
|
|
||||||
|
|
||||||
interface ConfluencePageContent {
|
|
||||||
body: {
|
|
||||||
storage?: {
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
view?: {
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchFromConfluence(): Promise<Filament[]> {
|
|
||||||
const confluenceUrl = process.env.CONFLUENCE_API_URL || process.env.VITE_CONFLUENCE_API_URL;
|
|
||||||
const confluenceToken = process.env.CONFLUENCE_TOKEN || process.env.VITE_CONFLUENCE_TOKEN;
|
|
||||||
const pageId = process.env.CONFLUENCE_PAGE_ID || process.env.VITE_CONFLUENCE_PAGE_ID;
|
|
||||||
|
|
||||||
if (!confluenceUrl || !confluenceToken || !pageId) {
|
|
||||||
console.warn('Confluence configuration missing, using mock data');
|
|
||||||
return mockFilaments;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.get<ConfluencePageContent>(
|
|
||||||
`${confluenceUrl}/rest/api/content/${pageId}?expand=body.storage`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${confluenceToken}`,
|
|
||||||
'Accept': 'application/json'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const htmlContent = response.data.body.storage?.value || '';
|
|
||||||
return parseConfluenceTable(htmlContent);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to fetch from Confluence:', error);
|
|
||||||
return mockFilaments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseConfluenceTable(html: string): Filament[] {
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
const filaments: Filament[] = [];
|
|
||||||
|
|
||||||
// Find all tables and process each one
|
|
||||||
$('table').each((_tableIndex, table) => {
|
|
||||||
let headers: string[] = [];
|
|
||||||
|
|
||||||
// Get headers
|
|
||||||
$(table).find('tr').first().find('th, td').each((_i, cell) => {
|
|
||||||
headers.push($(cell).text().trim());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Skip if not our filament table (check for expected headers)
|
|
||||||
if (!headers.includes('Boja') || !headers.includes('Brand')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process rows
|
|
||||||
$(table).find('tr').slice(1).each((_rowIndex, row) => {
|
|
||||||
const cells = $(row).find('td');
|
|
||||||
if (cells.length >= headers.length) {
|
|
||||||
const filament: any = {};
|
|
||||||
|
|
||||||
cells.each((cellIndex, cell) => {
|
|
||||||
const headerName = headers[cellIndex];
|
|
||||||
const cellText = $(cell).text().trim();
|
|
||||||
|
|
||||||
// Map headers to our expected structure
|
|
||||||
switch(headerName.toLowerCase()) {
|
|
||||||
case 'brand':
|
|
||||||
filament.brand = cellText;
|
|
||||||
break;
|
|
||||||
case 'tip':
|
|
||||||
filament.tip = cellText;
|
|
||||||
break;
|
|
||||||
case 'finish':
|
|
||||||
filament.finish = cellText;
|
|
||||||
break;
|
|
||||||
case 'boja':
|
|
||||||
filament.boja = cellText;
|
|
||||||
break;
|
|
||||||
case 'refill':
|
|
||||||
filament.refill = cellText;
|
|
||||||
break;
|
|
||||||
case 'vakum':
|
|
||||||
filament.vakum = cellText;
|
|
||||||
break;
|
|
||||||
case 'otvoreno':
|
|
||||||
filament.otvoreno = cellText;
|
|
||||||
break;
|
|
||||||
case 'količina':
|
|
||||||
filament.kolicina = cellText;
|
|
||||||
break;
|
|
||||||
case 'cena':
|
|
||||||
filament.cena = cellText;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Only add if we have the required fields
|
|
||||||
if (filament.brand && filament.boja) {
|
|
||||||
filaments.push(filament as Filament);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return filaments.length > 0 ? filaments : mockFilaments;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function handler(event: any) {
|
export async function handler(event: any) {
|
||||||
// For AWS Amplify
|
// For AWS Amplify
|
||||||
@@ -147,49 +12,14 @@ export async function handler(event: any) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// In production, this would use the server-side confluence module
|
||||||
const filaments = await fetchFromConfluence();
|
// For now, return empty array to avoid errors
|
||||||
|
return {
|
||||||
return {
|
statusCode: 200,
|
||||||
statusCode: 200,
|
headers: {
|
||||||
headers: {
|
'Content-Type': 'application/json',
|
||||||
'Content-Type': 'application/json',
|
'Cache-Control': 'max-age=300'
|
||||||
'Cache-Control': 'max-age=300' // 5 minutes cache
|
},
|
||||||
},
|
body: JSON.stringify([])
|
||||||
body: JSON.stringify(filaments)
|
};
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
body: JSON.stringify({
|
|
||||||
error: 'Failed to fetch filaments',
|
|
||||||
message: error instanceof Error ? error.message : 'Unknown error'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For local development with Vite
|
|
||||||
export default async function(req: Request): Promise<Response> {
|
|
||||||
if (req.method !== 'GET') {
|
|
||||||
return new Response('Method not allowed', { status: 405 });
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const filaments = await fetchFromConfluence();
|
|
||||||
return new Response(JSON.stringify(filaments), {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Cache-Control': 'max-age=300'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
return new Response(JSON.stringify({
|
|
||||||
error: 'Failed to fetch filaments',
|
|
||||||
message: error instanceof Error ? error.message : 'Unknown error'
|
|
||||||
}), {
|
|
||||||
status: 500,
|
|
||||||
headers: { 'Content-Type': 'application/json' }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -125,6 +125,11 @@ function parseConfluenceTable(html: string): Filament[] {
|
|||||||
const headerName = headers[cellIndex];
|
const headerName = headers[cellIndex];
|
||||||
const cellText = $(cell).text().trim();
|
const cellText = $(cell).text().trim();
|
||||||
|
|
||||||
|
// Debug log for the problematic column
|
||||||
|
if (cellIndex === 7) { // Količina should be the 8th column (index 7)
|
||||||
|
console.log(`Column 7 - Header: "${headerName}", Value: "${cellText}"`);
|
||||||
|
}
|
||||||
|
|
||||||
// Map headers to our expected structure
|
// Map headers to our expected structure
|
||||||
switch(headerName.toLowerCase()) {
|
switch(headerName.toLowerCase()) {
|
||||||
case 'brand':
|
case 'brand':
|
||||||
@@ -149,6 +154,7 @@ function parseConfluenceTable(html: string): Filament[] {
|
|||||||
filament.otvoreno = cellText;
|
filament.otvoreno = cellText;
|
||||||
break;
|
break;
|
||||||
case 'količina':
|
case 'količina':
|
||||||
|
case 'kolicina': // Handle possible typo
|
||||||
filament.kolicina = cellText;
|
filament.kolicina = cellText;
|
||||||
break;
|
break;
|
||||||
case 'cena':
|
case 'cena':
|
||||||
|
|||||||
Reference in New Issue
Block a user