| 1 | <html> |
| 2 | |
| 3 | <head> |
| 4 | <title>Memory Details</title> |
| 5 | </head> |
| 6 | |
| 7 | <body> |
| 8 | <div x-data> |
| 9 | <template x-if="$store.memoryDashboardStore && $store.memoryDashboardStore.detailMemory"> |
| 10 | <div class="memory-detail-container"> |
| 11 | <!-- Compact Modal Header --> |
| 12 | <div class="modal-header modal-header-compact"> |
| 13 | <div class="header-info"> |
| 14 | <span class="area-badge" |
| 15 | :style="`background-color: ${$store.memoryDashboardStore.getAreaColor($store.memoryDashboardStore.detailMemory?.area)}`" |
| 16 | x-text="$store.memoryDashboardStore.detailMemory?.area?.toUpperCase() || 'UNKNOWN'"></span> |
| 17 | <span class="timestamp-text" x-text="$store.memoryDashboardStore.formatTimestamp($store.memoryDashboardStore.detailMemory?.timestamp, true)"></span> |
| 18 | <span class="source-text" x-text="$store.memoryDashboardStore.detailMemory?.knowledge_source ? 'Knowledge' : 'Conversation'"></span> |
| 19 | </div> |
| 20 | <div class="header-actions"> |
| 21 | <!-- View Mode Buttons --> |
| 22 | <template x-if="!$store.memoryDashboardStore.editMode"> |
| 23 | <div style="display: flex; gap: 0.5rem;"> |
| 24 | |
| 25 | <button class="btn btn-action-header copy-all" @click="$store.memoryDashboardStore.copyToClipboard($store.memoryDashboardStore.formatMemoryForCopy($store.memoryDashboardStore.detailMemory))" |
| 26 | title="Copy Complete Memory with Metadata"> |
| 27 | <x-icon name="copy_all"></x-icon> All |
| 28 | </button> |
| 29 | <button class="btn btn-action-header copy-content" @click="$store.memoryDashboardStore.copyToClipboard($store.memoryDashboardStore.detailMemory?.content_full)" |
| 30 | title="Copy Content Only"> |
| 31 | <x-icon name="content_copy"></x-icon> Content |
| 32 | </button> |
| 33 | <div style="width:2em"></div> |
| 34 | <button class="btn btn-action-header edit" @click="$store.memoryDashboardStore.enableEditMode()" |
| 35 | title="Edit Memory"> |
| 36 | <x-icon name="edit_document"></x-icon> |
| 37 | </button> |
| 38 | <button class="btn btn-action-header delete danger" @click="$confirmClick($event, () => $store.memoryDashboardStore.deleteMemory($store.memoryDashboardStore.detailMemory))" |
| 39 | title="Delete Memory"> |
| 40 | <x-icon name="delete"></x-icon> |
| 41 | </button> |
| 42 | </div> |
| 43 | </template> |
| 44 | <!-- Edit Mode Buttons --> |
| 45 | <template x-if="$store.memoryDashboardStore.editMode"> |
| 46 | <div style="display: flex; gap: 0.5rem;"> |
| 47 | <button class="btn btn-action-header cancel" @click="$store.memoryDashboardStore.cancelEditMode()" |
| 48 | title="Cancel Edit"> |
| 49 | <x-icon name="close"></x-icon> |
| 50 | </button> |
| 51 | <button class="btn btn-action-header confirm" @click="$store.memoryDashboardStore.confirmEditMode()" |
| 52 | title="Confirm Changes"> |
| 53 | <x-icon name="check"></x-icon> |
| 54 | </button> |
| 55 | |
| 56 | </div> |
| 57 | </template> |
| 58 | </div> |
| 59 | </div> |
| 60 | |
| 61 | <!-- Modal Body --> |
| 62 | <div class="modal-body"> |
| 63 | <!-- Main Content Section --> |
| 64 | <div class="content-section-main"> |
| 65 | <div class="content-block"> |
| 66 | <h4>Memory Content</h4> |
| 67 | <template x-if="!$store.memoryDashboardStore.editMode"> |
| 68 | <div class="memory-content-display"> |
| 69 | <p x-text="$store.memoryDashboardStore.detailMemory?.content_full"></p> |
| 70 | </div> |
| 71 | </template> |
| 72 | <template x-if="$store.memoryDashboardStore.editMode"> |
| 73 | <textarea class="memory-content-display" x-model="$store.memoryDashboardStore.detailMemory.content_full"></textarea> |
| 74 | </template> |
| 75 | </div> |
| 76 | |
| 77 | <!-- Tags Section --> |
| 78 | <div class="content-block" x-show="$store.memoryDashboardStore.detailMemory?.tags && $store.memoryDashboardStore.detailMemory.tags.length > 0"> |
| 79 | <h4>Tags</h4> |
| 80 | <div class="tags-display"> |
| 81 | <template x-for="tag in $store.memoryDashboardStore.detailMemory?.tags || []" :key="tag"> |
| 82 | <span class="tag-display" x-text="tag"></span> |
| 83 | </template> |
| 84 | </div> |
| 85 | </div> |
| 86 | </div> |
| 87 | |
| 88 | <!-- Metadata Sidebar --> |
| 89 | <div class="metadata-sidebar no-scrollbar"> |
| 90 | <h4>Metadata</h4> |
| 91 | |
| 92 | <!-- Basic Info --> |
| 93 | <div class="metadata-group"> |
| 94 | <div class="metadata-item"> |
| 95 | <span class="metadata-label">ID:</span> |
| 96 | <span class="metadata-value" x-text="$store.memoryDashboardStore.detailMemory?.id || 'N/A'"></span> |
| 97 | </div> |
| 98 | <div class="metadata-item"> |
| 99 | <span class="metadata-label">Area:</span> |
| 100 | <span class="metadata-value" x-text="$store.memoryDashboardStore.detailMemory?.area || 'N/A'"></span> |
| 101 | </div> |
| 102 | <div class="metadata-item"> |
| 103 | <span class="metadata-label">Source:</span> |
| 104 | <span class="metadata-value" x-text="$store.memoryDashboardStore.detailMemory?.knowledge_source ? 'Knowledge' : 'Conversation'"></span> |
| 105 | </div> |
| 106 | </div> |
| 107 | |
| 108 | <!-- Timestamps --> |
| 109 | <div class="metadata-group"> |
| 110 | <h5>Timestamps</h5> |
| 111 | <div class="metadata-item"> |
| 112 | <span class="metadata-label">Created:</span> |
| 113 | <span class="metadata-value" x-text="$store.memoryDashboardStore.formatTimestamp($store.memoryDashboardStore.detailMemory?.timestamp, false)"></span> |
| 114 | </div> |
| 115 | </div> |
| 116 | |
| 117 | <!-- Source Information --> |
| 118 | <div class="metadata-group" x-show="$store.memoryDashboardStore.detailMemory?.source_file"> |
| 119 | <h5>Source File</h5> |
| 120 | <div class="metadata-item"> |
| 121 | <span class="metadata-value source-file-display" x-text="$store.memoryDashboardStore.detailMemory?.source_file"></span> |
| 122 | </div> |
| 123 | </div> |
| 124 | |
| 125 | <!-- All Custom Metadata --> |
| 126 | <div class="metadata-group" x-show="$store.memoryDashboardStore.detailMemory?.metadata && Object.keys($store.memoryDashboardStore.detailMemory.metadata).length > 0"> |
| 127 | <h5>Raw Metadata</h5> |
| 128 | <template x-for="[key, value] in Object.entries($store.memoryDashboardStore.detailMemory?.metadata || {})" :key="key"> |
| 129 | <div class="metadata-item"> |
| 130 | <span class="metadata-label" x-text="key + ':'"></span> |
| 131 | <span class="metadata-value" x-text="typeof value === 'object' ? JSON.stringify(value) : value"></span> |
| 132 | </div> |
| 133 | </template> |
| 134 | </div> |
| 135 | |
| 136 | </div> |
| 137 | </div> |
| 138 | </div> |
| 139 | </template> |
| 140 | <style> |
| 141 | .modal-header-compact { |
| 142 | position: sticky; |
| 143 | padding-left: 0.8rem; |
| 144 | top: 0; |
| 145 | z-index: 100; |
| 146 | } |
| 147 | |
| 148 | .header-info { |
| 149 | display: flex; |
| 150 | align-items: center; |
| 151 | gap: 0.5rem; |
| 152 | font-size: 0.9rem; |
| 153 | } |
| 154 | |
| 155 | .timestamp-text, |
| 156 | .source-text { |
| 157 | color: var(--color-text); |
| 158 | opacity: 0.8; |
| 159 | padding: 0.25rem 0.5rem; |
| 160 | border-radius: var(--border-radius); |
| 161 | font-size: 0.75rem; |
| 162 | font-weight: 500; |
| 163 | border: 1px solid; |
| 164 | } |
| 165 | |
| 166 | .modal-body { |
| 167 | display: flex; |
| 168 | min-height: 60vh; |
| 169 | max-height: 100%; |
| 170 | } |
| 171 | |
| 172 | .content-section-main { |
| 173 | flex: 1; |
| 174 | padding: 1.5rem; |
| 175 | padding-bottom: 0; |
| 176 | overflow-y: hidden; |
| 177 | display: flex; |
| 178 | flex-direction: column; |
| 179 | } |
| 180 | |
| 181 | .content-block { |
| 182 | /* margin-bottom: 3rem; */ |
| 183 | display: flex; |
| 184 | flex-direction: column; |
| 185 | min-height: 0; |
| 186 | } |
| 187 | |
| 188 | /* Make the first content block (Memory Content) take all available space */ |
| 189 | .content-block:first-child { |
| 190 | flex: 1; |
| 191 | /* margin-bottom: 1.5rem; */ |
| 192 | min-height: 0; |
| 193 | } |
| 194 | |
| 195 | .content-block h4 { |
| 196 | margin: 0 0 1rem 0; |
| 197 | color: var(--color-text); |
| 198 | font-size: 1.1rem; |
| 199 | font-weight: 600; |
| 200 | /* border-bottom: 1px solid var(--color-border); */ |
| 201 | /* padding-bottom: 0.5rem; */ |
| 202 | } |
| 203 | |
| 204 | .memory-content-display { |
| 205 | border: 1px solid var(--color-border); |
| 206 | border-radius: 8px; |
| 207 | /* padding: 1.5rem; */ |
| 208 | line-height: 1.6; |
| 209 | color: var(--color-text); |
| 210 | /* Fixed height: parent container minus 1rem */ |
| 211 | flex: 1; |
| 212 | min-height: 25em; |
| 213 | /* Ensure textarea uses same styling */ |
| 214 | font-family: inherit; |
| 215 | font-size: inherit; |
| 216 | resize: none; |
| 217 | width: 100%; |
| 218 | box-sizing: border-box; |
| 219 | overflow: hidden; |
| 220 | display: flex; |
| 221 | flex-direction: column; |
| 222 | } |
| 223 | |
| 224 | .memory-content-display p { |
| 225 | background: var(--color-panel); |
| 226 | margin: 0; |
| 227 | padding: 1.5rem; |
| 228 | white-space: pre-wrap; |
| 229 | word-break: break-word; |
| 230 | overflow-y: auto; |
| 231 | overflow-x: hidden; |
| 232 | height: 0; |
| 233 | flex-grow: 1; |
| 234 | } |
| 235 | |
| 236 | textarea.memory-content-display { |
| 237 | padding: 1.5rem; |
| 238 | overflow-y: auto; |
| 239 | display: block; |
| 240 | } |
| 241 | |
| 242 | .tags-display { |
| 243 | display: flex; |
| 244 | flex-wrap: wrap; |
| 245 | gap: 0.5rem; |
| 246 | background: var(--color-background); |
| 247 | padding: 0.75rem; |
| 248 | border-radius: 8px; |
| 249 | border: 1px solid var(--color-border); |
| 250 | } |
| 251 | |
| 252 | .tag-display { |
| 253 | background: var(--color-primary); |
| 254 | color: white; |
| 255 | padding: 0.25rem 0.75rem; |
| 256 | border-radius: 12px; |
| 257 | font-size: 0.75rem; |
| 258 | font-weight: 500; |
| 259 | } |
| 260 | |
| 261 | .metadata-sidebar { |
| 262 | min-width: 300px; |
| 263 | max-width: 350px; |
| 264 | background: var(--color-panel); |
| 265 | border-left: 1px solid var(--color-border); |
| 266 | padding: 1.5rem; |
| 267 | overflow-y: auto; |
| 268 | max-height: 50em; |
| 269 | } |
| 270 | |
| 271 | /* Unified scrollbar styling for modal content */ |
| 272 | .memory-content-display p::-webkit-scrollbar, |
| 273 | textarea.memory-content-display::-webkit-scrollbar { |
| 274 | width: 6px; |
| 275 | height: 6px; |
| 276 | } |
| 277 | |
| 278 | .memory-content-display p::-webkit-scrollbar-track, |
| 279 | textarea.memory-content-display::-webkit-scrollbar-track { |
| 280 | background: transparent; |
| 281 | margin: 4px 0; |
| 282 | border-radius: 6px; |
| 283 | } |
| 284 | |
| 285 | .memory-content-display p::-webkit-scrollbar-thumb, |
| 286 | textarea.memory-content-display::-webkit-scrollbar-thumb { |
| 287 | background-color: rgba(155, 155, 155, 0.5); |
| 288 | border-radius: 6px; |
| 289 | transition: background-color 0.2s ease; |
| 290 | } |
| 291 | |
| 292 | .memory-content-display p::-webkit-scrollbar-thumb:hover, |
| 293 | textarea.memory-content-display::-webkit-scrollbar-thumb:hover { |
| 294 | background-color: rgba(155, 155, 155, 0.7); |
| 295 | } |
| 296 | |
| 297 | .metadata-sidebar h4 { |
| 298 | margin: 0 0 1rem 0; |
| 299 | color: var(--color-text); |
| 300 | font-size: 1.1rem; |
| 301 | font-weight: 600; |
| 302 | } |
| 303 | |
| 304 | .metadata-group { |
| 305 | margin-bottom: 1.5rem; |
| 306 | } |
| 307 | |
| 308 | .metadata-group h5 { |
| 309 | margin: 0 0 0.75rem 0; |
| 310 | color: var(--color-text); |
| 311 | opacity: 0.7; |
| 312 | font-size: 0.9rem; |
| 313 | font-weight: 600; |
| 314 | text-transform: uppercase; |
| 315 | letter-spacing: 0.5px; |
| 316 | } |
| 317 | |
| 318 | .metadata-item { |
| 319 | display: flex; |
| 320 | flex-direction: column; |
| 321 | gap: 0.25rem; |
| 322 | margin-bottom: 0.75rem; |
| 323 | padding: 0.5rem; |
| 324 | background: var(--color-background); |
| 325 | border: 1px solid var(--color-border); |
| 326 | border-radius: 6px; |
| 327 | } |
| 328 | |
| 329 | .metadata-label { |
| 330 | font-size: 0.8rem; |
| 331 | font-weight: 600; |
| 332 | color: var(--color-text); |
| 333 | opacity: 0.7; |
| 334 | text-transform: uppercase; |
| 335 | letter-spacing: 0.3px; |
| 336 | } |
| 337 | |
| 338 | .metadata-value { |
| 339 | font-size: 0.9rem; |
| 340 | color: var(--color-text); |
| 341 | word-break: break-all; |
| 342 | line-height: 1.4; |
| 343 | } |
| 344 | |
| 345 | .source-file-display { |
| 346 | font-family: monospace; |
| 347 | background: var(--color-panel); |
| 348 | padding: 0.5rem; |
| 349 | border-radius: 4px; |
| 350 | border: 1px solid var(--color-border); |
| 351 | } |
| 352 | |
| 353 | .memory-detail-container { |
| 354 | display: flex; |
| 355 | flex-direction: column; |
| 356 | height: 100%; |
| 357 | } |
| 358 | |
| 359 | /* Responsive design for modal */ |
| 360 | @media (max-width: 870px) { |
| 361 | .modal-body { |
| 362 | flex-direction: column; |
| 363 | } |
| 364 | |
| 365 | .metadata-sidebar { |
| 366 | min-width: unset; |
| 367 | max-width: unset; |
| 368 | min-height: unset; |
| 369 | border-left: none; |
| 370 | border-top: 1px solid var(--color-border); |
| 371 | } |
| 372 | |
| 373 | .metadata-item { |
| 374 | display: block; |
| 375 | } |
| 376 | |
| 377 | .modal-header-compact { |
| 378 | padding: 0.75rem 1rem; |
| 379 | flex-wrap: wrap; |
| 380 | gap: 0.75rem; |
| 381 | } |
| 382 | |
| 383 | .header-info { |
| 384 | flex-wrap: wrap; |
| 385 | } |
| 386 | |
| 387 | .content-section-main, |
| 388 | .metadata-sidebar { |
| 389 | padding: 1rem; |
| 390 | } |
| 391 | } |
| 392 | </style> |
| 393 | </div> |
| 394 | </body> |
| 395 | |
| 396 | </html> |