feat: Oracle Canvas, Revision History and Canvas Sharing (#33)
Co-authored-by: Sagnik <sagnik7896@gmail.com> Reviewed-on: #33
This commit was merged in pull request #33.
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user