Merge branch 'master' into Fix-up-statcards

This commit is contained in:
2024-12-23 23:47:15 -05:00
5 changed files with 56 additions and 39 deletions

3
.gitignore vendored
View File

@@ -24,4 +24,5 @@ dist-ssr
*.sw? *.sw?
.env .env
dashboard/build/** dashboard/build/**
dashboard-server/frontend/build/** dashboard-server/frontend/build/**
._*

View File

@@ -38,7 +38,13 @@ const corsOptions = {
console.log('CORS check for origin:', origin); console.log('CORS check for origin:', origin);
// Check if origin is allowed // Allow local network IPs (192.168.1.xxx)
if (origin && origin.match(/^http:\/\/192\.168\.1\.\d{1,3}(:\d+)?$/)) {
callback(null, true);
return;
}
// Check if origin is in allowed list
if (!origin || allowedOrigins.indexOf(origin) !== -1) { if (!origin || allowedOrigins.indexOf(origin) !== -1) {
callback(null, true); callback(null, true);
} else { } else {
@@ -96,19 +102,19 @@ app.post('/login', (req, res) => {
expiresIn: '24h' expiresIn: '24h'
}); });
// Determine if request is from localhost // Determine if request is from local network
const isLocalhost = req.headers.origin?.includes('localhost'); const isLocalNetwork = req.headers.origin?.includes('192.168.1.') || req.headers.origin?.includes('localhost');
const cookieOptions = { const cookieOptions = {
httpOnly: true, httpOnly: true,
secure: !isLocalhost, secure: !isLocalNetwork, // Only use secure for non-local requests
sameSite: isLocalhost ? 'lax' : 'none', sameSite: isLocalNetwork ? 'lax' : 'none',
path: '/', path: '/',
maxAge: 24 * 60 * 60 * 1000 // 24 hours maxAge: 24 * 60 * 60 * 1000 // 24 hours
}; };
// Add domain only for production // Only set domain for production
if (!isLocalhost) { if (!isLocalNetwork) {
cookieOptions.domain = '.kent.pw'; cookieOptions.domain = '.kent.pw';
} }
@@ -163,13 +169,13 @@ app.get('/check', (req, res) => {
}); });
app.post('/logout', (req, res) => { app.post('/logout', (req, res) => {
const isLocalhost = req.headers.origin?.includes('localhost'); const isLocalNetwork = req.headers.origin?.includes('192.168.1.') || req.headers.origin?.includes('localhost');
const cookieOptions = { const cookieOptions = {
httpOnly: true, httpOnly: true,
secure: !isLocalhost, secure: !isLocalNetwork,
sameSite: isLocalhost ? 'lax' : 'none', sameSite: isLocalNetwork ? 'lax' : 'none',
path: '/', path: '/',
domain: isLocalhost ? undefined : '.kent.pw' domain: isLocalNetwork ? undefined : '.kent.pw'
}; };
console.log('Clearing cookie with options:', cookieOptions); console.log('Clearing cookie with options:', cookieOptions);

View File

@@ -91,27 +91,31 @@ const DashboardLayout = () => {
<div className="grid grid-cols-1 xl:grid-cols-6 gap-4"> <div className="grid grid-cols-1 xl:grid-cols-6 gap-4">
<div className="xl:col-span-4 col-span-6"> <div className="xl:col-span-4 col-span-6">
<div className="space-y-4 h-full w-full"> <div className="space-y-4 h-full w-full">
<StatCards /> <div id="stats">
<StatCards />
</div>
</div> </div>
</div> </div>
<div className="xl:col-span-2 col-span-6 h-[500px] xl:h-[643px] 2xl:h-[510px] lg:hidden xl:block"> <div id="feed-xl" className="xl:col-span-2 col-span-6 h-[500px] xl:h-[643px] 2xl:h-[510px] lg:hidden xl:block">
<div className="h-full"> <div className="h-full">
<div className="h-full"><EventFeed /></div> <div className="h-full"><EventFeed /></div>
</div> </div>
</div> </div>
</div> </div>
<div className="grid grid-cols-12 gap-4"> <div className="grid grid-cols-12 gap-4">
<div className="hidden lg:col-span-6 lg:block xl:hidden h-[740px]"> <div id="feed-lg" className="hidden lg:col-span-6 lg:block xl:hidden h-[740px]">
<EventFeed /> <EventFeed />
</div> </div>
<div className="col-span-12 lg:col-span-6 xl:col-span-4 h-[600px] lg:h-[740px]"> <div id="products" className="col-span-12 lg:col-span-6 xl:col-span-4 h-[600px] lg:h-[740px]">
<ProductGrid /> <ProductGrid />
</div> </div>
<div className="col-span-12 xl:col-span-8 h-full w-full flex"> <div id="sales" className="col-span-12 xl:col-span-8 h-full w-full flex">
<SalesChart className="w-full h-full"/> <SalesChart className="w-full h-full"/>
</div> </div>
</div> </div>
<AircallDashboard /> <div id="calls">
<AircallDashboard />
</div>
</div> </div>
</div> </div>
</ScrollProvider> </ScrollProvider>

View File

@@ -20,25 +20,13 @@ const Navigation = () => {
const baseSections = [ const baseSections = [
{ id: "stats", label: "Statistics" }, { id: "stats", label: "Statistics" },
{ {
id: "realtime", id: "feed",
label: "Realtime", label: "Event Feed",
responsiveIds: ["realtime-lg", "realtime-md"], responsiveIds: ["feed-xl", "feed-lg"],
order: { md: 2, default: 1 },
}, },
{ { id: "products", label: "Top Products" },
id: "products", { id: "sales", label: "Sales Chart" },
label: "Top Products", { id: "calls", label: "Aircall" },
responsiveIds: ["products-lg", "products-md"],
order: { md: 1, default: 2 },
},
{ id: "feed", label: "Activity Feed" },
{ id: "sales", label: "Sales Metrics" },
{ id: "campaigns", label: "Campaigns" },
{ id: "meta", label: "Meta Ads" },
{ id: "analytics", label: "Analytics" },
{ id: "behavior", label: "User Behavior" },
{ id: "gorgias", label: "Customer Service" },
{ id: "calls", label: "Calls" },
]; ];
const sortSections = (sections) => { const sortSections = (sections) => {

View File

@@ -72,8 +72,10 @@ export default defineConfig(({ mode }) => {
changeOrigin: true, changeOrigin: true,
secure: true, secure: true,
cookieDomainRewrite: { cookieDomainRewrite: {
"dashboard.kent.pw": "localhost", "dashboard.kent.pw": "",
}, },
hostRewrite: true,
autoRewrite: true,
configure: (proxy, _options) => { configure: (proxy, _options) => {
proxy.on("error", (err, req, res) => { proxy.on("error", (err, req, res) => {
console.log("Auth proxy error:", err); console.log("Auth proxy error:", err);
@@ -85,13 +87,29 @@ export default defineConfig(({ mode }) => {
); );
}); });
proxy.on("proxyReq", (proxyReq, req, _res) => { proxy.on("proxyReq", (proxyReq, req, _res) => {
proxyReq.setHeader('X-Forwarded-Host', req.headers.host);
proxyReq.setHeader('X-Forwarded-Proto', 'http');
const origin = req.headers.origin || `http://${req.headers.host}`;
proxyReq.setHeader('origin', origin);
console.log("Outgoing auth request:", { console.log("Outgoing auth request:", {
method: req.method, method: req.method,
url: req.url, url: req.url,
headers: req.headers, headers: proxyReq.getHeaders(),
}); });
}); });
proxy.on("proxyRes", (proxyRes, req, _res) => { proxy.on("proxyRes", (proxyRes, req, res) => {
const cookies = proxyRes.headers['set-cookie'];
if (cookies) {
proxyRes.headers['set-cookie'] = cookies.map(cookie =>
cookie
.replace(/Domain=[^;]+;/g, '')
.replace(/Secure;/g, '')
.replace(/SameSite=None/g, 'SameSite=Lax')
);
}
console.log("Auth proxy response:", { console.log("Auth proxy response:", {
statusCode: proxyRes.statusCode, statusCode: proxyRes.statusCode,
url: req.url, url: req.url,