feat: Oracle Canvas, Revision History and Canvas Sharing

This commit is contained in:
Sagnik
2026-04-23 01:19:03 +05:30
parent e519339cc9
commit 527b10cd41
58 changed files with 3187 additions and 705 deletions

View File

@@ -11,6 +11,8 @@ import uuid
from datetime import datetime, timezone
from typing import Any
from .canvas_service import canvas_service
logger = logging.getLogger(__name__)
# ── In-memory store (demo mode) ───────────────────────────────────────────────
@@ -23,6 +25,32 @@ def _now() -> str:
return datetime.now(timezone.utc).isoformat()
def _clone_components_for_fork(
components: list[dict[str, Any]],
*,
actor_id: str,
source_page_id: str,
source_branch_id: str,
source_revision: int,
) -> list[dict[str, Any]]:
cloned: list[dict[str, Any]] = []
for component in components:
forked = copy.deepcopy(component)
original_component_id = str(forked.get("componentId") or "")
forked["componentId"] = str(uuid.uuid4())
provenance = dict(forked.get("provenance") or {})
provenance["forkedAt"] = _now()
provenance["forkedBy"] = actor_id
provenance["sourcePageId"] = source_page_id
provenance["sourceBranchId"] = source_branch_id
provenance["sourceRevision"] = source_revision
if original_component_id:
provenance["sourceComponentId"] = original_component_id
forked["provenance"] = provenance
cloned.append(forked)
return cloned
# ── Three-way diff engine ─────────────────────────────────────────────────────
def _three_way_diff(
@@ -228,17 +256,50 @@ class CollaborationService:
Creates a fork from the source_page snapshot at its current headRevision.
Returns ForkRecord.
"""
if recipient_user_id == created_by:
raise ValueError("You cannot share a canvas with your own account.")
fork_id = str(uuid.uuid4())
fork_page_id = str(uuid.uuid4())
fork_branch_id = str(uuid.uuid4())
fork_page = await canvas_service.create_page(
tenant_id=source_page["tenantId"],
owner_id=recipient_user_id,
title=f"{source_page['title']} Fork",
page_type="fork",
branch_name=f"fork-{str(fork_id)[:8]}",
sharing_policy={
"shareMode": "direct_fork_only",
"allowReshare": visibility == "team",
"defaultForkVisibility": visibility,
},
)
fork_components = _clone_components_for_fork(
source_page.get("components", []),
actor_id=created_by,
source_page_id=source_page["pageId"],
source_branch_id=source_page["branchId"],
source_revision=source_page["headRevision"],
)
await canvas_service.commit_revision(
page_id=fork_page["pageId"],
tenant_id=source_page["tenantId"],
actor_id=created_by,
commit_kind="merge",
commit_summary=f"Forked from {source_page['title']} at rev.{source_page['headRevision']}",
components=fork_components,
execution_id=None,
merge_request_id=None,
idempotency_key=f"fork_{fork_id}",
)
fork = {
"forkId": fork_id,
"sourcePageId": source_page["pageId"],
"sourceBranchId": source_page["branchId"],
"sourceRevision": source_page["headRevision"],
"forkPageId": fork_page_id,
"forkBranchId": fork_branch_id,
"forkPageId": fork_page["pageId"],
"forkBranchId": fork_page["branchId"],
"recipientUserId": recipient_user_id,
"createdBy": created_by,
"visibility": visibility,