claude-code-templates 1.21.10 → 1.21.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-templates",
3
- "version": "1.21.10",
3
+ "version": "1.21.11",
4
4
  "description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -81,6 +81,26 @@
81
81
  width: 100%;
82
82
  }
83
83
 
84
+ .chat-header-content .header-left {
85
+ display: flex;
86
+ align-items: center;
87
+ flex: 1;
88
+ }
89
+
90
+ .chat-header-content .header-center {
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ flex: 0 0 auto;
95
+ }
96
+
97
+ .chat-header-content .header-right {
98
+ display: flex;
99
+ align-items: center;
100
+ justify-content: flex-end;
101
+ flex: 1;
102
+ }
103
+
84
104
  .chat-title {
85
105
  font-size: 1.2rem;
86
106
  font-weight: 700;
@@ -770,9 +790,30 @@
770
790
  border-bottom: 1px solid var(--border-primary);
771
791
  display: flex;
772
792
  align-items: center;
793
+ justify-content: space-between;
773
794
  min-height: 64px;
774
795
  }
775
796
 
797
+ .header-left {
798
+ display: flex;
799
+ align-items: center;
800
+ flex: 1;
801
+ }
802
+
803
+ .header-center {
804
+ display: flex;
805
+ align-items: center;
806
+ justify-content: center;
807
+ flex: 0 0 auto;
808
+ }
809
+
810
+ .header-right {
811
+ display: flex;
812
+ align-items: center;
813
+ justify-content: flex-end;
814
+ flex: 1;
815
+ }
816
+
776
817
  .chat-view-back {
777
818
  margin-right: 16px;
778
819
  }
@@ -997,6 +1038,136 @@
997
1038
  /* On larger screens, show side-by-side if needed */
998
1039
  }
999
1040
  }
1041
+ /* Modal styles */
1042
+ .modal-overlay {
1043
+ position: fixed;
1044
+ top: 0;
1045
+ left: 0;
1046
+ width: 100%;
1047
+ height: 100%;
1048
+ background: rgba(0, 0, 0, 0.8);
1049
+ display: none;
1050
+ justify-content: center;
1051
+ align-items: center;
1052
+ z-index: 1000;
1053
+ }
1054
+
1055
+ .modal-overlay.show {
1056
+ display: flex;
1057
+ }
1058
+
1059
+ .modal {
1060
+ background: var(--bg-secondary);
1061
+ border-radius: 12px;
1062
+ border: 1px solid var(--border-primary);
1063
+ padding: 24px;
1064
+ max-width: 600px;
1065
+ width: 95%;
1066
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
1067
+ animation: modalSlideIn 0.3s ease-out;
1068
+ }
1069
+
1070
+ @keyframes modalSlideIn {
1071
+ from {
1072
+ opacity: 0;
1073
+ transform: translateY(-20px) scale(0.95);
1074
+ }
1075
+ to {
1076
+ opacity: 1;
1077
+ transform: translateY(0) scale(1);
1078
+ }
1079
+ }
1080
+
1081
+ .modal-header {
1082
+ display: flex;
1083
+ align-items: center;
1084
+ margin-bottom: 16px;
1085
+ }
1086
+
1087
+ .modal-icon {
1088
+ font-size: 1.5rem;
1089
+ margin-right: 12px;
1090
+ }
1091
+
1092
+ .modal-title {
1093
+ font-size: 1.2rem;
1094
+ font-weight: 700;
1095
+ color: var(--text-primary);
1096
+ }
1097
+
1098
+ .modal-description {
1099
+ color: var(--text-secondary);
1100
+ font-size: 0.9rem;
1101
+ margin-bottom: 20px;
1102
+ line-height: 1.4;
1103
+ }
1104
+
1105
+ .modal-command {
1106
+ background: var(--bg-tertiary);
1107
+ border: 1px solid var(--border-primary);
1108
+ border-radius: 8px;
1109
+ padding: 12px;
1110
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
1111
+ font-size: 0.85rem;
1112
+ color: var(--terminal-orange);
1113
+ word-break: break-all;
1114
+ margin-bottom: 20px;
1115
+ }
1116
+
1117
+ .modal-actions {
1118
+ display: flex;
1119
+ gap: 12px;
1120
+ justify-content: flex-end;
1121
+ }
1122
+
1123
+ .modal-btn {
1124
+ background: rgba(255, 107, 53, 0.1);
1125
+ border: 1px solid rgba(255, 107, 53, 0.2);
1126
+ color: var(--terminal-orange);
1127
+ font-size: 0.85rem;
1128
+ font-weight: 600;
1129
+ cursor: pointer;
1130
+ padding: 8px 16px;
1131
+ border-radius: 8px;
1132
+ transition: all 0.2s ease;
1133
+ text-transform: uppercase;
1134
+ letter-spacing: 0.5px;
1135
+ }
1136
+
1137
+ .modal-btn:hover {
1138
+ background: rgba(255, 107, 53, 0.15);
1139
+ border-color: rgba(255, 107, 53, 0.3);
1140
+ transform: translateY(-1px);
1141
+ box-shadow: 0 2px 4px rgba(255, 107, 53, 0.2);
1142
+ }
1143
+
1144
+ .modal-btn:active {
1145
+ transform: translateY(0);
1146
+ box-shadow: 0 1px 2px rgba(255, 107, 53, 0.2);
1147
+ }
1148
+
1149
+ .modal-btn.primary {
1150
+ background: var(--terminal-orange);
1151
+ color: var(--bg-primary);
1152
+ }
1153
+
1154
+ .modal-btn.primary:hover {
1155
+ background: var(--terminal-orange-hover);
1156
+ color: var(--bg-primary);
1157
+ }
1158
+
1159
+ .modal-btn.secondary {
1160
+ background: transparent;
1161
+ border-color: var(--border-primary);
1162
+ color: var(--text-secondary);
1163
+ }
1164
+
1165
+ .modal-btn.secondary:hover {
1166
+ background: var(--bg-tertiary);
1167
+ border-color: var(--border-secondary);
1168
+ color: var(--text-primary);
1169
+ }
1170
+
1000
1171
  </style>
1001
1172
  </head>
1002
1173
  <body>
@@ -1006,8 +1177,15 @@
1006
1177
  <!-- Header -->
1007
1178
  <div class="chat-header">
1008
1179
  <div class="chat-header-content">
1009
- <h1 class="chat-title">Claude Code Chats</h1>
1010
- <div class="header-actions">
1180
+ <div class="header-left">
1181
+ <h1 class="chat-title">Claude Code Chats</h1>
1182
+ </div>
1183
+ <div class="header-center">
1184
+ <button class="header-btn" id="githubBtn" title="Star on GitHub" onclick="window.open('https://github.com/davila7/claude-code-templates', '_blank')">
1185
+ ⭐️ on Github
1186
+ </button>
1187
+ </div>
1188
+ <div class="header-right">
1011
1189
  <button class="header-btn" id="refreshBtn" title="Refresh">
1012
1190
  Refresh
1013
1191
  </button>
@@ -1034,19 +1212,28 @@
1034
1212
  <!-- Chat View -->
1035
1213
  <div class="chat-view" id="chatView">
1036
1214
  <div class="chat-view-header">
1037
- <button class="header-btn back-btn chat-view-back" id="backToList">
1038
-
1039
- </button>
1040
- <div class="chat-view-info">
1041
- <h2 class="chat-view-title" id="chatViewTitle">Select a conversation</h2>
1042
- <p class="chat-view-subtitle" id="chatViewSubtitle"></p>
1215
+ <div class="header-left">
1216
+ <button class="header-btn back-btn chat-view-back" id="backToList">
1217
+
1218
+ </button>
1219
+ <div class="chat-view-info">
1220
+ <h2 class="chat-view-title" id="chatViewTitle">Select a conversation</h2>
1221
+ <p class="chat-view-subtitle" id="chatViewSubtitle"></p>
1222
+ </div>
1223
+ </div>
1224
+ <div class="header-center">
1225
+ <button class="header-btn resume-btn" id="resumeConversation" style="display: none;" onclick="resumeConversationWithClaude()">
1226
+ ▶️ Resume
1227
+ </button>
1043
1228
  </div>
1044
- <div class="tools-toggle" id="toolsToggle">
1045
- <span class="tools-toggle-label" onclick="document.getElementById('showToolsSwitch').click()">Show Tools</span>
1046
- <label class="toggle-switch">
1047
- <input type="checkbox" id="showToolsSwitch" checked>
1048
- <span class="toggle-slider"></span>
1049
- </label>
1229
+ <div class="header-right">
1230
+ <div class="tools-toggle" id="toolsToggle">
1231
+ <span class="tools-toggle-label" onclick="document.getElementById('showToolsSwitch').click()">Show Tools</span>
1232
+ <label class="toggle-switch">
1233
+ <input type="checkbox" id="showToolsSwitch" checked>
1234
+ <span class="toggle-slider"></span>
1235
+ </label>
1236
+ </div>
1050
1237
  </div>
1051
1238
  </div>
1052
1239
  <div class="chat-messages" id="chatMessages">
@@ -1068,6 +1255,26 @@
1068
1255
  </div>
1069
1256
  </div>
1070
1257
 
1258
+ <!-- Resume Conversation Modal -->
1259
+ <div class="modal-overlay" id="resumeModal">
1260
+ <div class="modal">
1261
+ <div class="modal-header">
1262
+ <span class="modal-icon">▶️</span>
1263
+ <h3 class="modal-title">Resume Conversation</h3>
1264
+ </div>
1265
+ <p class="modal-description">
1266
+ To resume this conversation in Claude Code, copy and run the following command in your terminal:
1267
+ </p>
1268
+ <div class="modal-command" id="modalCommand">
1269
+ <!-- Command will be inserted here -->
1270
+ </div>
1271
+ <div class="modal-actions">
1272
+ <button class="modal-btn secondary" onclick="closeResumeModal()">Cancel</button>
1273
+ <button class="modal-btn primary" id="copyCommandBtn" onclick="copyModalCommand()">Copy Command</button>
1274
+ </div>
1275
+ </div>
1276
+ </div>
1277
+
1071
1278
  <!-- Import WebSocket and Data Services -->
1072
1279
  <script src="services/WebSocketService.js"></script>
1073
1280
  <script src="services/DataService.js"></script>
@@ -1308,6 +1515,11 @@
1308
1515
  chatView.classList.remove('show-tools');
1309
1516
  }
1310
1517
 
1518
+ // Show resume button
1519
+ const resumeBtn = document.getElementById('resumeConversation');
1520
+ resumeBtn.style.display = 'block';
1521
+ resumeBtn.setAttribute('data-conversation-id', conversationId);
1522
+
1311
1523
  // Load messages (placeholder for now)
1312
1524
  this.loadChatMessages(conversationId);
1313
1525
  }
@@ -1320,6 +1532,10 @@
1320
1532
 
1321
1533
  // Clean up scroll tracking when leaving conversation
1322
1534
  this.removeScrollTracking();
1535
+
1536
+ // Hide resume button
1537
+ const resumeBtn = document.getElementById('resumeConversation');
1538
+ resumeBtn.style.display = 'none';
1323
1539
 
1324
1540
  // Remove active state from conversations
1325
1541
  document.querySelectorAll('.conversation-item').forEach(item => {
@@ -2581,6 +2797,114 @@
2581
2797
  }
2582
2798
  }
2583
2799
 
2800
+ // Global function to resume conversation with Claude Code
2801
+ function resumeConversationWithClaude() {
2802
+ const resumeBtn = document.getElementById('resumeConversation');
2803
+ const conversationId = resumeBtn.getAttribute('data-conversation-id');
2804
+
2805
+ if (!conversationId) {
2806
+ console.error('No conversation ID found');
2807
+ return;
2808
+ }
2809
+
2810
+ // Show modal with command
2811
+ showResumeModal(conversationId);
2812
+ }
2813
+
2814
+ function showResumeModal(conversationId) {
2815
+ const modal = document.getElementById('resumeModal');
2816
+ const modalCommand = document.getElementById('modalCommand');
2817
+ const command = `claude --resume ${conversationId}`;
2818
+
2819
+ // Set the command in the modal
2820
+ modalCommand.textContent = command;
2821
+ modalCommand.setAttribute('data-command', command);
2822
+
2823
+ // Show the modal
2824
+ modal.classList.add('show');
2825
+
2826
+ // Close modal when clicking outside
2827
+ modal.addEventListener('click', (e) => {
2828
+ if (e.target === modal) {
2829
+ closeResumeModal();
2830
+ }
2831
+ });
2832
+
2833
+ console.log('📋 Resume modal opened for conversation:', conversationId);
2834
+ }
2835
+
2836
+ function closeResumeModal() {
2837
+ const modal = document.getElementById('resumeModal');
2838
+ modal.classList.remove('show');
2839
+ }
2840
+
2841
+ function copyModalCommand() {
2842
+ const modalCommand = document.getElementById('modalCommand');
2843
+ const copyBtn = document.getElementById('copyCommandBtn');
2844
+ const command = modalCommand.getAttribute('data-command');
2845
+
2846
+ if (!command) {
2847
+ console.error('No command found to copy');
2848
+ return;
2849
+ }
2850
+
2851
+ if (navigator.clipboard && navigator.clipboard.writeText) {
2852
+ navigator.clipboard.writeText(command).then(() => {
2853
+ // Show success feedback
2854
+ const originalText = copyBtn.textContent;
2855
+ copyBtn.textContent = '✅ Copied!';
2856
+ copyBtn.style.backgroundColor = 'rgba(63, 185, 80, 0.8)';
2857
+ copyBtn.style.borderColor = 'rgba(63, 185, 80, 1)';
2858
+
2859
+ setTimeout(() => {
2860
+ copyBtn.textContent = originalText;
2861
+ copyBtn.style.backgroundColor = '';
2862
+ copyBtn.style.borderColor = '';
2863
+ closeResumeModal();
2864
+ }, 1500);
2865
+
2866
+ console.log('📋 Command copied to clipboard:', command);
2867
+ }).catch(err => {
2868
+ console.error('Failed to copy to clipboard:', err);
2869
+ fallbackCopy(command);
2870
+ });
2871
+ } else {
2872
+ // Fallback for browsers without clipboard API
2873
+ fallbackCopy(command);
2874
+ }
2875
+ }
2876
+
2877
+ function fallbackCopy(command) {
2878
+ // Create a temporary text area to select and copy
2879
+ const tempTextArea = document.createElement('textarea');
2880
+ tempTextArea.value = command;
2881
+ tempTextArea.style.position = 'fixed';
2882
+ tempTextArea.style.left = '-9999px';
2883
+ document.body.appendChild(tempTextArea);
2884
+ tempTextArea.select();
2885
+
2886
+ try {
2887
+ document.execCommand('copy');
2888
+ const copyBtn = document.getElementById('copyCommandBtn');
2889
+ const originalText = copyBtn.textContent;
2890
+ copyBtn.textContent = '✅ Copied!';
2891
+ copyBtn.style.backgroundColor = 'rgba(63, 185, 80, 0.8)';
2892
+
2893
+ setTimeout(() => {
2894
+ copyBtn.textContent = originalText;
2895
+ copyBtn.style.backgroundColor = '';
2896
+ closeResumeModal();
2897
+ }, 1500);
2898
+
2899
+ console.log('📋 Command copied using fallback method:', command);
2900
+ } catch (err) {
2901
+ console.error('Fallback copy failed:', err);
2902
+ alert(`Please copy this command manually:\n\n${command}`);
2903
+ } finally {
2904
+ document.body.removeChild(tempTextArea);
2905
+ }
2906
+ }
2907
+
2584
2908
  // Initialize the app
2585
2909
  document.addEventListener('DOMContentLoaded', () => {
2586
2910
  new ChatsMobileApp();
package/src/analytics.js CHANGED
@@ -1227,41 +1227,10 @@ class ClaudeAnalytics {
1227
1227
  // Activity heatmap data endpoint - needs full conversation history
1228
1228
  this.app.get('/api/activity', async (req, res) => {
1229
1229
  try {
1230
- // TEMPORARY: Use test data for demo/screenshots
1231
- console.log(`🔥 /api/activity called - using test data for demo...`);
1232
- const fs = require('fs');
1233
- const path = require('path');
1234
- const testDataPath = path.join(__dirname, 'test-activity-data.json');
1235
-
1236
- if (fs.existsSync(testDataPath)) {
1237
- const testData = JSON.parse(fs.readFileSync(testDataPath, 'utf8'));
1238
-
1239
- // Calculate totals
1240
- const totalContributions = testData.reduce((sum, day) => sum + day.conversations, 0);
1241
- const totalTools = testData.reduce((sum, day) => sum + day.tools, 0);
1242
- const totalMessages = testData.reduce((sum, day) => sum + day.messages, 0);
1243
- const totalTokens = testData.reduce((sum, day) => sum + day.tokens, 0);
1244
-
1245
- const activityData = {
1246
- dailyActivity: testData,
1247
- totalContributions,
1248
- activeDays: testData.length,
1249
- longestStreak: 7, // Sample streak
1250
- currentStreak: 3, // Sample current streak
1251
- totalTools,
1252
- totalMessages,
1253
- totalTokens,
1254
- timestamp: new Date().toISOString()
1255
- };
1256
-
1257
- return res.json(activityData);
1258
- }
1259
-
1260
- // Fallback to real data if test file doesn't exist
1261
1230
  console.log(`🔥 /api/activity called - loading all conversations...`);
1262
1231
  const allConversations = await this.conversationAnalyzer.loadConversations(this.stateCalculator);
1263
1232
  console.log(`🔥 Loaded ${allConversations.length} conversations from server`);
1264
-
1233
+
1265
1234
  // Generate activity data using complete dataset
1266
1235
  const activityData = this.generateActivityDataFromConversations(allConversations);
1267
1236
  res.json({