Add plugin platform with modular backend and frontend registry.

Split graph/import/meta into Django apps, add API v1 with OpenAPI and pytest, and introduce plugin registry with the tags reference plugin on both FE and BE.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-25 09:35:51 +03:00
co-authored by Cursor
parent b694a596b8
commit cafc7335ad
77 changed files with 1801 additions and 490 deletions
+66
View File
@@ -0,0 +1,66 @@
from contacts.models import Contact, Relation, NetworkMap, NetworkMapMembership
def node_from_contact(contact):
return {
'id': contact.id,
'label': contact.name,
'title': '\n'.join(filter(None, [contact.organization, contact.position, contact.email])),
'group': contact.organization or 'default',
}
def node_from_membership(membership):
contact = membership.contact
return {
**node_from_contact(contact),
'life_sphere': membership.life_sphere,
'network_circle': membership.network_circle,
'importance': membership.importance,
'map_angle': membership.map_angle,
'map_radius_ratio': membership.map_radius_ratio,
'membership_id': membership.id,
}
def edge_from_relation(relation):
return {
'id': relation.id,
'from': relation.source_id,
'to': relation.target_id,
'label': relation.get_relation_type_display(),
'title': relation.description or relation.get_relation_type_display(),
'relation_type': relation.relation_type,
'interaction_intensity': relation.interaction_intensity,
}
def build_full_graph():
contacts = Contact.objects.all()
nodes = [node_from_contact(c) for c in contacts]
relations = Relation.objects.select_related('source', 'target').all()
edges = [edge_from_relation(r) for r in relations]
return {'nodes': nodes, 'edges': edges}
def build_network_map_graph(map_id=None):
if not map_id:
default_map = NetworkMap.objects.order_by('id').first()
if not default_map:
return {'nodes': [], 'edges': []}
map_id = default_map.id
memberships = list(
NetworkMapMembership.objects.filter(map_id=map_id)
.select_related('contact')
.order_by('contact__name')
)
allowed_ids = {m.contact_id for m in memberships}
nodes = [node_from_membership(m) for m in memberships]
relations = Relation.objects.select_related('source', 'target').all()
edges = [
edge_from_relation(r)
for r in relations
if r.source_id in allowed_ids and r.target_id in allowed_ids
]
return {'nodes': nodes, 'edges': edges}