Enhance group and collection handling by adding style and extent properties, updating controllers and services, and implementing event handling for group creation and ungrouping.
This commit is contained in:
@@ -8,7 +8,7 @@ export const addGroupController = async (
|
||||
): Promise<void> => {
|
||||
try {
|
||||
const { organization, userId } = req.user || {};
|
||||
const { projectId, position, groupName, type, collections } = req.body;
|
||||
const { projectId, position, groupName, type, collections,style } = req.body;
|
||||
const missing = Object.entries({
|
||||
organization,
|
||||
projectId,
|
||||
@@ -31,7 +31,7 @@ export const addGroupController = async (
|
||||
const data = {
|
||||
organization: organization as string,
|
||||
projectId,
|
||||
position,
|
||||
position,style,
|
||||
type,
|
||||
groupName,
|
||||
collections,
|
||||
@@ -101,7 +101,7 @@ export const unGroupController = async (
|
||||
): Promise<void> => {
|
||||
try {
|
||||
const { organization, userId } = req.user || {};
|
||||
const { projectId, position, groupId, collections } = req.body;
|
||||
const { projectId, position, groupId, collections,style } = req.body;
|
||||
const missing = Object.entries({
|
||||
organization,
|
||||
projectId,
|
||||
@@ -124,7 +124,7 @@ export const unGroupController = async (
|
||||
organization: organization as string,
|
||||
projectId,
|
||||
position,
|
||||
groupId,
|
||||
groupId,style,
|
||||
collections,
|
||||
userId: userId as string,
|
||||
};
|
||||
|
||||
@@ -33,6 +33,7 @@ interface IAttributes {
|
||||
}
|
||||
export interface ICollectionNode extends Document {
|
||||
type: string;
|
||||
extent: string;
|
||||
projectId: IProject["_id"];
|
||||
parentCollectionNodeId: ICollectionNode["_id"];
|
||||
isSubCollection: boolean;
|
||||
@@ -119,6 +120,7 @@ const collectionSchema: Schema<ICollectionNode> = new Schema(
|
||||
parentCollectionNodeId: { type: Schema.Types.ObjectId, ref: "Collection" },
|
||||
attributeparentId: { type: Schema.Types.ObjectId, ref: "Collection" },
|
||||
groupParentId: { type: Schema.Types.ObjectId, ref: "Collection" },
|
||||
extent:{type:String},
|
||||
collectionName: { type: String },
|
||||
type: { type: String, enum: ["collectionNode", "objectNode"] },
|
||||
backgroundColor: { type: backgroundColorSchema },
|
||||
|
||||
@@ -11,6 +11,10 @@ export interface IgroupModel extends Document {
|
||||
y: number;
|
||||
zoom: number;
|
||||
};
|
||||
style: {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
projectId: IProject["_id"];
|
||||
collections: ICollectionNode["_id"][];
|
||||
isArchive: boolean;
|
||||
@@ -25,6 +29,10 @@ const GroupSchema = new Schema<IgroupModel>(
|
||||
y: { type: Number },
|
||||
zoom: { type: Number },
|
||||
},
|
||||
style: {
|
||||
width: { type: Number },
|
||||
height: { type: Number },
|
||||
},
|
||||
projectId: { type: Schema.Types.ObjectId, ref: "Project", required: true },
|
||||
collections: [{ type: Schema.Types.ObjectId, ref: "Collection" }],
|
||||
isArchive: { type: Boolean, default: false },
|
||||
|
||||
@@ -165,7 +165,7 @@ export const Nodecreation = async (
|
||||
});
|
||||
if (existingCollection)
|
||||
return { status: "CollectionName already exists" };
|
||||
let attributes = [{ key: "auto_id", type: "string" ,keyType:"primary"}];
|
||||
let attributes = [{ key: "auto_id", type: "string",keyType:"primary" }];
|
||||
const newAttributes = attributes;
|
||||
const updatedAttributesMap = new Map<string, any>();
|
||||
|
||||
@@ -190,16 +190,9 @@ export const Nodecreation = async (
|
||||
const models = [newCollectionnode.collectionName];
|
||||
const finalResult = {
|
||||
collectionNodeId: newCollectionnode._id,
|
||||
// fieldId: (newCollectionnode.attributes[0] as any)._id,
|
||||
// models,
|
||||
type:newCollectionnode.type,
|
||||
position:newCollectionnode.position,
|
||||
data:{
|
||||
collectionName:newCollectionnode.collectionName,
|
||||
collectionData:newCollectionnode.attributes,
|
||||
}
|
||||
};
|
||||
// console.log("finalResult: ", finalResult);
|
||||
fieldId: (newCollectionnode.attributes[0] as any)._id,
|
||||
models,
|
||||
};
|
||||
const models1 = [
|
||||
{
|
||||
name: newCollectionnode.collectionName,
|
||||
@@ -216,13 +209,13 @@ export const Nodecreation = async (
|
||||
projectName: existingProject.projectName, // 👈 take from DB
|
||||
models1,
|
||||
};
|
||||
// console.log("fileData: ", fileData);
|
||||
try {
|
||||
const fileResponse = await modelNodeFile(fileData);
|
||||
// console.log("📦 File backend response:", fileResponse);
|
||||
} catch (err) {
|
||||
// console.error("⚠️ File backend error:", err);
|
||||
}
|
||||
|
||||
// try {
|
||||
// const fileResponse = await modelNodeFile(fileData);
|
||||
// console.log("📦 File backend response:", fileResponse);
|
||||
// } catch (err) {
|
||||
// // console.error("⚠️ File backend error:", err);
|
||||
// }
|
||||
return { status: "Success", data: finalResult };
|
||||
}
|
||||
}
|
||||
@@ -257,8 +250,7 @@ export const updatecollection = async (
|
||||
collectionName,
|
||||
userId,
|
||||
} = data;
|
||||
console.log('data: nodeupdate', data);
|
||||
|
||||
console.log("data:node ", data);
|
||||
try {
|
||||
const ExistingUser = await userModel(organization).findOne({
|
||||
_id: userId,
|
||||
@@ -283,6 +275,7 @@ export const updatecollection = async (
|
||||
}
|
||||
|
||||
function updateModelName(oldName: string, newBaseName: string): string {
|
||||
console.log("newBaseName: ", newBaseName);
|
||||
const [prefix, ...suffixParts] = oldName.split("_");
|
||||
|
||||
if (suffixParts.length > 0) {
|
||||
@@ -293,6 +286,7 @@ export const updatecollection = async (
|
||||
return newBaseName;
|
||||
}
|
||||
|
||||
const newBaseName = collectionName as string;
|
||||
// const referencedEdges = await collectionsModel(organization).find({
|
||||
// isArchive: false,
|
||||
// projectId,
|
||||
@@ -303,9 +297,9 @@ export const updatecollection = async (
|
||||
// ),
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
|
||||
// console.log('referencedEdges: ', referencedEdges);
|
||||
// console.log("referencedEdges: ", referencedEdges);
|
||||
// if (referencedEdges.length) {
|
||||
// for (const doc of referencedEdges) {
|
||||
// let updated = false;
|
||||
@@ -315,9 +309,9 @@ export const updatecollection = async (
|
||||
// if (
|
||||
// refKey?.collection_id?.toString() === collectionNodeId.toString()
|
||||
// ) {
|
||||
// const newBaseName = collectionName as string;
|
||||
// const oldName = attr.key;
|
||||
// const newKey = updateModelName(oldName, newBaseName);
|
||||
// console.log("newKey: ", newKey);
|
||||
// attr.key = newKey;
|
||||
// updated = true;
|
||||
// }
|
||||
@@ -328,84 +322,95 @@ export const updatecollection = async (
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
async function updateReferencedKeysRecursively(
|
||||
organization: string,
|
||||
projectId: string,
|
||||
collectionNodeId: any,
|
||||
collectionName: string,
|
||||
visited = new Set<string>()
|
||||
): Promise<void> {
|
||||
if (visited.has(collectionNodeId)) return;
|
||||
visited.add(collectionNodeId);
|
||||
|
||||
const referencedEdges = await collectionsModel(organization).find({
|
||||
isArchive: false,
|
||||
projectId,
|
||||
$or: [
|
||||
{ "attributes.refKey.collection_id": new mongoose.Types.ObjectId(collectionNodeId) },
|
||||
{ "attributes.refKey.collection_id": collectionNodeId },
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
console.log('referencedEdges: ', referencedEdges);
|
||||
console.log(
|
||||
`🔍 Found ${referencedEdges.length} referencing collections for '${collectionName}'`
|
||||
);
|
||||
|
||||
for (const doc of referencedEdges) {
|
||||
let updated = false;
|
||||
|
||||
for (const attr of doc.attributes) {
|
||||
const refKey = attr.refKey as any;
|
||||
|
||||
if (refKey?.collection_id?.toString() === collectionNodeId.toString()) {
|
||||
const oldName = attr.key;
|
||||
const newBaseName = collectionName;
|
||||
const newKey = updateModelName(oldName, newBaseName);
|
||||
|
||||
attr.key = newKey;
|
||||
updated = true;
|
||||
let referencedEdges
|
||||
async function updateReferencedKeysRecursively(
|
||||
organization: string,
|
||||
projectId: string,
|
||||
collectionNodeId: any,
|
||||
collectionName: string,
|
||||
visited = new Set<string>()
|
||||
) {
|
||||
if (visited.has(collectionNodeId)) return [];
|
||||
visited.add(collectionNodeId);
|
||||
|
||||
const referencedEdges = await collectionsModel(organization).find({
|
||||
isArchive: false,
|
||||
projectId,
|
||||
$or: [
|
||||
{
|
||||
"attributes.refKey.collection_id": new mongoose.Types.ObjectId(
|
||||
collectionNodeId
|
||||
),
|
||||
},
|
||||
{ "attributes.refKey.collection_id": collectionNodeId },
|
||||
],
|
||||
});
|
||||
if (!referencedEdges.length) return [];
|
||||
// return referencedEdges
|
||||
console.log("referencedEdges: ", referencedEdges);
|
||||
console.log(
|
||||
`🔁 Updated key in '${doc.collectionName}': ${oldName} → ${newKey} (ref to '${collectionName}')`
|
||||
`🔍 Found ${referencedEdges.length} referencing collections for '${collectionName}'`
|
||||
);
|
||||
|
||||
const updatedDocs = [];
|
||||
for (const doc of referencedEdges) {
|
||||
let updated = false;
|
||||
|
||||
for (const attr of doc.attributes) {
|
||||
const refKey = attr.refKey as any;
|
||||
|
||||
if (
|
||||
refKey?.collection_id?.toString() === collectionNodeId.toString()
|
||||
) {
|
||||
const oldName = attr.key;
|
||||
const newBaseName = collectionName;
|
||||
const newKey = updateModelName(oldName, newBaseName);
|
||||
|
||||
attr.key = newKey;
|
||||
updated = true;
|
||||
|
||||
console.log(
|
||||
`🔁 Updated key in '${doc.collectionName}': ${oldName} → ${newKey} (ref to '${collectionName}')`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
await doc.save();
|
||||
updatedDocs.push(doc);
|
||||
console.log(`✅ Saved changes in '${doc.collectionName}'`);
|
||||
}
|
||||
|
||||
// 🔁 Recursive update if the collection itself has a valid name
|
||||
if (doc.collectionName) {
|
||||
const childUpdates: any = await updateReferencedKeysRecursively(
|
||||
organization,
|
||||
projectId,
|
||||
doc._id,
|
||||
doc.collectionName,
|
||||
visited
|
||||
);
|
||||
updatedDocs.push(...childUpdates);
|
||||
} else {
|
||||
console.warn(
|
||||
`⚠️ Skipped recursion for ${doc._id} (no collectionName)`
|
||||
);
|
||||
}
|
||||
}
|
||||
return updatedDocs;
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
await doc.save();
|
||||
console.log(`✅ Saved changes in '${doc.collectionName}'`);
|
||||
}
|
||||
|
||||
// 🔁 Recursive update if the collection itself has a valid name
|
||||
if (doc.collectionName) {
|
||||
await updateReferencedKeysRecursively(
|
||||
organization,
|
||||
projectId,
|
||||
doc._id,
|
||||
doc.collectionName,
|
||||
visited
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ Skipped recursion for ${doc._id} (no collectionName)`);
|
||||
}
|
||||
}
|
||||
}
|
||||
const currentCollectionName =
|
||||
collectionName || existingCollection.collectionName;
|
||||
|
||||
await updateReferencedKeysRecursively(
|
||||
organization,
|
||||
projectId,
|
||||
collectionNodeId,
|
||||
currentCollectionName
|
||||
);
|
||||
|
||||
const currentCollectionName =
|
||||
collectionName || existingCollection.collectionName;
|
||||
|
||||
const updatedRefs = await updateReferencedKeysRecursively(
|
||||
organization,
|
||||
projectId,
|
||||
collectionNodeId,
|
||||
currentCollectionName
|
||||
);
|
||||
console.log('updatedRefs: ', updatedRefs);
|
||||
const oldName = existingCollection.collectionName;
|
||||
const newName = collectionName;
|
||||
|
||||
const collectionNameupdate = await collectionsModel(
|
||||
organization
|
||||
).findOneAndUpdate(
|
||||
@@ -429,7 +434,7 @@ await updateReferencedKeysRecursively(
|
||||
},
|
||||
{ new: true }
|
||||
);
|
||||
// console.log('collectionNameupdate: ', collectionNameupdate);
|
||||
// console.log('collectionNameupdate: ', collectionNameupdate);
|
||||
if (collectionNameupdate) {
|
||||
// ✅ If name changed, trigger file rename
|
||||
// if (collectionNameupdate && oldName !== newName) {
|
||||
@@ -447,7 +452,7 @@ await updateReferencedKeysRecursively(
|
||||
status: "Success",
|
||||
data: {
|
||||
collectionNameupdate: collectionNameupdate,
|
||||
// updateFileds: referencedEdges,
|
||||
updateFileds: updatedRefs,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
@@ -646,29 +651,31 @@ export const GetNodesInProject = async (
|
||||
);
|
||||
|
||||
if (refAttribute) {
|
||||
console.log('refAttribute: ', refAttribute);
|
||||
// targetFieldKey = refAttribute.key;
|
||||
targetFieldKey = e.to.fieldId;
|
||||
console.log('e: ', e.to.fieldId);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
edgeId: e._id, //mongo edgeid
|
||||
id: `e_source-${e.from.collection_id}-${e.from.collection_id}_${targetFieldKey}`,
|
||||
id: `e_source-${e.from.collection_id}-${e.from.fieldId}_${e.to.fieldId}`,
|
||||
source: e.from.collection_id,
|
||||
sourceHandle: `source-${e.from.collection_id}-${e.from.fieldId}`,
|
||||
target: e.to.collection_id,
|
||||
targetHandle: `target-${e.to.collection_id}-${targetFieldKey}`,
|
||||
targetHandle: `target-${e.to.collection_id}-${e.to.fieldId}`,
|
||||
// targetHandle: targetFieldKey || e.to.collection_id,
|
||||
};
|
||||
})
|
||||
);
|
||||
let formattedGroups=[];
|
||||
let formattedGroups = [];
|
||||
const groupDatas = await groupModel(organization).find({
|
||||
isArchive: false,
|
||||
projectId:projectId,
|
||||
projectId: projectId,
|
||||
});
|
||||
// let formattedGroups
|
||||
for (const grpdata of groupDatas) {
|
||||
console.log('grpdata: ', grpdata);
|
||||
const collectionsDatas = await collectionsModel(organization).find({
|
||||
isArchive: false,
|
||||
projectId,
|
||||
@@ -678,21 +685,20 @@ export const GetNodesInProject = async (
|
||||
groupId: grpdata._id,
|
||||
type: grpdata.type,
|
||||
position: grpdata.position,
|
||||
style: grpdata.style,
|
||||
data: {
|
||||
label: grpdata.groupName,
|
||||
childrenCount: collectionsDatas.length,
|
||||
},
|
||||
});
|
||||
}
|
||||
// return formattedGroups
|
||||
const formattedCollections = collectionNodes.map((collection: any) => {
|
||||
// console.log("collection: ", collection);
|
||||
// console.log("collection.groupParentId: ", collection.groupParentId);
|
||||
const baseData = {
|
||||
id: collection._id,
|
||||
position: collection.position,
|
||||
type: collection.type,
|
||||
parentGroupNode: `group - ${collection.groupParentId}`|| " ",
|
||||
parentGroupNode: `group-${collection.groupParentId}` || " ",
|
||||
extent: collection.extent || " ",
|
||||
data: {
|
||||
collectionName: collection.collectionName,
|
||||
collectionData: collection.attributes
|
||||
@@ -730,13 +736,11 @@ export const GetNodesInProject = async (
|
||||
}
|
||||
return baseData;
|
||||
});
|
||||
// console.log("filteredEdges: ", filteredEdges);
|
||||
const finalResult = {
|
||||
nodes: formattedCollections,
|
||||
edges: filteredEdges,
|
||||
groups: formattedGroups,
|
||||
};
|
||||
// console.log("finalResult: ", finalResult);
|
||||
return { status: "Success", data: finalResult };
|
||||
}
|
||||
}
|
||||
@@ -780,7 +784,6 @@ export const UpdateAttributes = async (
|
||||
});
|
||||
if (!existingCollection) return { status: "Collection not found" };
|
||||
|
||||
let referencedEdges;
|
||||
for (const attr of attributes) {
|
||||
const fieldId = attr.fieldId;
|
||||
if (attr.type === "Object") {
|
||||
@@ -792,7 +795,7 @@ export const UpdateAttributes = async (
|
||||
attributeparentId: fieldId,
|
||||
isArchive: false,
|
||||
});
|
||||
|
||||
console.log("existingsubcollection: ", existingsubcollection);
|
||||
if (!existingsubcollection) {
|
||||
const fieldnamefind = await collectionsModel(organization).findOne(
|
||||
{
|
||||
@@ -824,100 +827,70 @@ export const UpdateAttributes = async (
|
||||
};
|
||||
}
|
||||
}
|
||||
const referencedEdges = await collectionsModel(organization).find({
|
||||
isArchive: false,
|
||||
projectId,
|
||||
attributes: {
|
||||
$elemMatch: {
|
||||
"refKey.collection_id": new mongoose.Types.ObjectId(
|
||||
collectionNodeId
|
||||
),
|
||||
"refKey.fieldId": new mongoose.Types.ObjectId(fieldId),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (attr.type) {
|
||||
referencedEdges = await collectionsModel(organization)
|
||||
.find({
|
||||
isArchive: false,
|
||||
projectId,
|
||||
attributes: {
|
||||
$elemMatch: {
|
||||
"refKey.collection_id": new mongoose.Types.ObjectId(
|
||||
collectionNodeId
|
||||
),
|
||||
"refKey.fieldId": new mongoose.Types.ObjectId(fieldId),
|
||||
},
|
||||
},
|
||||
})
|
||||
.select("attributes projectId collectionName type");
|
||||
console.log("referencedEdges: ", referencedEdges);
|
||||
if (referencedEdges.length) {
|
||||
for (const doc of referencedEdges) {
|
||||
let updated = false;
|
||||
|
||||
if (referencedEdges.length) {
|
||||
for (const doc of referencedEdges) {
|
||||
let updated = false;
|
||||
try {
|
||||
for (const oldattr of doc.attributes) {
|
||||
const refKey = oldattr.refKey as any;
|
||||
if (
|
||||
refKey?.collection_id?.toString() ===
|
||||
collectionNodeId.toString() &&
|
||||
refKey?.fieldId?.toString() === fieldId.toString()
|
||||
) {
|
||||
const oldType = oldattr.type;
|
||||
const newType = attr.type;
|
||||
oldattr.type = newType as any;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
// for (const oldattr of doc.attributes) {
|
||||
// console.log("oldattr: ", oldattr);
|
||||
// const refKey = oldattr.refKey as any;
|
||||
// if (
|
||||
// refKey?.collection_id?.toString() ===
|
||||
// collectionNodeId.toString() &&
|
||||
// refKey?.fieldId?.toString() === fieldId.toString()
|
||||
// ) {
|
||||
// const oldType = oldattr.type;
|
||||
// const newType = attr.type;
|
||||
|
||||
if (updated) {
|
||||
doc.markModified("attributes");
|
||||
await doc.save();
|
||||
}
|
||||
} catch (err: any) {
|
||||
return { status: "Validation Error", data: err.message };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// console.log("oldType:", oldType, "→ newType:", newType);
|
||||
|
||||
if (attr.key) {
|
||||
function updateModelName(
|
||||
oldName: string,
|
||||
newBaseName: string
|
||||
): string {
|
||||
const firstUnderscoreIndex = oldName.indexOf("_");
|
||||
// // ✅ Update directly
|
||||
// oldattr.type = newType as any;
|
||||
|
||||
if (firstUnderscoreIndex === -1) {
|
||||
return newBaseName;
|
||||
}
|
||||
// updated = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
let prefix = oldName.slice(0, firstUnderscoreIndex);
|
||||
|
||||
if (!prefix || prefix === "undefined" || prefix === "") {
|
||||
prefix = existingCollection?.collectionName as string;
|
||||
// console.log(`⚠️ Prefix invalid, fallback used: ${prefix}`);
|
||||
}
|
||||
return `${prefix}_${newBaseName}`;
|
||||
}
|
||||
|
||||
referencedEdges = await collectionsModel(organization)
|
||||
.find({
|
||||
isArchive: false,
|
||||
projectId,
|
||||
attributes: {
|
||||
$elemMatch: {
|
||||
"refKey.fieldId": new mongoose.Types.ObjectId(fieldId),
|
||||
},
|
||||
},
|
||||
})
|
||||
.select("attributes projectId collectionName type");
|
||||
|
||||
if (referencedEdges.length) {
|
||||
for (const doc of referencedEdges) {
|
||||
let updated = false;
|
||||
// if (updated) {
|
||||
// doc.markModified("attributes");
|
||||
// console.log("hi");
|
||||
// await doc.save();
|
||||
// console.log("hello");
|
||||
// console.log("doc: ", doc);
|
||||
// }
|
||||
|
||||
try {
|
||||
for (const oldattr of doc.attributes) {
|
||||
console.log("oldattr: ", oldattr);
|
||||
const refKey = oldattr.refKey as any;
|
||||
if (refKey?.fieldId?.toString() === fieldId.toString()) {
|
||||
const oldName = oldattr.key;
|
||||
const updateName = attr.key;
|
||||
const newKey = updateModelName(oldName, updateName);
|
||||
oldattr.key = newKey;
|
||||
if (
|
||||
refKey?.collection_id?.toString() ===
|
||||
collectionNodeId.toString() &&
|
||||
refKey?.fieldId?.toString() === fieldId.toString()
|
||||
) {
|
||||
const oldType = oldattr.type;
|
||||
const newType = attr.type;
|
||||
oldattr.type = newType as any;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
doc.markModified("attributes");
|
||||
await doc.save();
|
||||
}
|
||||
} catch (err: any) {
|
||||
@@ -951,9 +924,9 @@ export const UpdateAttributes = async (
|
||||
{ new: true }
|
||||
);
|
||||
|
||||
// console.log("editCollection", editCollection);
|
||||
console.log("editCollection", editCollection);
|
||||
}
|
||||
return { status: "Success", data: referencedEdges };
|
||||
return { status: "Success" };
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
@@ -1254,24 +1227,23 @@ export const DuplicateAttributes = async (
|
||||
(attr: any) => attr.key.toLowerCase() === attrKey.toLowerCase()
|
||||
);
|
||||
|
||||
console.log("existingAttr: ", existingAttr);
|
||||
if (existingAttr) {
|
||||
let counter = 1;
|
||||
let newKey = `${attrKey}(${counter})`;
|
||||
console.log("attrKey: ", attrKey);
|
||||
console.log("newKey: ", newKey);
|
||||
|
||||
while (
|
||||
existingCollection.attributes.some(
|
||||
(attr: any) => attr.key === newKey
|
||||
)
|
||||
) {
|
||||
console.log("hi");
|
||||
counter++;
|
||||
newKey = `${attrKey}(${counter})`;
|
||||
console.log("newKey: ", newKey);
|
||||
}
|
||||
|
||||
// existingCollection.attributes.push({
|
||||
// key: newKey,
|
||||
// type: existingAttr.type,
|
||||
// isArchive: false,
|
||||
// });
|
||||
} else {
|
||||
return { status: "Attribute doesnot match" };
|
||||
}
|
||||
@@ -1343,6 +1315,7 @@ export const DelAttributes = async (
|
||||
data: IAttributesDel
|
||||
): Promise<Iresponse> => {
|
||||
const { organization, userId, projectId, collectionNodeId, fieldId } = data;
|
||||
console.log("data: ", data);
|
||||
|
||||
try {
|
||||
const existingUser = await userModel(organization).findOne({
|
||||
@@ -1363,6 +1336,7 @@ export const DelAttributes = async (
|
||||
isArchive: false,
|
||||
"attributes._id": new mongoose.Types.ObjectId(fieldId),
|
||||
});
|
||||
console.log("existingCollection: ", existingCollection);
|
||||
if (!existingCollection) return { status: "Collection not found" };
|
||||
|
||||
const attribute = existingCollection.attributes.find(
|
||||
@@ -1426,6 +1400,7 @@ export const addAttributes = async (
|
||||
): Promise<Iresponse> => {
|
||||
const { organization, projectId, userId, collectionNodeId, attributes } =
|
||||
data;
|
||||
console.log("data: ", data);
|
||||
|
||||
try {
|
||||
const existingUser = await userModel(organization).findOne({
|
||||
@@ -1453,6 +1428,7 @@ export const addAttributes = async (
|
||||
const duplicate = existingAttributes.find(
|
||||
(exAttr) => exAttr.key === attr.key && !exAttr.isArchive
|
||||
);
|
||||
console.log("duplicate: ", duplicate);
|
||||
if (duplicate) {
|
||||
return { status: `Attribute "${attr.key}" already exists` };
|
||||
}
|
||||
|
||||
@@ -365,114 +365,56 @@ interface IResolvedKey {
|
||||
* If "fromField" is a foreign key, it recursively traces back
|
||||
* to its original primary field and returns its reference info.
|
||||
*/
|
||||
// export const resolveForeignKey = async (
|
||||
// organization: string,
|
||||
// fromCollection: any,
|
||||
// fromField: IAttribute
|
||||
// ): Promise<IResolvedKey> => {
|
||||
// if (!fromField) {
|
||||
// return {
|
||||
// keyType: "normal",
|
||||
// sourceCollectionName: fromCollection.collectionName,
|
||||
// sourceCollectionId: fromCollection._id?.toString?.() || "",
|
||||
// sourceFieldId: "",
|
||||
// sourceFieldName: "",
|
||||
// };
|
||||
// }
|
||||
// let keyType = fromField?.keyType || "normal";
|
||||
// let sourceCollectionName = fromCollection.collectionName;
|
||||
// let sourceCollectionId = fromCollection._id?.toString?.() || "";
|
||||
// let sourceFieldId = fromField?._id?.toString?.() || "";
|
||||
// let sourceFieldName = fromField?.key || "";
|
||||
|
||||
// // 🔁 If the field is foreign → trace back to original primary
|
||||
// if (fromField?.keyType === "foreign" && fromField?.refKey) {
|
||||
// const refCol = await collectionsModel(organization).findById(
|
||||
// fromField.refKey.collection_id
|
||||
// );
|
||||
|
||||
// if (refCol) {
|
||||
// const primaryAttr = (refCol.attributes as IAttribute[]).find(
|
||||
// (attr) => attr?._id?.toString?.() === fromField.refKey?.fieldId
|
||||
// );
|
||||
|
||||
// if (primaryAttr) {
|
||||
// console.log("🔁 Tracing back to original primary field...");
|
||||
|
||||
// // Recursive call to ensure multi-level tracing
|
||||
// return await resolveForeignKey(organization, refCol, primaryAttr);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ✅ If the field is primary, mark the propagated key as foreign
|
||||
// if (fromField?.keyType === "primary") {
|
||||
// keyType = "foreign";
|
||||
// }
|
||||
|
||||
// return {
|
||||
// keyType,
|
||||
// sourceCollectionName,
|
||||
// sourceCollectionId,
|
||||
// sourceFieldId,
|
||||
// sourceFieldName,
|
||||
// };
|
||||
// };
|
||||
export const resolveForeignKey = async (
|
||||
organization: string,
|
||||
fromCollection: any,
|
||||
fromField?: IAttribute
|
||||
fromField: IAttribute
|
||||
): Promise<IResolvedKey> => {
|
||||
if (!fromField || !fromCollection) {
|
||||
if (!fromField) {
|
||||
return {
|
||||
keyType: "normal",
|
||||
sourceCollectionName: fromCollection?.collectionName || "",
|
||||
sourceCollectionId: fromCollection?._id?.toString?.() || "",
|
||||
sourceCollectionName: fromCollection.collectionName,
|
||||
sourceCollectionId: fromCollection._id?.toString?.() || "",
|
||||
sourceFieldId: "",
|
||||
sourceFieldName: "",
|
||||
};
|
||||
}
|
||||
|
||||
let keyType = fromField.keyType || "normal";
|
||||
let keyType = fromField?.keyType || "normal";
|
||||
let sourceCollectionName = fromCollection.collectionName;
|
||||
let sourceCollectionId = fromCollection._id?.toString?.() || "";
|
||||
let sourceFieldId = fromField._id?.toString?.() || "";
|
||||
let sourceFieldName = fromField.key || "";
|
||||
let sourceFieldId = fromField?._id?.toString?.() || "";
|
||||
let sourceFieldName = fromField?.key || "";
|
||||
|
||||
// 🔁 Recursive tracing for both FOREIGN and SECONDARY with refKey
|
||||
if (
|
||||
// 🔁 If the field is foreign → trace back to original primary
|
||||
// if (fromField?.keyType === "foreign" && fromField?.refKey) {
|
||||
// const refCol = await collectionsModel(organization).findById(
|
||||
// fromField.refKey.collection_id
|
||||
// );
|
||||
if (
|
||||
(fromField.keyType === "foreign" || fromField.keyType === "secondary") &&
|
||||
fromField.refKey
|
||||
) {
|
||||
const refCol = await collectionsModel(organization).findById(
|
||||
fromField.refKey.collection_id
|
||||
);
|
||||
|
||||
if (refCol) {
|
||||
const refField = (refCol.attributes as IAttribute[]).find(
|
||||
const primaryAttr = (refCol.attributes as IAttribute[]).find(
|
||||
(attr) => attr?._id?.toString?.() === fromField.refKey?.fieldId
|
||||
);
|
||||
|
||||
if (refField) {
|
||||
console.log(
|
||||
`🔁 Tracing ${fromField.keyType} key ${fromField.key} → ${refCol.collectionName}.${refField.key}`
|
||||
);
|
||||
// Recursive call — trace until primary
|
||||
return await resolveForeignKey(organization, refCol, refField);
|
||||
} else {
|
||||
console.warn(
|
||||
`⚠️ Field not found for refKey.fieldId: ${fromField.refKey?.fieldId}`
|
||||
);
|
||||
if (primaryAttr) {
|
||||
console.log("🔁 Tracing back to original primary field...");
|
||||
|
||||
// Recursive call to ensure multi-level tracing
|
||||
return await resolveForeignKey(organization, refCol, primaryAttr);
|
||||
}
|
||||
} else {
|
||||
console.warn(
|
||||
`⚠️ Collection not found for refKey.collection_id: ${fromField.refKey?.collection_id}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ Convert primary to foreign for propagation
|
||||
if (fromField.keyType === "primary") keyType = "foreign";
|
||||
// ✅ If the field is primary, mark the propagated key as foreign
|
||||
if (fromField?.keyType === "primary") {
|
||||
keyType = "foreign";
|
||||
}
|
||||
|
||||
return {
|
||||
keyType,
|
||||
|
||||
@@ -24,11 +24,24 @@ interface IgroupNode {
|
||||
y: number;
|
||||
zoom: number;
|
||||
};
|
||||
style: {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface IunGrp {
|
||||
projectId: string;
|
||||
groupId: string;
|
||||
position: {
|
||||
x: number;
|
||||
y: number;
|
||||
zoom: number;
|
||||
};
|
||||
style: {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
userId: string;
|
||||
organization: string;
|
||||
collections: IcollectionsNode[];
|
||||
@@ -41,6 +54,7 @@ export const groupcreationService = async (
|
||||
organization,
|
||||
projectId,
|
||||
position,
|
||||
style,
|
||||
userId,
|
||||
groupName,
|
||||
type,
|
||||
@@ -95,6 +109,7 @@ export const groupcreationService = async (
|
||||
groupName,
|
||||
type,
|
||||
position,
|
||||
style,
|
||||
projectId,
|
||||
createdBy: userId,
|
||||
collections: validCollectionIds,
|
||||
@@ -102,7 +117,7 @@ export const groupcreationService = async (
|
||||
if (validCollectionIds.length > 0) {
|
||||
await collectionsModel(organization).updateMany(
|
||||
{ _id: { $in: validCollectionIds } },
|
||||
{ $set: { groupParentId: newGroup._id } }
|
||||
{ $set: { groupParentId: newGroup._id, extent: "parent" } }
|
||||
);
|
||||
}
|
||||
if (invalidIds.length > 0) {
|
||||
@@ -148,10 +163,12 @@ export const groupcreationService = async (
|
||||
|
||||
if (newIds.length > 0) {
|
||||
existingGroup.collections.push(...newIds);
|
||||
existingGroup.style;
|
||||
existingGroup.position;
|
||||
await existingGroup.save();
|
||||
await collectionsModel(organization).updateMany(
|
||||
{ _id: { $in: newIds } },
|
||||
{ $set: { groupParentId: existingGroup._id } }
|
||||
{ $set: { groupParentId: existingGroup._id, extent: "parent" } }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -178,7 +195,15 @@ export const groupcreationService = async (
|
||||
};
|
||||
|
||||
export const unGrpService = async (data: IunGrp): Promise<Iresponse> => {
|
||||
const { organization, projectId, userId, groupId, collections } = data;
|
||||
const {
|
||||
organization,
|
||||
projectId,
|
||||
userId,
|
||||
groupId,
|
||||
style,
|
||||
position,
|
||||
collections,
|
||||
} = data;
|
||||
try {
|
||||
const ExistingUser = await userModel(organization).findOne({
|
||||
_id: userId,
|
||||
@@ -214,6 +239,8 @@ export const unGrpService = async (data: IunGrp): Promise<Iresponse> => {
|
||||
|
||||
if (index1 !== -1) {
|
||||
existingGroup.collections.splice(index1, 1);
|
||||
existingGroup.style;
|
||||
existingGroup.position;
|
||||
await existingGroup.save();
|
||||
|
||||
const deleteCollection = await collectionsModel(
|
||||
@@ -226,6 +253,7 @@ export const unGrpService = async (data: IunGrp): Promise<Iresponse> => {
|
||||
|
||||
if (deleteCollection) {
|
||||
deleteCollection.groupParentId = undefined;
|
||||
deleteCollection.extent = "";
|
||||
await deleteCollection.save();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -110,6 +110,7 @@ export const CollectionUpdateHandleEvent = async (
|
||||
return;
|
||||
}
|
||||
const result = await updatecollection(data);
|
||||
console.log('result: ', result);
|
||||
|
||||
const status = typeof result?.status === "string" ? result.status : "unknown";
|
||||
|
||||
|
||||
130
src/socket-server/controllers/groupContoller.ts
Normal file
130
src/socket-server/controllers/groupContoller.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import { Socket, Server } from "socket.io";
|
||||
import { EVENTS } from "../events/events";
|
||||
import {
|
||||
ErrorResponse,
|
||||
FinalResponse,
|
||||
validateFields,
|
||||
} from "../utils/socketfunctionHelpers";
|
||||
import { emitToRoom } from "../utils/emitEventResponse";
|
||||
import { groupcreationService, unGrpService } from "../../shared/services/groupService";
|
||||
|
||||
export const addGroupHandleEvent = async (
|
||||
event: string,
|
||||
socket: Socket,
|
||||
io: Server,
|
||||
data: any,
|
||||
connectedUsersByOrg: {
|
||||
[org: string]: { socketId: string; userId: string; role: string }[];
|
||||
}
|
||||
) => {
|
||||
if (event !== EVENTS.addGroupCollection || !data?.organization) return;
|
||||
const requiredFields = ["position", "projectId", "organization","groupName"];
|
||||
const missingFields = validateFields(data, requiredFields);
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
let room: string | undefined;
|
||||
|
||||
if (data?.projectId) {
|
||||
room = data.projectId.toString();
|
||||
}
|
||||
if (room) {
|
||||
emitToRoom(
|
||||
io,
|
||||
socket,
|
||||
room,
|
||||
EVENTS.addGroupCollectionResponse,
|
||||
ErrorResponse(missingFields, socket, room)
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const result = await groupcreationService(data);
|
||||
const status = typeof result?.status === "string" ? result.status : "unknown";
|
||||
|
||||
const messages: Record<string, { message: string }> = {
|
||||
Success: { message: "Group created successfully" },
|
||||
"Project not found": { message: "Project not found" },
|
||||
"User not found": { message: "User not found" },
|
||||
};
|
||||
|
||||
const msg = messages[status] || { message: "Internal server error" };
|
||||
const result_Datas =
|
||||
status === "Success" && result?.data ? result.data : undefined;
|
||||
|
||||
const response = FinalResponse(
|
||||
status,
|
||||
socket,
|
||||
data.organization,
|
||||
messages,
|
||||
result_Datas
|
||||
);
|
||||
let room: string | undefined;
|
||||
if (data?.projectId) {
|
||||
room = data.projectId.toString();
|
||||
}
|
||||
|
||||
if (room) {
|
||||
console.log('room: ', room);
|
||||
emitToRoom(io, socket, room, EVENTS.addGroupCollectionResponse, response);
|
||||
}
|
||||
};
|
||||
export const unGroupHandleEvent = async (
|
||||
event: string,
|
||||
socket: Socket,
|
||||
io: Server,
|
||||
data: any,
|
||||
connectedUsersByOrg: {
|
||||
[org: string]: { socketId: string; userId: string; role: string }[];
|
||||
}
|
||||
) => {
|
||||
if (event !== EVENTS.unGroupCollection || !data?.organization) return;
|
||||
const requiredFields = ["position", "projectId", "organization","groupId"];
|
||||
const missingFields = validateFields(data, requiredFields);
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
let room: string | undefined;
|
||||
|
||||
if (data?.projectId) {
|
||||
room = data.projectId.toString();
|
||||
}
|
||||
if (room) {
|
||||
emitToRoom(
|
||||
io,
|
||||
socket,
|
||||
room,
|
||||
EVENTS.unGroupCollectionResponse,
|
||||
ErrorResponse(missingFields, socket, room)
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const result = await unGrpService(data);
|
||||
const status = typeof result?.status === "string" ? result.status : "unknown";
|
||||
|
||||
const messages: Record<string, { message: string }> = {
|
||||
Success: { message: "Group created successfully" },
|
||||
"Project not found": { message: "Project not found" },
|
||||
"User not found": { message: "User not found" },
|
||||
};
|
||||
|
||||
const msg = messages[status] || { message: "Internal server error" };
|
||||
const result_Datas =
|
||||
status === "Success" && result?.data ? result.data : undefined;
|
||||
|
||||
const response = FinalResponse(
|
||||
status,
|
||||
socket,
|
||||
data.organization,
|
||||
messages,
|
||||
result_Datas
|
||||
);
|
||||
let room: string | undefined;
|
||||
if (data?.projectId) {
|
||||
room = data.projectId.toString();
|
||||
}
|
||||
|
||||
if (room) {
|
||||
console.log('room: ', room);
|
||||
emitToRoom(io, socket, room, EVENTS.unGroupCollectionResponse, response);
|
||||
}
|
||||
};
|
||||
@@ -55,27 +55,27 @@ export const projectHandleEvent = async (
|
||||
}
|
||||
const result = await projectCreationService(data);
|
||||
const status = typeof result?.status === "string" ? result.status : "unknown";
|
||||
if (result.status === "Success") {
|
||||
const fetchResult = await folderProject(
|
||||
subBkd,
|
||||
data.projectName,
|
||||
data.language,
|
||||
data.apiProtocol,
|
||||
data.application,
|
||||
data.architecture
|
||||
);
|
||||
// if (fetchResult) {
|
||||
// res.status(200).json({
|
||||
// message: "Project creation unsuccessfull",
|
||||
// projectId: result.data,
|
||||
// });
|
||||
// // return { status: "Success", data: fetchResult.data };
|
||||
// } else {
|
||||
// res.status(500).json({
|
||||
// message: "error",
|
||||
// });
|
||||
// }
|
||||
}
|
||||
// if (result.status === "Success") {
|
||||
// const fetchResult = await folderProject(
|
||||
// subBkd,
|
||||
// data.projectName,
|
||||
// data.language,
|
||||
// data.apiProtocol,
|
||||
// data.application,
|
||||
// data.architecture
|
||||
// );
|
||||
// // if (fetchResult) {
|
||||
// // res.status(200).json({
|
||||
// // message: "Project creation unsuccessfull",
|
||||
// // projectId: result.data,
|
||||
// // });
|
||||
// // // return { status: "Success", data: fetchResult.data };
|
||||
// // } else {
|
||||
// // res.status(500).json({
|
||||
// // message: "error",
|
||||
// // });
|
||||
// // }
|
||||
// }
|
||||
const messages: Record<string, { message: string }> = {
|
||||
Success: { message: "Project Created Successfully" },
|
||||
"Project Already Exists": { message: "Project Already Exists" },
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
setAttributesHandleEvent,
|
||||
} from "../controllers/collectionNodeController";
|
||||
import { deleteEdgeHandleEvent, edgeHandleEvent } from "../controllers/edgeController";
|
||||
import { addGroupHandleEvent, unGroupHandleEvent } from "../controllers/groupContoller";
|
||||
import {
|
||||
projectClearHandleEvent,
|
||||
projectDeleteHandleEvent,
|
||||
@@ -32,4 +33,7 @@ export const eventHandlerMap: Record<string, Function> = {
|
||||
|
||||
[EVENTS.edgeConnect]: edgeHandleEvent,
|
||||
[EVENTS.deleteEdgeConnect]: deleteEdgeHandleEvent,
|
||||
|
||||
[EVENTS.addGroupCollection]: addGroupHandleEvent,
|
||||
[EVENTS.unGroupCollection]: unGroupHandleEvent,
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@ export const EVENTS = {
|
||||
roomCreated: "roomCreated",
|
||||
roomDeleted: "roomDeleted",
|
||||
|
||||
|
||||
projectCreate: "v1:project:create",
|
||||
projectCreateResponse: "v1:response:project:create",
|
||||
projectUpdate: "v1:project:update",
|
||||
@@ -33,12 +32,19 @@ export const EVENTS = {
|
||||
collectionAttributeSet: "v1:collection-node:attributeSet",
|
||||
collectionAttributeSetResponse: "v1:response:collection-node:attributeSet",
|
||||
collectionAttributeUpdate: "v1:collection-node:attributeUpdate",
|
||||
collectionAttributeUpdateResponse: "v1:response:collection-node:attributeUpdate",
|
||||
collectionAttributeUpdateResponse:
|
||||
"v1:response:collection-node:attributeUpdate",
|
||||
collectionAttributeDelete: "v1:collection-node:attributeDelete",
|
||||
collectionAttributeDeleteResponse: "v1:response:collection-node:attributeDelete",
|
||||
collectionAttributeDeleteResponse:
|
||||
"v1:response:collection-node:attributeDelete",
|
||||
|
||||
edgeConnect: "v1:edge:connect",
|
||||
edgeConnectResponse: "v1:response:edge:connect",
|
||||
deleteEdgeConnect: "v1:edge:deleteConnect",
|
||||
deleteEdgeConnectResponse: "v1:response:edge:deleteConnect",
|
||||
}
|
||||
|
||||
addGroupCollection: "v1:group:add",
|
||||
addGroupCollectionResponse: "v1:response:group:ungroup",
|
||||
unGroupCollection: "v1:group:update",
|
||||
unGroupCollectionResponse: "v1:response:group:ungroup",
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user