- Remove complex tracking form from home page
- Replace with clean 'Analyze URL Redirects' call-to-action button
- Remove announcement badge '🚀 URL Tracker Tool V2 - Now Available'
- Clean up unused imports and form-related code
- Direct users to dedicated /track page for full functionality
- Improve user experience with cleaner, more focused home page
Changes:
- Simplified HomePage component with single CTA button
- Removed form validation, mutation handling, and result display
- Maintained all tracking functionality on /track page
- Professional appearance without promotional clutter
373 lines
13 KiB
JavaScript
373 lines
13 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const express_1 = __importDefault(require("express"));
|
|
const zod_1 = require("zod");
|
|
const auth_middleware_1 = require("../middleware/auth.middleware");
|
|
const client_1 = require("@prisma/client");
|
|
const logger_1 = require("../lib/logger");
|
|
const router = express_1.default.Router();
|
|
const prisma = new client_1.PrismaClient();
|
|
const createProjectSchema = zod_1.z.object({
|
|
name: zod_1.z.string().min(1, 'Project name is required').max(100, 'Project name too long'),
|
|
description: zod_1.z.string().optional(),
|
|
settings: zod_1.z.object({
|
|
defaultMethod: zod_1.z.enum(['GET', 'POST', 'HEAD']).default('GET'),
|
|
defaultTimeout: zod_1.z.number().min(1000).max(30000).default(15000),
|
|
defaultMaxHops: zod_1.z.number().min(1).max(20).default(10),
|
|
enableSSLAnalysis: zod_1.z.boolean().default(true),
|
|
enableSEOAnalysis: zod_1.z.boolean().default(true),
|
|
enableSecurityAnalysis: zod_1.z.boolean().default(true),
|
|
}).optional(),
|
|
});
|
|
const updateProjectSchema = zod_1.z.object({
|
|
name: zod_1.z.string().min(1).max(100).optional(),
|
|
description: zod_1.z.string().optional(),
|
|
settings: zod_1.z.object({
|
|
defaultMethod: zod_1.z.enum(['GET', 'POST', 'HEAD']).optional(),
|
|
defaultTimeout: zod_1.z.number().min(1000).max(30000).optional(),
|
|
defaultMaxHops: zod_1.z.number().min(1).max(20).optional(),
|
|
enableSSLAnalysis: zod_1.z.boolean().optional(),
|
|
enableSEOAnalysis: zod_1.z.boolean().optional(),
|
|
enableSecurityAnalysis: zod_1.z.boolean().optional(),
|
|
}).optional(),
|
|
});
|
|
const projectParamsSchema = zod_1.z.object({
|
|
projectId: zod_1.z.string().min(1),
|
|
});
|
|
router.get('/', auth_middleware_1.requireAuth, async (req, res) => {
|
|
try {
|
|
const user = req.user;
|
|
const orgId = user.memberships[0]?.orgId;
|
|
if (!orgId) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'No organization found',
|
|
message: 'User must belong to an organization to access projects'
|
|
});
|
|
}
|
|
const projects = await prisma.project.findMany({
|
|
where: {
|
|
orgId: orgId,
|
|
},
|
|
include: {
|
|
_count: {
|
|
select: {
|
|
checks: true,
|
|
},
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: 'desc',
|
|
},
|
|
});
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
projects: projects.map(project => ({
|
|
id: project.id,
|
|
name: project.name,
|
|
description: project.settingsJson?.description || null,
|
|
settings: project.settingsJson,
|
|
trackingCount: project._count.checks,
|
|
createdAt: project.createdAt,
|
|
})),
|
|
},
|
|
});
|
|
}
|
|
catch (error) {
|
|
logger_1.logger.error('Failed to get projects:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to get projects',
|
|
message: error instanceof Error ? error.message : 'Unknown error',
|
|
});
|
|
}
|
|
});
|
|
router.post('/', auth_middleware_1.requireAuth, async (req, res) => {
|
|
try {
|
|
const user = req.user;
|
|
const orgId = user.memberships[0]?.orgId;
|
|
if (!orgId) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'No organization found',
|
|
message: 'User must belong to an organization to create projects'
|
|
});
|
|
}
|
|
const validatedData = createProjectSchema.parse(req.body);
|
|
const project = await prisma.project.create({
|
|
data: {
|
|
name: validatedData.name,
|
|
orgId: orgId,
|
|
settingsJson: {
|
|
description: validatedData.description || '',
|
|
...validatedData.settings,
|
|
},
|
|
},
|
|
});
|
|
logger_1.logger.info(`Project created: ${project.id}`, {
|
|
userId: user.id,
|
|
orgId,
|
|
projectName: project.name,
|
|
});
|
|
res.status(201).json({
|
|
success: true,
|
|
data: {
|
|
project: {
|
|
id: project.id,
|
|
name: project.name,
|
|
description: validatedData.description || null,
|
|
settings: project.settingsJson,
|
|
trackingCount: 0,
|
|
createdAt: project.createdAt,
|
|
},
|
|
},
|
|
message: 'Project created successfully',
|
|
});
|
|
}
|
|
catch (error) {
|
|
logger_1.logger.error('Failed to create project:', error);
|
|
if (error instanceof zod_1.z.ZodError) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Validation failed',
|
|
details: error.errors,
|
|
});
|
|
}
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to create project',
|
|
message: error instanceof Error ? error.message : 'Unknown error',
|
|
});
|
|
}
|
|
});
|
|
router.get('/:projectId', auth_middleware_1.requireAuth, async (req, res) => {
|
|
try {
|
|
const user = req.user;
|
|
const { projectId } = projectParamsSchema.parse(req.params);
|
|
const orgId = user.memberships[0]?.orgId;
|
|
if (!orgId) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'No organization found',
|
|
});
|
|
}
|
|
const project = await prisma.project.findFirst({
|
|
where: {
|
|
id: projectId,
|
|
orgId: orgId,
|
|
},
|
|
include: {
|
|
_count: {
|
|
select: {
|
|
checks: true,
|
|
},
|
|
},
|
|
checks: {
|
|
take: 10,
|
|
orderBy: {
|
|
startedAt: 'desc',
|
|
},
|
|
include: {
|
|
hops: {
|
|
select: {
|
|
url: true,
|
|
statusCode: true,
|
|
redirectType: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
if (!project) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'Project not found',
|
|
message: 'Project does not exist or you do not have access to it',
|
|
});
|
|
}
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
project: {
|
|
id: project.id,
|
|
name: project.name,
|
|
description: project.settingsJson?.description || null,
|
|
settings: project.settingsJson,
|
|
trackingCount: project._count.checks,
|
|
recentChecks: project.checks.map(check => ({
|
|
id: check.id,
|
|
inputUrl: check.inputUrl,
|
|
finalUrl: check.finalUrl,
|
|
status: check.status,
|
|
startedAt: check.startedAt,
|
|
hopCount: check.hops.length,
|
|
})),
|
|
createdAt: project.createdAt,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
catch (error) {
|
|
logger_1.logger.error('Failed to get project:', error);
|
|
if (error instanceof zod_1.z.ZodError) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Invalid project ID',
|
|
});
|
|
}
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to get project',
|
|
message: error instanceof Error ? error.message : 'Unknown error',
|
|
});
|
|
}
|
|
});
|
|
router.put('/:projectId', auth_middleware_1.requireAuth, async (req, res) => {
|
|
try {
|
|
const user = req.user;
|
|
const { projectId } = projectParamsSchema.parse(req.params);
|
|
const orgId = user.memberships[0]?.orgId;
|
|
if (!orgId) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'No organization found',
|
|
});
|
|
}
|
|
const validatedData = updateProjectSchema.parse(req.body);
|
|
const existingProject = await prisma.project.findFirst({
|
|
where: {
|
|
id: projectId,
|
|
orgId: orgId,
|
|
},
|
|
});
|
|
if (!existingProject) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'Project not found',
|
|
message: 'Project does not exist or you do not have access to it',
|
|
});
|
|
}
|
|
const currentSettings = existingProject.settingsJson || {};
|
|
const project = await prisma.project.update({
|
|
where: {
|
|
id: projectId,
|
|
},
|
|
data: {
|
|
...(validatedData.name && { name: validatedData.name }),
|
|
settingsJson: {
|
|
...currentSettings,
|
|
...(validatedData.description !== undefined && { description: validatedData.description }),
|
|
...validatedData.settings,
|
|
},
|
|
},
|
|
});
|
|
logger_1.logger.info(`Project updated: ${project.id}`, {
|
|
userId: user.id,
|
|
orgId,
|
|
changes: validatedData,
|
|
});
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
project: {
|
|
id: project.id,
|
|
name: project.name,
|
|
description: project.settingsJson?.description || null,
|
|
settings: project.settingsJson,
|
|
createdAt: project.createdAt,
|
|
},
|
|
},
|
|
message: 'Project updated successfully',
|
|
});
|
|
}
|
|
catch (error) {
|
|
logger_1.logger.error('Failed to update project:', error);
|
|
if (error instanceof zod_1.z.ZodError) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Validation failed',
|
|
details: error.errors,
|
|
});
|
|
}
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to update project',
|
|
message: error instanceof Error ? error.message : 'Unknown error',
|
|
});
|
|
}
|
|
});
|
|
router.delete('/:projectId', auth_middleware_1.requireAuth, async (req, res) => {
|
|
try {
|
|
const user = req.user;
|
|
const { projectId } = projectParamsSchema.parse(req.params);
|
|
const orgId = user.memberships[0]?.orgId;
|
|
if (!orgId) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'No organization found',
|
|
});
|
|
}
|
|
const existingProject = await prisma.project.findFirst({
|
|
where: {
|
|
id: projectId,
|
|
orgId: orgId,
|
|
},
|
|
include: {
|
|
_count: {
|
|
select: {
|
|
checks: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
if (!existingProject) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'Project not found',
|
|
message: 'Project does not exist or you do not have access to it',
|
|
});
|
|
}
|
|
if (existingProject._count.checks > 0) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Cannot delete project with tracking data',
|
|
message: `This project has ${existingProject._count.checks} tracking records. Please archive or move the data first.`,
|
|
});
|
|
}
|
|
await prisma.project.delete({
|
|
where: {
|
|
id: projectId,
|
|
},
|
|
});
|
|
logger_1.logger.info(`Project deleted: ${projectId}`, {
|
|
userId: user.id,
|
|
orgId,
|
|
projectName: existingProject.name,
|
|
});
|
|
res.json({
|
|
success: true,
|
|
message: 'Project deleted successfully',
|
|
});
|
|
}
|
|
catch (error) {
|
|
logger_1.logger.error('Failed to delete project:', error);
|
|
if (error instanceof zod_1.z.ZodError) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Invalid project ID',
|
|
});
|
|
}
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to delete project',
|
|
message: error instanceof Error ? error.message : 'Unknown error',
|
|
});
|
|
}
|
|
});
|
|
exports.default = router;
|
|
//# sourceMappingURL=projects.routes.js.map
|