From a9c2d2230ccc7d38d7351ef8c5364bc4a98d19bb Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Thu, 18 Dec 2025 17:46:16 +0000 Subject: [PATCH] feat(icons): migrate icon usage to the new dees-icon API and integrate collaboration sidebar into the editor --- changelog.md | 10 + readme.hints.md | 31 + ts_web/00_commitinfo_data.ts | 2 +- ts_web/elements/index.ts | 1 + .../sdig-collaboration-sidebar/index.ts | 1 + .../sdig-collaboration-sidebar.ts | 846 ++++++++++++++++++ .../sdig-contract-attachments.ts | 40 +- .../sdig-contract-audit.ts | 36 +- .../sdig-contract-collaboration.ts | 22 +- .../sdig-contract-content.ts | 38 +- .../sdig-contract-header.ts | 8 +- .../sdig-contract-metadata.ts | 8 +- .../sdig-contract-parties.ts | 40 +- .../sdig-contract-signatures.ts | 50 +- .../sdig-contract-terms.ts | 28 +- .../sdig-contracteditor.ts | 62 +- ts_web/elements/sdig-contracteditor/types.ts | 16 +- 17 files changed, 1090 insertions(+), 149 deletions(-) create mode 100644 ts_web/elements/sdig-collaboration-sidebar/index.ts create mode 100644 ts_web/elements/sdig-collaboration-sidebar/sdig-collaboration-sidebar.ts diff --git a/changelog.md b/changelog.md index 7627efe..dd829e9 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,15 @@ # Changelog +## 2025-12-18 - 1.2.0 - feat(icons) +migrate icon usage to the new dees-icon API and integrate collaboration sidebar into the editor + +- Replaced deprecated .iconFA with .icon across multiple components +- Updated lucide icon identifiers to PascalCase/camelCase to match new dees-icon format +- Added sdig-collaboration-sidebar component and exported it from elements index +- Integrated a toggleable editor sidebar (PanelRight) and wired comment/suggestion navigation & add-comment events in sdig-contracteditor +- Added development hints (readme.hints.md) documenting dees-icon usage and icon name formats +- Minor UI/styling tweak: .btn-ghost.active appearance + ## 2025-12-18 - 1.1.0 - feat(catalog) add ContractEditor and many editor subcomponents; implement SignPad and SignBox; update README and bump dependencies diff --git a/readme.hints.md b/readme.hints.md index e69de29..9dd081f 100644 --- a/readme.hints.md +++ b/readme.hints.md @@ -0,0 +1,31 @@ +# Development Hints for @signature.digital/catalog + +## dees-icon Usage + +**Important**: Use the `.icon` property, NOT `.iconFA` (deprecated). + +### Format +```html + +``` + +### Lucide Icons (PascalCase) +Lucide icons use **PascalCase** names: +- `lucide:CheckCircle` ✓ +- `lucide:UserPlus` ✓ +- `lucide:PenTool` ✓ +- `lucide:Mail` ✓ +- `lucide:Users` ✓ + +**Wrong formats**: +- `lucide:check-circle` ✗ (kebab-case doesn't work) +- `lucide:userPlus` ✗ (camelCase doesn't work) + +### FontAwesome Icons (camelCase) +FontAwesome icons use **camelCase** names: +- `fa:arrowRight` +- `fa:magnifyingGlass` +- `fa:penToSquare` + +### Documentation +See: https://code.foss.global/design.estate/dees-catalog/src/branch/main/readme.icons.md diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 66d8e8f..c43e74f 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@signature.digital/catalog', - version: '1.1.0', + version: '1.2.0', description: 'A comprehensive catalog of customizable web components designed for building and managing e-signature applications.' } diff --git a/ts_web/elements/index.ts b/ts_web/elements/index.ts index 873bd7a..3283b75 100644 --- a/ts_web/elements/index.ts +++ b/ts_web/elements/index.ts @@ -11,6 +11,7 @@ export * from './sdig-contract-signatures/index.js'; export * from './sdig-contract-attachments/index.js'; export * from './sdig-contract-collaboration/index.js'; export * from './sdig-contract-audit/index.js'; +export * from './sdig-collaboration-sidebar/index.js'; // Signature components export * from './sdig-signbox/index.js'; diff --git a/ts_web/elements/sdig-collaboration-sidebar/index.ts b/ts_web/elements/sdig-collaboration-sidebar/index.ts new file mode 100644 index 0000000..f8500cd --- /dev/null +++ b/ts_web/elements/sdig-collaboration-sidebar/index.ts @@ -0,0 +1 @@ +export * from './sdig-collaboration-sidebar.js'; diff --git a/ts_web/elements/sdig-collaboration-sidebar/sdig-collaboration-sidebar.ts b/ts_web/elements/sdig-collaboration-sidebar/sdig-collaboration-sidebar.ts new file mode 100644 index 0000000..51e4ac2 --- /dev/null +++ b/ts_web/elements/sdig-collaboration-sidebar/sdig-collaboration-sidebar.ts @@ -0,0 +1,846 @@ +/** + * @file sdig-collaboration-sidebar.ts + * @description Compact collaboration sidebar for the contract editor + */ + +import { + DeesElement, + property, + html, + customElement, + type TemplateResult, + css, + cssManager, + state, +} from '@design.estate/dees-element'; + +import * as plugins from '../../plugins.js'; + +declare global { + interface HTMLElementTagNameMap { + 'sdig-collaboration-sidebar': SdigCollaborationSidebar; + } +} + +// Comment interface +interface IComment { + id: string; + userId: string; + userName: string; + userColor: string; + content: string; + createdAt: number; + updatedAt?: number; + anchorPath?: string; + anchorText?: string; + resolved: boolean; + replies: IComment[]; +} + +// Suggestion interface +interface ISuggestion { + id: string; + userId: string; + userName: string; + userColor: string; + originalText: string; + suggestedText: string; + path: string; + status: 'pending' | 'accepted' | 'rejected'; + createdAt: number; +} + +// Presence interface +interface IPresence { + userId: string; + userName: string; + userColor: string; + currentSection: string; + cursorPosition?: { path: string; offset: number }; + lastActive: number; +} + +@customElement('sdig-collaboration-sidebar') +export class SdigCollaborationSidebar extends DeesElement { + // ============================================================================ + // STATIC + // ============================================================================ + + public static demo = () => html` +
+ +
+ `; + + public static styles = [ + cssManager.defaultStyles, + css` + :host { + display: block; + height: 100%; + overflow: hidden; + } + + .sidebar-container { + display: flex; + flex-direction: column; + height: 100%; + } + + /* Presence bar */ + .presence-bar { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 16px; + background: ${cssManager.bdTheme('#f9fafb', '#111111')}; + border-bottom: 1px solid ${cssManager.bdTheme('#e5e5e5', '#27272a')}; + } + + .presence-avatars { + display: flex; + align-items: center; + } + + .presence-avatar { + width: 28px; + height: 28px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 11px; + font-weight: 600; + color: white; + margin-left: -6px; + border: 2px solid ${cssManager.bdTheme('#f9fafb', '#111111')}; + cursor: pointer; + position: relative; + } + + .presence-avatar:first-child { + margin-left: 0; + } + + .presence-avatar .status-dot { + position: absolute; + bottom: -1px; + right: -1px; + width: 8px; + height: 8px; + border-radius: 50%; + background: #10b981; + border: 2px solid ${cssManager.bdTheme('#f9fafb', '#111111')}; + } + + .presence-avatar .status-dot.away { + background: #f59e0b; + } + + .presence-count { + display: flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; + border-radius: 50%; + background: ${cssManager.bdTheme('#e5e7eb', '#3f3f46')}; + color: ${cssManager.bdTheme('#6b7280', '#9ca3af')}; + font-size: 11px; + font-weight: 600; + margin-left: -6px; + border: 2px solid ${cssManager.bdTheme('#f9fafb', '#111111')}; + } + + .presence-label { + font-size: 12px; + color: ${cssManager.bdTheme('#6b7280', '#9ca3af')}; + } + + /* Scrollable content */ + .sidebar-content { + flex: 1; + overflow-y: auto; + padding: 12px; + } + + /* Collapsible sections */ + .collapsible-section { + margin-bottom: 12px; + border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#27272a')}; + border-radius: 8px; + overflow: hidden; + background: ${cssManager.bdTheme('#ffffff', '#0a0a0a')}; + } + + .section-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 12px; + background: ${cssManager.bdTheme('#f9fafb', '#111111')}; + cursor: pointer; + user-select: none; + transition: background 0.15s ease; + } + + .section-header:hover { + background: ${cssManager.bdTheme('#f3f4f6', '#18181b')}; + } + + .section-title { + display: flex; + align-items: center; + gap: 8px; + font-size: 13px; + font-weight: 600; + color: ${cssManager.bdTheme('#374151', '#d1d5db')}; + } + + .section-title dees-icon { + font-size: 14px; + color: ${cssManager.bdTheme('#6b7280', '#9ca3af')}; + } + + .section-badge { + padding: 2px 6px; + border-radius: 9999px; + font-size: 10px; + font-weight: 600; + background: ${cssManager.bdTheme('#dbeafe', '#1e3a5f')}; + color: ${cssManager.bdTheme('#1e40af', '#93c5fd')}; + } + + .section-chevron { + font-size: 14px; + color: ${cssManager.bdTheme('#9ca3af', '#6b7280')}; + transition: transform 0.2s ease; + } + + .section-chevron.expanded { + transform: rotate(180deg); + } + + .section-body { + padding: 0; + max-height: 0; + overflow: hidden; + transition: max-height 0.2s ease, padding 0.2s ease; + } + + .section-body.expanded { + padding: 12px; + max-height: 1000px; + } + + /* Compact comment cards */ + .comment-card { + display: flex; + gap: 10px; + padding: 10px; + background: ${cssManager.bdTheme('#f9fafb', '#111111')}; + border-radius: 6px; + margin-bottom: 8px; + cursor: pointer; + transition: background 0.15s ease; + } + + .comment-card:last-child { + margin-bottom: 0; + } + + .comment-card:hover { + background: ${cssManager.bdTheme('#f3f4f6', '#18181b')}; + } + + .comment-card.resolved { + opacity: 0.6; + } + + .comment-avatar { + width: 24px; + height: 24px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 10px; + font-weight: 600; + color: white; + flex-shrink: 0; + } + + .comment-body { + flex: 1; + min-width: 0; + } + + .comment-meta { + display: flex; + align-items: center; + gap: 6px; + margin-bottom: 4px; + } + + .comment-author { + font-size: 12px; + font-weight: 600; + color: ${cssManager.bdTheme('#374151', '#d1d5db')}; + } + + .comment-time { + font-size: 10px; + color: ${cssManager.bdTheme('#9ca3af', '#6b7280')}; + } + + .comment-preview { + font-size: 12px; + line-height: 1.4; + color: ${cssManager.bdTheme('#6b7280', '#9ca3af')}; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .comment-replies { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 10px; + color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')}; + margin-top: 4px; + } + + .comment-replies dees-icon { + font-size: 12px; + } + + /* Suggestion cards */ + .suggestion-card { + padding: 10px; + background: ${cssManager.bdTheme('#f9fafb', '#111111')}; + border-radius: 6px; + margin-bottom: 8px; + cursor: pointer; + transition: background 0.15s ease; + } + + .suggestion-card:last-child { + margin-bottom: 0; + } + + .suggestion-card:hover { + background: ${cssManager.bdTheme('#f3f4f6', '#18181b')}; + } + + .suggestion-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; + } + + .suggestion-user { + display: flex; + align-items: center; + gap: 6px; + } + + .suggestion-status { + display: flex; + align-items: center; + gap: 4px; + padding: 2px 6px; + border-radius: 9999px; + font-size: 10px; + font-weight: 500; + } + + .suggestion-status dees-icon { + font-size: 10px; + } + + .suggestion-status.pending { + background: ${cssManager.bdTheme('#fef3c7', '#422006')}; + color: ${cssManager.bdTheme('#92400e', '#fcd34d')}; + } + + .suggestion-status.accepted { + background: ${cssManager.bdTheme('#d1fae5', '#064e3b')}; + color: ${cssManager.bdTheme('#065f46', '#6ee7b7')}; + } + + .suggestion-status.rejected { + background: ${cssManager.bdTheme('#fee2e2', '#450a0a')}; + color: ${cssManager.bdTheme('#991b1b', '#fca5a5')}; + } + + .suggestion-diff { + font-family: 'Roboto Mono', monospace; + font-size: 11px; + line-height: 1.4; + } + + .diff-removed { + background: ${cssManager.bdTheme('#fee2e2', '#450a0a')}; + color: ${cssManager.bdTheme('#991b1b', '#fca5a5')}; + text-decoration: line-through; + padding: 1px 3px; + border-radius: 2px; + } + + .diff-added { + background: ${cssManager.bdTheme('#d1fae5', '#064e3b')}; + color: ${cssManager.bdTheme('#065f46', '#6ee7b7')}; + padding: 1px 3px; + border-radius: 2px; + } + + /* Quick add comment */ + .quick-add { + padding: 12px; + border-top: 1px solid ${cssManager.bdTheme('#e5e5e5', '#27272a')}; + background: ${cssManager.bdTheme('#f9fafb', '#111111')}; + } + + .quick-add-input { + width: 100%; + padding: 10px 12px; + font-size: 13px; + color: ${cssManager.bdTheme('#111111', '#fafafa')}; + background: ${cssManager.bdTheme('#ffffff', '#0a0a0a')}; + border: 1px solid ${cssManager.bdTheme('#d1d5db', '#3f3f46')}; + border-radius: 6px; + outline: none; + resize: none; + min-height: 60px; + font-family: inherit; + box-sizing: border-box; + } + + .quick-add-input:focus { + border-color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')}; + box-shadow: 0 0 0 3px ${cssManager.bdTheme('rgba(59, 130, 246, 0.1)', 'rgba(96, 165, 250, 0.1)')}; + } + + .quick-add-input::placeholder { + color: ${cssManager.bdTheme('#9ca3af', '#6b7280')}; + } + + .quick-add-actions { + display: flex; + justify-content: flex-end; + margin-top: 8px; + } + + .btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 12px; + font-size: 12px; + font-weight: 500; + border-radius: 6px; + border: none; + cursor: pointer; + transition: all 0.15s ease; + } + + .btn-primary { + background: ${cssManager.bdTheme('#111111', '#fafafa')}; + color: ${cssManager.bdTheme('#ffffff', '#09090b')}; + } + + .btn-primary:hover { + background: ${cssManager.bdTheme('#333333', '#e5e5e5')}; + } + + .btn-primary:disabled { + opacity: 0.5; + cursor: not-allowed; + } + + /* Empty state */ + .empty-state { + display: flex; + flex-direction: column; + align-items: center; + padding: 24px 16px; + text-align: center; + color: ${cssManager.bdTheme('#9ca3af', '#6b7280')}; + } + + .empty-state dees-icon { + font-size: 32px; + margin-bottom: 8px; + opacity: 0.5; + } + + .empty-state p { + margin: 0; + font-size: 12px; + } + `, + ]; + + // ============================================================================ + // PROPERTIES + // ============================================================================ + + @property({ type: Object }) + public accessor contract: plugins.sdInterfaces.IPortableContract | null = null; + + @property({ type: Boolean }) + public accessor readonly: boolean = false; + + // ============================================================================ + // STATE + // ============================================================================ + + @state() + private accessor commentsExpanded: boolean = true; + + @state() + private accessor suggestionsExpanded: boolean = true; + + @state() + private accessor newCommentText: string = ''; + + // Demo presence data + @state() + private accessor presenceList: IPresence[] = [ + { userId: '1', userName: 'Alice Smith', userColor: '#3b82f6', currentSection: 'content', lastActive: Date.now() }, + { userId: '2', userName: 'Bob Johnson', userColor: '#10b981', currentSection: 'parties', lastActive: Date.now() - 60000 }, + { userId: '3', userName: 'Carol Davis', userColor: '#f59e0b', currentSection: 'terms', lastActive: Date.now() - 300000 }, + ]; + + // Demo comments data + @state() + private accessor comments: IComment[] = [ + { + id: '1', + userId: '1', + userName: 'Alice Smith', + userColor: '#3b82f6', + content: 'Can we clarify the payment terms in paragraph 3? The current wording seems ambiguous.', + createdAt: Date.now() - 3600000, + anchorPath: 'paragraphs.2', + anchorText: 'Compensation', + resolved: false, + replies: [ + { + id: '1-1', + userId: '2', + userName: 'Bob Johnson', + userColor: '#10b981', + content: 'Good point. I\'ll update the wording to be more specific.', + createdAt: Date.now() - 1800000, + resolved: false, + replies: [], + }, + ], + }, + { + id: '2', + userId: '3', + userName: 'Carol Davis', + userColor: '#f59e0b', + content: 'The termination clause needs to comply with the latest regulations.', + createdAt: Date.now() - 86400000, + resolved: true, + replies: [], + }, + { + id: '3', + userId: '2', + userName: 'Bob Johnson', + userColor: '#10b981', + content: 'Should we add an automatic renewal clause?', + createdAt: Date.now() - 7200000, + resolved: false, + replies: [], + }, + ]; + + // Demo suggestions data + @state() + private accessor suggestions: ISuggestion[] = [ + { + id: '1', + userId: '1', + userName: 'Alice Smith', + userColor: '#3b82f6', + originalText: 'monthly salary', + suggestedText: 'monthly gross salary', + path: 'paragraphs.2.content', + status: 'pending', + createdAt: Date.now() - 7200000, + }, + { + id: '2', + userId: '3', + userName: 'Carol Davis', + userColor: '#f59e0b', + originalText: '30 days', + suggestedText: '60 days', + path: 'paragraphs.5.content', + status: 'pending', + createdAt: Date.now() - 3600000, + }, + ]; + + // ============================================================================ + // EVENT HANDLERS + // ============================================================================ + + private handleCommentClick(comment: IComment) { + this.dispatchEvent( + new CustomEvent('comment-click', { + detail: { comment }, + bubbles: true, + composed: true, + }) + ); + } + + private handleSuggestionClick(suggestion: ISuggestion) { + this.dispatchEvent( + new CustomEvent('suggestion-click', { + detail: { suggestion }, + bubbles: true, + composed: true, + }) + ); + } + + private handleAddComment() { + if (!this.newCommentText.trim()) return; + + const newComment: IComment = { + id: `comment-${Date.now()}`, + userId: 'current-user', + userName: 'You', + userColor: '#6366f1', + content: this.newCommentText, + createdAt: Date.now(), + resolved: false, + replies: [], + }; + + this.comments = [newComment, ...this.comments]; + this.newCommentText = ''; + + this.dispatchEvent( + new CustomEvent('add-comment', { + detail: { comment: newComment }, + bubbles: true, + composed: true, + }) + ); + } + + // ============================================================================ + // HELPERS + // ============================================================================ + + private formatTimeAgo(timestamp: number): string { + const seconds = Math.floor((Date.now() - timestamp) / 1000); + if (seconds < 60) return 'now'; + const minutes = Math.floor(seconds / 60); + if (minutes < 60) return `${minutes}m`; + const hours = Math.floor(minutes / 60); + if (hours < 24) return `${hours}h`; + const days = Math.floor(hours / 24); + return `${days}d`; + } + + private getActivePresence(): IPresence[] { + const fiveMinutesAgo = Date.now() - 300000; + return this.presenceList.filter((p) => p.lastActive > fiveMinutesAgo); + } + + private getOpenComments(): IComment[] { + return this.comments.filter((c) => !c.resolved); + } + + private getPendingSuggestions(): ISuggestion[] { + return this.suggestions.filter((s) => s.status === 'pending'); + } + + // ============================================================================ + // RENDER + // ============================================================================ + + public render(): TemplateResult { + const activePresence = this.getActivePresence(); + const openComments = this.getOpenComments(); + const pendingSuggestions = this.getPendingSuggestions(); + + return html` + + `; + } + + private renderCommentCard(comment: IComment): TemplateResult { + return html` +
this.handleCommentClick(comment)} + > +
+ ${comment.userName.charAt(0)} +
+
+
+ ${comment.userName} + ${this.formatTimeAgo(comment.createdAt)} +
+
${comment.content}
+ ${comment.replies.length > 0 + ? html` +
+ + ${comment.replies.length} ${comment.replies.length === 1 ? 'reply' : 'replies'} +
+ ` + : ''} +
+
+ `; + } + + private renderSuggestionCard(suggestion: ISuggestion): TemplateResult { + return html` +
this.handleSuggestionClick(suggestion)}> +
+
+
+ ${suggestion.userName.charAt(0)} +
+ ${suggestion.userName} +
+
+ + ${suggestion.status} +
+
+
+ ${suggestion.originalText} + + ${suggestion.suggestedText} +
+
+ `; + } +} diff --git a/ts_web/elements/sdig-contract-attachments/sdig-contract-attachments.ts b/ts_web/elements/sdig-contract-attachments/sdig-contract-attachments.ts index 5f902ed..976d60c 100644 --- a/ts_web/elements/sdig-contract-attachments/sdig-contract-attachments.ts +++ b/ts_web/elements/sdig-contract-attachments/sdig-contract-attachments.ts @@ -37,11 +37,11 @@ interface IAttachment { // File type configuration const FILE_TYPES = { - document: { icon: 'lucide:file-text', color: '#3b82f6', label: 'Document' }, - image: { icon: 'lucide:image', color: '#10b981', label: 'Image' }, - spreadsheet: { icon: 'lucide:sheet', color: '#22c55e', label: 'Spreadsheet' }, - pdf: { icon: 'lucide:file-type', color: '#ef4444', label: 'PDF' }, - other: { icon: 'lucide:file', color: '#6b7280', label: 'File' }, + document: { icon: 'lucide:FileText', color: '#3b82f6', label: 'Document' }, + image: { icon: 'lucide:Image', color: '#10b981', label: 'Image' }, + spreadsheet: { icon: 'lucide:Sheet', color: '#22c55e', label: 'Spreadsheet' }, + pdf: { icon: 'lucide:FileType', color: '#ef4444', label: 'PDF' }, + other: { icon: 'lucide:File', color: '#6b7280', label: 'File' }, }; @customElement('sdig-contract-attachments') @@ -631,7 +631,7 @@ export class SdigContractAttachments extends DeesElement {
- + Attachments
${this.attachments.length} files @@ -662,7 +662,7 @@ export class SdigContractAttachments extends DeesElement { @click=${this.handleFileSelect} >
- +
Drop files here or click to upload
Add supporting documents, images, or spreadsheets
@@ -680,7 +680,7 @@ export class SdigContractAttachments extends DeesElement { ` : html`
- +

No Attachments

Upload files to attach them to this contract

@@ -692,13 +692,13 @@ export class SdigContractAttachments extends DeesElement {
- + Prior Contracts
${!this.readonly ? html` ` @@ -715,7 +715,7 @@ export class SdigContractAttachments extends DeesElement { ` : html`
- +

No Prior Contracts

Link related or predecessor contracts here

@@ -732,7 +732,7 @@ export class SdigContractAttachments extends DeesElement { return html`
- +
${attachment.name}
@@ -742,21 +742,21 @@ export class SdigContractAttachments extends DeesElement { ${this.formatFileSize(attachment.size)} - + ${this.formatDate(attachment.uploadedAt)} - + ${this.getPartyName(attachment.uploadedBy)}
${!this.readonly ? html` @@ -765,7 +765,7 @@ export class SdigContractAttachments extends DeesElement { title="Delete" @click=${() => this.handleDeleteAttachment(attachment.id)} > - + ` : ''} @@ -778,7 +778,7 @@ export class SdigContractAttachments extends DeesElement { return html`
- +
${priorContract.title}
@@ -786,7 +786,7 @@ export class SdigContractAttachments extends DeesElement {
${!this.readonly @@ -795,7 +795,7 @@ export class SdigContractAttachments extends DeesElement { class="btn btn-ghost btn-danger" @click=${() => this.handleRemovePriorContract(index)} > - + ` : ''} diff --git a/ts_web/elements/sdig-contract-audit/sdig-contract-audit.ts b/ts_web/elements/sdig-contract-audit/sdig-contract-audit.ts index 9be9afa..6f9e4d1 100644 --- a/ts_web/elements/sdig-contract-audit/sdig-contract-audit.ts +++ b/ts_web/elements/sdig-contract-audit/sdig-contract-audit.ts @@ -42,23 +42,23 @@ interface IAuditEvent { // Status workflow configuration const STATUS_WORKFLOW = [ - { id: 'draft', label: 'Draft', icon: 'lucide:file-edit', color: '#f59e0b' }, - { id: 'review', label: 'Review', icon: 'lucide:eye', color: '#3b82f6' }, - { id: 'pending', label: 'Pending Signatures', icon: 'lucide:pen-tool', color: '#8b5cf6' }, - { id: 'signed', label: 'Signed', icon: 'lucide:check-circle', color: '#10b981' }, - { id: 'executed', label: 'Executed', icon: 'lucide:shield-check', color: '#059669' }, + { id: 'draft', label: 'Draft', icon: 'lucide:FileEdit', color: '#f59e0b' }, + { id: 'review', label: 'Review', icon: 'lucide:Eye', color: '#3b82f6' }, + { id: 'pending', label: 'Pending Signatures', icon: 'lucide:PenTool', color: '#8b5cf6' }, + { id: 'signed', label: 'Signed', icon: 'lucide:CheckCircle', color: '#10b981' }, + { id: 'executed', label: 'Executed', icon: 'lucide:ShieldCheck', color: '#059669' }, ]; // Event type configuration const EVENT_TYPES = { - created: { icon: 'lucide:plus-circle', color: '#10b981', label: 'Created' }, - updated: { icon: 'lucide:pencil', color: '#3b82f6', label: 'Updated' }, - status_change: { icon: 'lucide:arrow-right-circle', color: '#8b5cf6', label: 'Status Changed' }, - signature: { icon: 'lucide:pen-tool', color: '#10b981', label: 'Signature' }, - comment: { icon: 'lucide:message-circle', color: '#f59e0b', label: 'Comment' }, - attachment: { icon: 'lucide:paperclip', color: '#6366f1', label: 'Attachment' }, - viewed: { icon: 'lucide:eye', color: '#6b7280', label: 'Viewed' }, - shared: { icon: 'lucide:share-2', color: '#ec4899', label: 'Shared' }, + created: { icon: 'lucide:PlusCircle', color: '#10b981', label: 'Created' }, + updated: { icon: 'lucide:Pencil', color: '#3b82f6', label: 'Updated' }, + status_change: { icon: 'lucide:ArrowRightCircle', color: '#8b5cf6', label: 'Status Changed' }, + signature: { icon: 'lucide:PenTool', color: '#10b981', label: 'Signature' }, + comment: { icon: 'lucide:MessageCircle', color: '#f59e0b', label: 'Comment' }, + attachment: { icon: 'lucide:Paperclip', color: '#6366f1', label: 'Attachment' }, + viewed: { icon: 'lucide:Eye', color: '#6b7280', label: 'Viewed' }, + shared: { icon: 'lucide:Share2', color: '#ec4899', label: 'Shared' }, }; @customElement('sdig-contract-audit') @@ -623,7 +623,7 @@ export class SdigContractAudit extends DeesElement { ${STATUS_WORKFLOW.map((status, index) => html`
- +
${status.label}
@@ -658,11 +658,11 @@ export class SdigContractAudit extends DeesElement {
- + Activity Log
@@ -697,7 +697,7 @@ export class SdigContractAudit extends DeesElement { ` : html`
- +

No Events Found

No activity matches your current filters

@@ -714,7 +714,7 @@ export class SdigContractAudit extends DeesElement { return html`
- +
diff --git a/ts_web/elements/sdig-contract-collaboration/sdig-contract-collaboration.ts b/ts_web/elements/sdig-contract-collaboration/sdig-contract-collaboration.ts index 5cd7544..e8d2a8c 100644 --- a/ts_web/elements/sdig-contract-collaboration/sdig-contract-collaboration.ts +++ b/ts_web/elements/sdig-contract-collaboration/sdig-contract-collaboration.ts @@ -765,7 +765,7 @@ export class SdigContractCollaboration extends DeesElement {
@@ -774,7 +774,7 @@ export class SdigContractCollaboration extends DeesElement {
- + Comments ${openComments > 0 ? html`${openComments} open` : ''}
@@ -813,7 +813,7 @@ export class SdigContractCollaboration extends DeesElement { @input=${(e: Event) => (this.newCommentText = (e.target as HTMLTextAreaElement).value)} >
@@ -829,7 +829,7 @@ export class SdigContractCollaboration extends DeesElement { ` : html`
- +

No Comments

Start a discussion by adding a comment

@@ -841,7 +841,7 @@ export class SdigContractCollaboration extends DeesElement {
- + Suggestions ${pendingSuggestions > 0 ? html`${pendingSuggestions} pending` : ''}
@@ -855,7 +855,7 @@ export class SdigContractCollaboration extends DeesElement { ` : html`
- +

No Suggestions

Suggested changes will appear here

@@ -883,7 +883,7 @@ export class SdigContractCollaboration extends DeesElement { class="btn btn-ghost btn-sm" @click=${() => this.handleResolveComment(comment.id)} > - + ${comment.resolved ? 'Reopen' : 'Resolve'} ` @@ -893,7 +893,7 @@ export class SdigContractCollaboration extends DeesElement { ${comment.anchorText ? html`
- + ${comment.anchorText}
` @@ -941,7 +941,7 @@ export class SdigContractCollaboration extends DeesElement {
- + ${suggestion.status.charAt(0).toUpperCase() + suggestion.status.slice(1)}
@@ -956,11 +956,11 @@ export class SdigContractCollaboration extends DeesElement { ? html`
diff --git a/ts_web/elements/sdig-contract-content/sdig-contract-content.ts b/ts_web/elements/sdig-contract-content/sdig-contract-content.ts index 9f31308..33e1902 100644 --- a/ts_web/elements/sdig-contract-content/sdig-contract-content.ts +++ b/ts_web/elements/sdig-contract-content/sdig-contract-content.ts @@ -24,12 +24,12 @@ declare global { // Paragraph type configuration const PARAGRAPH_TYPES = [ - { value: 'section', label: 'Section', icon: 'lucide:heading' }, - { value: 'clause', label: 'Clause', icon: 'lucide:file-text' }, - { value: 'definition', label: 'Definition', icon: 'lucide:book-open' }, - { value: 'obligation', label: 'Obligation', icon: 'lucide:check-square' }, - { value: 'condition', label: 'Condition', icon: 'lucide:git-branch' }, - { value: 'schedule', label: 'Schedule', icon: 'lucide:calendar' }, + { value: 'section', label: 'Section', icon: 'lucide:Heading' }, + { value: 'clause', label: 'Clause', icon: 'lucide:FileText' }, + { value: 'definition', label: 'Definition', icon: 'lucide:BookOpen' }, + { value: 'obligation', label: 'Obligation', icon: 'lucide:CheckSquare' }, + { value: 'condition', label: 'Condition', icon: 'lucide:GitBranch' }, + { value: 'schedule', label: 'Schedule', icon: 'lucide:Calendar' }, ]; @customElement('sdig-contract-content') @@ -718,7 +718,7 @@ export class SdigContractContent extends DeesElement {
${!this.readonly ? html` ` @@ -759,7 +759,7 @@ export class SdigContractContent extends DeesElement {
- + Contract Content
${this.contract.paragraphs.length} paragraphs @@ -777,7 +777,7 @@ export class SdigContractContent extends DeesElement { ? html`
@@ -786,13 +786,13 @@ export class SdigContractContent extends DeesElement { ` : html`
- +

No Paragraphs Yet

Start building your contract by adding paragraphs. Each paragraph can contain clauses, definitions, or obligations.

${!this.readonly ? html` ` @@ -819,7 +819,7 @@ export class SdigContractContent extends DeesElement { ${!this.readonly ? html`
- +
` : ''} @@ -880,28 +880,28 @@ export class SdigContractContent extends DeesElement { @click=${(e: Event) => { e.stopPropagation(); this.handleEditParagraph(paragraph); }} title="Edit" > - +
` diff --git a/ts_web/elements/sdig-contract-header/sdig-contract-header.ts b/ts_web/elements/sdig-contract-header/sdig-contract-header.ts index 8a2e5e7..cf2ac7d 100644 --- a/ts_web/elements/sdig-contract-header/sdig-contract-header.ts +++ b/ts_web/elements/sdig-contract-header/sdig-contract-header.ts @@ -455,7 +455,7 @@ export class SdigContractHeader extends DeesElement { ${this.formatStatus(status)} ${!this.readonly - ? html`` + ? html`` : ''} @@ -491,13 +491,13 @@ export class SdigContractHeader extends DeesElement {
diff --git a/ts_web/elements/sdig-contract-metadata/sdig-contract-metadata.ts b/ts_web/elements/sdig-contract-metadata/sdig-contract-metadata.ts index b8cea34..9a0f702 100644 --- a/ts_web/elements/sdig-contract-metadata/sdig-contract-metadata.ts +++ b/ts_web/elements/sdig-contract-metadata/sdig-contract-metadata.ts @@ -448,7 +448,7 @@ export class SdigContractMetadata extends DeesElement {
- + Basic Information
@@ -555,7 +555,7 @@ export class SdigContractMetadata extends DeesElement {
- + Language Settings
@@ -606,7 +606,7 @@ export class SdigContractMetadata extends DeesElement {
- + Governing Law & Jurisdiction
@@ -758,7 +758,7 @@ export class SdigContractMetadata extends DeesElement {
- + References & Integration
diff --git a/ts_web/elements/sdig-contract-parties/sdig-contract-parties.ts b/ts_web/elements/sdig-contract-parties/sdig-contract-parties.ts index a6241b1..f008858 100644 --- a/ts_web/elements/sdig-contract-parties/sdig-contract-parties.ts +++ b/ts_web/elements/sdig-contract-parties/sdig-contract-parties.ts @@ -24,13 +24,13 @@ declare global { // Party role display configuration const PARTY_ROLES: Array<{ value: plugins.sdInterfaces.TPartyRole; label: string; icon: string }> = [ - { value: 'signer', label: 'Signer', icon: 'lucide:pen-tool' }, - { value: 'witness', label: 'Witness', icon: 'lucide:eye' }, - { value: 'notary', label: 'Notary', icon: 'lucide:stamp' }, - { value: 'cc', label: 'CC (Copy)', icon: 'lucide:mail' }, - { value: 'approver', label: 'Approver', icon: 'lucide:check-circle' }, - { value: 'guarantor', label: 'Guarantor', icon: 'lucide:shield' }, - { value: 'beneficiary', label: 'Beneficiary', icon: 'lucide:user-check' }, + { value: 'signer', label: 'Signer', icon: 'lucide:PenTool' }, + { value: 'witness', label: 'Witness', icon: 'lucide:Eye' }, + { value: 'notary', label: 'Notary', icon: 'lucide:Stamp' }, + { value: 'cc', label: 'CC (Copy)', icon: 'lucide:Mail' }, + { value: 'approver', label: 'Approver', icon: 'lucide:CheckCircle' }, + { value: 'guarantor', label: 'Guarantor', icon: 'lucide:Shield' }, + { value: 'beneficiary', label: 'Beneficiary', icon: 'lucide:UserCheck' }, ]; const SIGNING_DEPENDENCIES: Array<{ value: plugins.sdInterfaces.TSigningDependency; label: string }> = [ @@ -550,13 +550,13 @@ export class SdigContractParties extends DeesElement {
- + Available Roles
${!this.readonly ? html` ` @@ -571,7 +571,7 @@ export class SdigContractParties extends DeesElement { ` : html`
- +

No Roles Defined

Add roles to define the types of parties in this contract

@@ -583,13 +583,13 @@ export class SdigContractParties extends DeesElement {
- + Involved Parties (${parties.length})
${!this.readonly ? html` ` @@ -604,7 +604,7 @@ export class SdigContractParties extends DeesElement { ` : html`
- +

No Parties Added

Add parties who will be involved in this contract

@@ -621,7 +621,7 @@ export class SdigContractParties extends DeesElement {
${role.name} @@ -633,7 +633,7 @@ export class SdigContractParties extends DeesElement { ${role.signatureRequired ? html` - + Signature required ` @@ -641,7 +641,7 @@ export class SdigContractParties extends DeesElement { ${role.defaultSigningOrder > 0 ? html` - + Order: ${role.defaultSigningOrder} ` @@ -649,7 +649,7 @@ export class SdigContractParties extends DeesElement { ${role.minParties ? html` - + Min: ${role.minParties}${role.maxParties ? `, Max: ${role.maxParties}` : ''} ` @@ -693,7 +693,7 @@ export class SdigContractParties extends DeesElement { ${deliveryEmail ? html`
- + ${deliveryEmail}
` @@ -701,7 +701,7 @@ export class SdigContractParties extends DeesElement { ${deliveryPhone ? html`
- + ${deliveryPhone}
` @@ -709,7 +709,7 @@ export class SdigContractParties extends DeesElement { ${actingAsProxy ? html`
- + Acting as proxy
` diff --git a/ts_web/elements/sdig-contract-signatures/sdig-contract-signatures.ts b/ts_web/elements/sdig-contract-signatures/sdig-contract-signatures.ts index cb2548c..1458ae1 100644 --- a/ts_web/elements/sdig-contract-signatures/sdig-contract-signatures.ts +++ b/ts_web/elements/sdig-contract-signatures/sdig-contract-signatures.ts @@ -43,17 +43,17 @@ interface ISignatureField { // Signature status configuration const SIGNATURE_STATUSES = [ - { value: 'pending', label: 'Pending', color: '#f59e0b', icon: 'lucide:clock' }, - { value: 'ready', label: 'Ready to Sign', color: '#3b82f6', icon: 'lucide:pen-tool' }, - { value: 'signed', label: 'Signed', color: '#10b981', icon: 'lucide:check-circle' }, - { value: 'declined', label: 'Declined', color: '#ef4444', icon: 'lucide:x-circle' }, + { value: 'pending', label: 'Pending', color: '#f59e0b', icon: 'lucide:Clock' }, + { value: 'ready', label: 'Ready to Sign', color: '#3b82f6', icon: 'lucide:PenTool' }, + { value: 'signed', label: 'Signed', color: '#10b981', icon: 'lucide:CheckCircle' }, + { value: 'declined', label: 'Declined', color: '#ef4444', icon: 'lucide:XCircle' }, ]; const FIELD_TYPES = [ - { value: 'signature', label: 'Full Signature', icon: 'lucide:pen-tool' }, - { value: 'initials', label: 'Initials', icon: 'lucide:type' }, - { value: 'date', label: 'Date', icon: 'lucide:calendar' }, - { value: 'text', label: 'Text Field', icon: 'lucide:text-cursor' }, + { value: 'signature', label: 'Full Signature', icon: 'lucide:PenTool' }, + { value: 'initials', label: 'Initials', icon: 'lucide:Type' }, + { value: 'date', label: 'Date', icon: 'lucide:Calendar' }, + { value: 'text', label: 'Text Field', icon: 'lucide:TextCursor' }, ]; @customElement('sdig-contract-signatures') @@ -649,28 +649,28 @@ export class SdigContractSignatures extends DeesElement {
- +
${stats.pending}
Pending
- +
${stats.ready}
Ready to Sign
- +
${stats.signed}
Signed
- +
${stats.declined}
Declined
@@ -681,13 +681,13 @@ export class SdigContractSignatures extends DeesElement {
- + Signature Fields
${!this.readonly ? html` ` @@ -702,13 +702,13 @@ export class SdigContractSignatures extends DeesElement { ` : html`
- +

No Signature Fields

Add signature fields to define where parties should sign the contract

${!this.readonly ? html` ` @@ -724,7 +724,7 @@ export class SdigContractSignatures extends DeesElement {
- + Signers Progress
@@ -753,24 +753,24 @@ export class SdigContractSignatures extends DeesElement {
${index + 1}
- +
${field.name}
- + ${this.getPartyRoleName(field.roleId)} - + ${typeConfig.label} ${field.required ? html` - + Required ` @@ -778,7 +778,7 @@ export class SdigContractSignatures extends DeesElement { ${field.signedAt ? html` - + ${this.formatDate(field.signedAt)} ` @@ -787,7 +787,7 @@ export class SdigContractSignatures extends DeesElement {
- + ${statusConfig.label}
@@ -795,7 +795,7 @@ export class SdigContractSignatures extends DeesElement { ? html`
` diff --git a/ts_web/elements/sdig-contract-terms/sdig-contract-terms.ts b/ts_web/elements/sdig-contract-terms/sdig-contract-terms.ts index 253e0c6..30d50dd 100644 --- a/ts_web/elements/sdig-contract-terms/sdig-contract-terms.ts +++ b/ts_web/elements/sdig-contract-terms/sdig-contract-terms.ts @@ -33,9 +33,9 @@ interface ITermTabConfig { } const TERM_TABS: ITermTabConfig[] = [ - { id: 'financial', label: 'Financial Terms', icon: 'lucide:banknote', description: 'Payment schedules, rates, and penalties' }, - { id: 'time', label: 'Time Terms', icon: 'lucide:calendar', description: 'Milestones, deadlines, and renewal' }, - { id: 'obligations', label: 'Obligations', icon: 'lucide:check-square', description: 'Deliverables, SLAs, and warranties' }, + { id: 'financial', label: 'Financial Terms', icon: 'lucide:Banknote', description: 'Payment schedules, rates, and penalties' }, + { id: 'time', label: 'Time Terms', icon: 'lucide:Calendar', description: 'Milestones, deadlines, and renewal' }, + { id: 'obligations', label: 'Obligations', icon: 'lucide:CheckSquare', description: 'Deliverables, SLAs, and warranties' }, ]; // Extended contract terms interfaces (for future interface updates) @@ -588,7 +588,7 @@ export class SdigContractTerms extends DeesElement { class="tab-btn ${this.activeTab === tab.id ? 'active' : ''}" @click=${() => this.handleTabChange(tab.id)} > - + ${tab.label} ` @@ -640,7 +640,7 @@ export class SdigContractTerms extends DeesElement { ${!this.readonly ? html` ` @@ -671,7 +671,7 @@ export class SdigContractTerms extends DeesElement { ? html` ` @@ -684,7 +684,7 @@ export class SdigContractTerms extends DeesElement { ` : html`
- +

No Payment Schedule

Add payment terms to track financial obligations

@@ -724,7 +724,7 @@ export class SdigContractTerms extends DeesElement { ${!this.readonly ? html` ` @@ -755,7 +755,7 @@ export class SdigContractTerms extends DeesElement { ? html` ` @@ -768,7 +768,7 @@ export class SdigContractTerms extends DeesElement { ` : html`
- +

No Milestones

Add milestones to track project progress

@@ -799,7 +799,7 @@ export class SdigContractTerms extends DeesElement {
- +
Contractual Obligations
@@ -818,7 +818,7 @@ export class SdigContractTerms extends DeesElement { ${!this.readonly ? html` ` @@ -849,7 +849,7 @@ export class SdigContractTerms extends DeesElement { ? html` ` @@ -862,7 +862,7 @@ export class SdigContractTerms extends DeesElement { ` : html`
- +

No Obligations

Add obligations to track party responsibilities

diff --git a/ts_web/elements/sdig-contracteditor/sdig-contracteditor.ts b/ts_web/elements/sdig-contracteditor/sdig-contracteditor.ts index 3901158..46b9073 100644 --- a/ts_web/elements/sdig-contracteditor/sdig-contracteditor.ts +++ b/ts_web/elements/sdig-contracteditor/sdig-contracteditor.ts @@ -34,6 +34,7 @@ import '../sdig-contract-signatures/sdig-contract-signatures.js'; import '../sdig-contract-attachments/sdig-contract-attachments.js'; import '../sdig-contract-collaboration/sdig-contract-collaboration.js'; import '../sdig-contract-audit/sdig-contract-audit.js'; +import '../sdig-collaboration-sidebar/sdig-collaboration-sidebar.js'; declare global { interface HTMLElementTagNameMap { @@ -338,6 +339,11 @@ export class SdigContracteditor extends DeesElement { color: ${cssManager.bdTheme('#111111', '#fafafa')}; } + .btn-ghost.active { + background: ${cssManager.bdTheme('#e5e7eb', '#3f3f46')}; + color: ${cssManager.bdTheme('#111111', '#fafafa')}; + } + .btn:disabled { opacity: 0.5; cursor: not-allowed; @@ -490,6 +496,40 @@ export class SdigContracteditor extends DeesElement { this.store?.redo(); } + private handleCommentClick(e: CustomEvent) { + // Navigate to collaboration section and highlight comment + this.store?.setActiveSection('collaboration'); + this.dispatchEvent( + new CustomEvent('comment-focus', { + detail: e.detail, + bubbles: true, + composed: true, + }) + ); + } + + private handleSuggestionClick(e: CustomEvent) { + // Navigate to collaboration section and highlight suggestion + this.store?.setActiveSection('collaboration'); + this.dispatchEvent( + new CustomEvent('suggestion-focus', { + detail: e.detail, + bubbles: true, + composed: true, + }) + ); + } + + private handleSidebarAddComment(e: CustomEvent) { + this.dispatchEvent( + new CustomEvent('comment-added', { + detail: e.detail, + bubbles: true, + composed: true, + }) + ); + } + // ============================================================================ // PUBLIC API // ============================================================================ @@ -691,7 +731,7 @@ export class SdigContracteditor extends DeesElement { private renderPlaceholder(sectionConfig: typeof EDITOR_SECTIONS[0] | undefined, message: string): TemplateResult { return html`
- +

${sectionConfig?.label || 'Section'}

${message}

@@ -757,10 +797,17 @@ export class SdigContracteditor extends DeesElement { ` : ''} +
@@ -774,7 +821,7 @@ export class SdigContracteditor extends DeesElement { @click=${() => this.handleSectionChange(section.id)} ?disabled=${section.disabled} > - + ${section.label} ${section.badge ? html`${section.badge}` @@ -792,7 +839,12 @@ export class SdigContracteditor extends DeesElement { ${this.showSidebar ? html` ` : ''} diff --git a/ts_web/elements/sdig-contracteditor/types.ts b/ts_web/elements/sdig-contracteditor/types.ts index f56aa38..83b42d8 100644 --- a/ts_web/elements/sdig-contracteditor/types.ts +++ b/ts_web/elements/sdig-contracteditor/types.ts @@ -37,14 +37,14 @@ export interface IEditorSectionConfig { * Default section configurations */ export const EDITOR_SECTIONS: IEditorSectionConfig[] = [ - { id: 'overview', label: 'Overview', icon: 'lucide:file-text' }, - { id: 'parties', label: 'Parties & Roles', icon: 'lucide:users' }, - { id: 'content', label: 'Content', icon: 'lucide:file-edit' }, - { id: 'terms', label: 'Terms', icon: 'lucide:calculator' }, - { id: 'signatures', label: 'Signatures', icon: 'lucide:pen-tool' }, - { id: 'attachments', label: 'Attachments', icon: 'lucide:paperclip' }, - { id: 'collaboration', label: 'Collaboration', icon: 'lucide:message-circle' }, - { id: 'audit', label: 'Audit & History', icon: 'lucide:history' }, + { id: 'overview', label: 'Overview', icon: 'lucide:FileText' }, + { id: 'parties', label: 'Parties & Roles', icon: 'lucide:Users' }, + { id: 'content', label: 'Content', icon: 'lucide:FileEdit' }, + { id: 'terms', label: 'Terms', icon: 'lucide:Calculator' }, + { id: 'signatures', label: 'Signatures', icon: 'lucide:PenTool' }, + { id: 'attachments', label: 'Attachments', icon: 'lucide:Paperclip' }, + { id: 'collaboration', label: 'Collaboration', icon: 'lucide:MessageCircle' }, + { id: 'audit', label: 'Audit & History', icon: 'lucide:History' }, ]; // ============================================================================