feat(interfaces): add comprehensive TypeScript interface modules, demo data, docs, and publish metadata
This commit is contained in:
365
ts_interfaces/collaboration.ts
Normal file
365
ts_interfaces/collaboration.ts
Normal file
@@ -0,0 +1,365 @@
|
||||
/**
|
||||
* @file collaboration.ts
|
||||
* @description Collaboration interfaces
|
||||
* Comments, suggestions, user presence, and collaborative editing support
|
||||
*/
|
||||
|
||||
import * as plugins from './plugins.js';
|
||||
import type {
|
||||
TPresenceStatus,
|
||||
TCommentThreadStatus,
|
||||
TSuggestionStatus,
|
||||
TSuggestionChangeType,
|
||||
TConflictResolutionStrategy,
|
||||
TEditingMode,
|
||||
TCollaborationPermission,
|
||||
} from './types.js';
|
||||
import type { IVersionChange } from './versioning.js';
|
||||
|
||||
// ============================================================================
|
||||
// USER PRESENCE
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* User's current location in document
|
||||
*/
|
||||
export interface IUserLocation {
|
||||
paragraphId?: string;
|
||||
characterPosition?: number;
|
||||
selectionRange?: {
|
||||
start: number;
|
||||
end: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Device information for presence
|
||||
*/
|
||||
export interface IDeviceInfo {
|
||||
type: 'desktop' | 'tablet' | 'mobile';
|
||||
browser?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* User presence information
|
||||
*/
|
||||
export interface IUserPresence {
|
||||
userId: string;
|
||||
displayName: string;
|
||||
avatarUrl?: string;
|
||||
color: string;
|
||||
status: TPresenceStatus;
|
||||
currentLocation?: IUserLocation;
|
||||
lastActivity: number;
|
||||
sessionStarted: number;
|
||||
deviceInfo?: IDeviceInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Real-time cursor position for collaborative editing
|
||||
*/
|
||||
export interface ICursorPosition {
|
||||
userId: string;
|
||||
paragraphId: string;
|
||||
offset: number;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// COMMENTS
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Anchor point for a comment
|
||||
*/
|
||||
export interface ICommentAnchor {
|
||||
type: 'paragraph' | 'text_range' | 'document' | 'party' | 'attachment';
|
||||
paragraphId?: string;
|
||||
textRange?: {
|
||||
start: number;
|
||||
end: number;
|
||||
quotedText: string;
|
||||
};
|
||||
elementPath?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* User mention in comment
|
||||
*/
|
||||
export interface IMention {
|
||||
userId: string;
|
||||
displayName: string;
|
||||
notified: boolean;
|
||||
notifiedAt?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reaction on a comment
|
||||
*/
|
||||
export interface IReaction {
|
||||
emoji: string;
|
||||
userId: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Individual comment within a thread
|
||||
*/
|
||||
export interface IComment {
|
||||
id: string;
|
||||
threadId: string;
|
||||
authorId: string;
|
||||
authorDisplayName: string;
|
||||
authorAvatarUrl?: string;
|
||||
content: string;
|
||||
createdAt: number;
|
||||
editedAt?: number;
|
||||
mentions: IMention[];
|
||||
reactions: IReaction[];
|
||||
parentCommentId?: string;
|
||||
isDeleted: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comment thread on a specific location
|
||||
*/
|
||||
export interface ICommentThread {
|
||||
id: string;
|
||||
contractId: string;
|
||||
versionId: string;
|
||||
anchor: ICommentAnchor;
|
||||
status: TCommentThreadStatus;
|
||||
resolvedBy?: string;
|
||||
resolvedAt?: number;
|
||||
comments: IComment[];
|
||||
createdAt: number;
|
||||
createdBy: string;
|
||||
lastActivityAt: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// SUGGESTIONS
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Suggestion for proposed changes (track changes mode)
|
||||
*/
|
||||
export interface ISuggestion {
|
||||
id: string;
|
||||
contractId: string;
|
||||
versionId: string;
|
||||
targetParagraphId: string;
|
||||
targetTextRange?: {
|
||||
start: number;
|
||||
end: number;
|
||||
};
|
||||
changeType: TSuggestionChangeType;
|
||||
originalContent: string;
|
||||
suggestedContent: string;
|
||||
status: TSuggestionStatus;
|
||||
suggestedBy: string;
|
||||
suggestedByDisplayName: string;
|
||||
suggestedAt: number;
|
||||
reviewedBy?: string;
|
||||
reviewedAt?: number;
|
||||
rejectionReason?: string;
|
||||
discussionThreadId?: string;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// CONFLICTS
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Conflicting change from a user
|
||||
*/
|
||||
export interface IConflictingChange {
|
||||
userId: string;
|
||||
userDisplayName: string;
|
||||
content: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conflict marker for simultaneous edits
|
||||
*/
|
||||
export interface IEditConflict {
|
||||
id: string;
|
||||
contractId: string;
|
||||
paragraphId: string;
|
||||
baseContent: string;
|
||||
changes: IConflictingChange[];
|
||||
status: 'unresolved' | 'resolved' | 'auto_merged';
|
||||
resolvedContent?: string;
|
||||
resolvedBy?: string;
|
||||
resolvedAt?: number;
|
||||
resolutionStrategy?: TConflictResolutionStrategy;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// COLLABORATION SESSION
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Collaborative editing session
|
||||
*/
|
||||
export interface ICollaborationSession {
|
||||
id: string;
|
||||
contractId: string;
|
||||
versionId: string;
|
||||
participants: IUserPresence[];
|
||||
editingMode: TEditingMode;
|
||||
activeCursors: ICursorPosition[];
|
||||
pendingChanges: IVersionChange[];
|
||||
startedAt: number;
|
||||
lastActivityAt: number;
|
||||
autoSaveInterval: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// COLLABORATOR
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Notification preferences for a collaborator
|
||||
*/
|
||||
export interface INotificationPreferences {
|
||||
onComment: boolean;
|
||||
onSuggestion: boolean;
|
||||
onVersionPublish: boolean;
|
||||
onSignatureRequest: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collaborator with permission
|
||||
*/
|
||||
export interface ICollaborator {
|
||||
userId: string;
|
||||
contact: plugins.tsclass.business.TContact;
|
||||
permission: TCollaborationPermission;
|
||||
invitedBy: string;
|
||||
invitedAt: number;
|
||||
acceptedAt?: number;
|
||||
expiresAt?: number;
|
||||
notificationPreferences: INotificationPreferences;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// FACTORY FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Create a new comment thread
|
||||
*/
|
||||
export function createCommentThread(
|
||||
contractId: string,
|
||||
versionId: string,
|
||||
anchor: ICommentAnchor,
|
||||
userId: string
|
||||
): ICommentThread {
|
||||
const now = Date.now();
|
||||
return {
|
||||
id: crypto.randomUUID(),
|
||||
contractId,
|
||||
versionId,
|
||||
anchor,
|
||||
status: 'open',
|
||||
comments: [],
|
||||
createdAt: now,
|
||||
createdBy: userId,
|
||||
lastActivityAt: now,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new comment
|
||||
*/
|
||||
export function createComment(
|
||||
threadId: string,
|
||||
authorId: string,
|
||||
authorDisplayName: string,
|
||||
content: string
|
||||
): IComment {
|
||||
return {
|
||||
id: crypto.randomUUID(),
|
||||
threadId,
|
||||
authorId,
|
||||
authorDisplayName,
|
||||
content,
|
||||
createdAt: Date.now(),
|
||||
mentions: [],
|
||||
reactions: [],
|
||||
isDeleted: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new suggestion
|
||||
*/
|
||||
export function createSuggestion(
|
||||
contractId: string,
|
||||
versionId: string,
|
||||
targetParagraphId: string,
|
||||
changeType: TSuggestionChangeType,
|
||||
originalContent: string,
|
||||
suggestedContent: string,
|
||||
suggestedBy: string,
|
||||
suggestedByDisplayName: string
|
||||
): ISuggestion {
|
||||
return {
|
||||
id: crypto.randomUUID(),
|
||||
contractId,
|
||||
versionId,
|
||||
targetParagraphId,
|
||||
changeType,
|
||||
originalContent,
|
||||
suggestedContent,
|
||||
status: 'pending',
|
||||
suggestedBy,
|
||||
suggestedByDisplayName,
|
||||
suggestedAt: Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collaborator
|
||||
*/
|
||||
export function createCollaborator(
|
||||
userId: string,
|
||||
contact: plugins.tsclass.business.TContact,
|
||||
permission: TCollaborationPermission,
|
||||
invitedBy: string
|
||||
): ICollaborator {
|
||||
return {
|
||||
userId,
|
||||
contact,
|
||||
permission,
|
||||
invitedBy,
|
||||
invitedAt: Date.now(),
|
||||
notificationPreferences: {
|
||||
onComment: true,
|
||||
onSuggestion: true,
|
||||
onVersionPublish: true,
|
||||
onSignatureRequest: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default user presence
|
||||
*/
|
||||
export function createUserPresence(
|
||||
userId: string,
|
||||
displayName: string,
|
||||
color: string
|
||||
): IUserPresence {
|
||||
const now = Date.now();
|
||||
return {
|
||||
userId,
|
||||
displayName,
|
||||
color,
|
||||
status: 'viewing',
|
||||
lastActivity: now,
|
||||
sessionStarted: now,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user