ui related fixes in validations
This commit is contained in:
parent
c88a6123e8
commit
ac13a80726
@ -39,9 +39,11 @@ class CustomTemplate {
|
|||||||
|
|
||||||
// Check for duplicate custom templates based on title, type, category, and user_id
|
// Check for duplicate custom templates based on title, type, category, and user_id
|
||||||
static async checkForDuplicate(templateData) {
|
static async checkForDuplicate(templateData) {
|
||||||
|
const normalizedTitle = (templateData.title || '').toLowerCase();
|
||||||
console.log('[CustomTemplate.checkForDuplicate] Checking for duplicates:', {
|
console.log('[CustomTemplate.checkForDuplicate] Checking for duplicates:', {
|
||||||
type: templateData.type,
|
type: templateData.type,
|
||||||
title: templateData.title,
|
title: templateData.title,
|
||||||
|
normalizedTitle,
|
||||||
category: templateData.category,
|
category: templateData.category,
|
||||||
user_id: templateData.user_id
|
user_id: templateData.user_id
|
||||||
});
|
});
|
||||||
@ -58,24 +60,53 @@ class CustomTemplate {
|
|||||||
return typeResult.rows[0];
|
return typeResult.rows[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for same title + category for same user
|
// Check for same title for same user (category-agnostic)
|
||||||
if (templateData.user_id) {
|
if (templateData.user_id) {
|
||||||
const titleQuery = `
|
const titleQuery = `
|
||||||
SELECT id, title, type, category, user_id FROM custom_templates
|
SELECT id, title, type, category, user_id FROM custom_templates
|
||||||
WHERE LOWER(title) = LOWER($1) AND category = $2 AND user_id = $3
|
WHERE LOWER(title) = LOWER($1) AND user_id = $2
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const titleResult = await database.query(titleQuery, [
|
const titleParams = [templateData.title, templateData.user_id];
|
||||||
templateData.title,
|
console.log('[CustomTemplate.checkForDuplicate] title check params:', titleParams);
|
||||||
templateData.category,
|
const titleResult = await database.query(titleQuery, titleParams);
|
||||||
templateData.user_id
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (titleResult.rows.length > 0) {
|
if (titleResult.rows.length > 0) {
|
||||||
console.log('[CustomTemplate.checkForDuplicate] Found duplicate by title+category+user:', titleResult.rows[0]);
|
const row = titleResult.rows[0];
|
||||||
|
const titleMatch = (row.title || '').toLowerCase() === normalizedTitle;
|
||||||
|
console.log('[CustomTemplate.checkForDuplicate] Found duplicate by title+user:', {
|
||||||
|
id: row.id,
|
||||||
|
title: row.title,
|
||||||
|
type: row.type,
|
||||||
|
category: row.category,
|
||||||
|
user_id: row.user_id,
|
||||||
|
titleMatch
|
||||||
|
});
|
||||||
return titleResult.rows[0];
|
return titleResult.rows[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also check if main templates already have the same title (case-insensitive)
|
||||||
|
const mainTitleQuery = `
|
||||||
|
SELECT id, title, type, category FROM templates
|
||||||
|
WHERE is_active = true AND LOWER(title) = LOWER($1)
|
||||||
|
LIMIT 1
|
||||||
|
`;
|
||||||
|
const mainTitleParams = [templateData.title];
|
||||||
|
console.log('[CustomTemplate.checkForDuplicate] main title check params:', mainTitleParams);
|
||||||
|
const mainTitleResult = await database.query(mainTitleQuery, mainTitleParams);
|
||||||
|
if (mainTitleResult.rows.length > 0) {
|
||||||
|
const row = mainTitleResult.rows[0];
|
||||||
|
const titleMatch = (row.title || '').toLowerCase() === normalizedTitle;
|
||||||
|
console.log('[CustomTemplate.checkForDuplicate] Found duplicate title in main templates:', {
|
||||||
|
id: row.id,
|
||||||
|
title: row.title,
|
||||||
|
type: row.type,
|
||||||
|
category: row.category,
|
||||||
|
titleMatch
|
||||||
|
});
|
||||||
|
return mainTitleResult.rows[0];
|
||||||
|
}
|
||||||
|
|
||||||
console.log('[CustomTemplate.checkForDuplicate] No duplicates found');
|
console.log('[CustomTemplate.checkForDuplicate] No duplicates found');
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -87,23 +87,54 @@ class Template {
|
|||||||
|
|
||||||
// Check for duplicate templates based on title, type, and category
|
// Check for duplicate templates based on title, type, and category
|
||||||
static async checkForDuplicate(templateData) {
|
static async checkForDuplicate(templateData) {
|
||||||
|
const normalizedTitle = (templateData.title || '').toLowerCase();
|
||||||
|
const incomingType = templateData.type;
|
||||||
|
console.log('[Template.checkForDuplicate] input:', {
|
||||||
|
type: incomingType,
|
||||||
|
title: templateData.title,
|
||||||
|
normalizedTitle
|
||||||
|
});
|
||||||
const query = `
|
const query = `
|
||||||
SELECT id, title, type, category FROM templates
|
SELECT id, title, type, category FROM templates
|
||||||
WHERE is_active = true AND (
|
WHERE is_active = true AND (
|
||||||
type = $1 OR
|
type = $1 OR
|
||||||
(LOWER(title) = LOWER($2) AND category = $3)
|
LOWER(title) = LOWER($2)
|
||||||
)
|
)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const result = await database.query(query, [
|
const params = [incomingType, templateData.title];
|
||||||
templateData.type,
|
console.log('[Template.checkForDuplicate] query params:', params);
|
||||||
templateData.title,
|
const result = await database.query(query, params);
|
||||||
templateData.category
|
if (result.rows.length > 0) {
|
||||||
]);
|
const row = result.rows[0];
|
||||||
|
const titleMatch = (row.title || '').toLowerCase() === normalizedTitle;
|
||||||
|
const typeMatch = (row.type || '') === incomingType;
|
||||||
|
console.log('[Template.checkForDuplicate] found duplicate:', {
|
||||||
|
id: row.id,
|
||||||
|
title: row.title,
|
||||||
|
type: row.type,
|
||||||
|
category: row.category,
|
||||||
|
titleMatch,
|
||||||
|
typeMatch
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('[Template.checkForDuplicate] no duplicates found');
|
||||||
|
}
|
||||||
|
|
||||||
return result.rows.length > 0 ? result.rows[0] : null;
|
return result.rows.length > 0 ? result.rows[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a template by title (case-insensitive)
|
||||||
|
static async getByTitle(title) {
|
||||||
|
const query = `
|
||||||
|
SELECT * FROM templates
|
||||||
|
WHERE is_active = true AND LOWER(title) = LOWER($1)
|
||||||
|
LIMIT 1
|
||||||
|
`;
|
||||||
|
const result = await database.query(query, [title]);
|
||||||
|
return result.rows.length > 0 ? new Template(result.rows[0]) : null;
|
||||||
|
}
|
||||||
|
|
||||||
// Create new template
|
// Create new template
|
||||||
static async create(templateData) {
|
static async create(templateData) {
|
||||||
const id = uuidv4();
|
const id = uuidv4();
|
||||||
|
|||||||
@ -562,7 +562,17 @@ router.get('/:id([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/f
|
|||||||
router.post('/', async (req, res) => {
|
router.post('/', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const templateData = req.body;
|
const templateData = req.body;
|
||||||
console.log('🏗️ Creating new template - incoming body:', JSON.stringify(templateData));
|
const debugPayload = {
|
||||||
|
raw: templateData,
|
||||||
|
normalized: {
|
||||||
|
title: (templateData.title || '').toLowerCase(),
|
||||||
|
type: templateData.type,
|
||||||
|
category: templateData.category,
|
||||||
|
isCustom: templateData.isCustom ?? templateData.is_custom ?? false,
|
||||||
|
user_id: templateData.user_id || templateData.userId || null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log('🏗️ Creating new template - incoming body:', JSON.stringify(debugPayload));
|
||||||
|
|
||||||
// Validate required fields
|
// Validate required fields
|
||||||
const requiredFields = ['type', 'title', 'category'];
|
const requiredFields = ['type', 'title', 'category'];
|
||||||
@ -579,10 +589,16 @@ router.post('/', async (req, res) => {
|
|||||||
// Check for duplicates in regular templates first
|
// Check for duplicates in regular templates first
|
||||||
const existingTemplate = await Template.checkForDuplicate(templateData);
|
const existingTemplate = await Template.checkForDuplicate(templateData);
|
||||||
if (existingTemplate) {
|
if (existingTemplate) {
|
||||||
|
const isTitleDuplicate = (existingTemplate.title || '').toLowerCase() === (templateData.title || '').toLowerCase();
|
||||||
|
const isTypeDuplicate = (existingTemplate.type || '') === (templateData.type || '');
|
||||||
|
console.log('[POST /api/templates] duplicate detected in main templates:', { existingTemplate, isTitleDuplicate, isTypeDuplicate });
|
||||||
|
const message = isTitleDuplicate
|
||||||
|
? `A template with this name already exists: "${existingTemplate.title}"`
|
||||||
|
: `A template with this type already exists: "${existingTemplate.title}" (type: ${existingTemplate.type})`;
|
||||||
return res.status(409).json({
|
return res.status(409).json({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Duplicate template detected',
|
error: isTitleDuplicate ? 'Template name already exists' : 'Template type already exists',
|
||||||
message: `A template with similar characteristics already exists: "${existingTemplate.title}" (type: ${existingTemplate.type})`,
|
message,
|
||||||
existing_template: {
|
existing_template: {
|
||||||
id: existingTemplate.id,
|
id: existingTemplate.id,
|
||||||
title: existingTemplate.title,
|
title: existingTemplate.title,
|
||||||
@ -631,12 +647,19 @@ router.post('/', async (req, res) => {
|
|||||||
user_id: incomingUserId
|
user_id: incomingUserId
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log('[POST /api/templates - custom] duplicate payload:', duplicatePayload);
|
||||||
const existingCustomTemplate = await CustomTemplate.checkForDuplicate(duplicatePayload);
|
const existingCustomTemplate = await CustomTemplate.checkForDuplicate(duplicatePayload);
|
||||||
if (existingCustomTemplate) {
|
if (existingCustomTemplate) {
|
||||||
|
const isTitleDuplicate = (existingCustomTemplate.title || '').toLowerCase() === (templateData.title || '').toLowerCase();
|
||||||
|
const isTypeDuplicate = (existingCustomTemplate.type || '') === (templateData.type || '');
|
||||||
|
console.log('[POST /api/templates - custom] duplicate detected in custom/main:', { existingCustomTemplate, isTitleDuplicate, isTypeDuplicate });
|
||||||
|
const message = isTitleDuplicate
|
||||||
|
? `You already have a template with this name: "${existingCustomTemplate.title}"`
|
||||||
|
: `You already have a template with this type: "${existingCustomTemplate.title}" (type: ${existingCustomTemplate.type})`;
|
||||||
return res.status(409).json({
|
return res.status(409).json({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Duplicate custom template detected',
|
error: isTitleDuplicate ? 'Template name already exists' : 'Template type already exists',
|
||||||
message: `You already have a similar template: "${existingCustomTemplate.title}" (type: ${existingCustomTemplate.type})`,
|
message,
|
||||||
existing_template: {
|
existing_template: {
|
||||||
id: existingCustomTemplate.id,
|
id: existingCustomTemplate.id,
|
||||||
title: existingCustomTemplate.title,
|
title: existingCustomTemplate.title,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user