feat: local Bootstrap Vue ECharts dashboards and universal genealogy write scope
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
"""Generation-based write boundaries. Viewing and role grants are separate."""
|
||||
from collections import deque
|
||||
|
||||
LIMIT = 5
|
||||
|
||||
|
||||
def generations(people, links, self_id):
|
||||
ids = {p['id'] for p in people}
|
||||
if self_id not in ids:
|
||||
return {}, False
|
||||
graph = {key: [] for key in ids}
|
||||
for edge in links:
|
||||
a, b = edge.get('fromId'), edge.get('toId')
|
||||
if not edge.get('active') or a not in ids or b not in ids:
|
||||
continue
|
||||
delta = 1 if edge.get('kind') == 'parent' else 0
|
||||
if edge.get('kind') not in ('parent', 'spouse'):
|
||||
continue
|
||||
graph[a].append((b, delta))
|
||||
graph[b].append((a, -delta))
|
||||
levels, pending, conflict = {self_id: 0}, deque([self_id]), False
|
||||
while pending:
|
||||
current = pending.popleft()
|
||||
for other, delta in graph[current]:
|
||||
level = levels[current] + delta
|
||||
if other in levels:
|
||||
conflict |= levels[other] != level
|
||||
else:
|
||||
levels[other] = level
|
||||
pending.append(other)
|
||||
return levels, conflict
|
||||
|
||||
|
||||
def within(levels, person_id):
|
||||
return person_id in levels and abs(levels[person_id]) <= LIMIT
|
||||
|
||||
|
||||
def targets(kind, item):
|
||||
if kind == 'person':
|
||||
return [item['id']]
|
||||
if kind == 'link':
|
||||
return [item['fromId'], item['toId']]
|
||||
return item.get('personIds', [])
|
||||
Reference in New Issue
Block a user