diff --git a/exo/tinychat/index.css b/exo/tinychat/index.css index 2dd3d087..47c5e4be 100644 --- a/exo/tinychat/index.css +++ b/exo/tinychat/index.css @@ -778,4 +778,55 @@ main { border-top-color: transparent; border-radius: 50%; animation: thinking-spin 1s linear infinite; +} + +.model-group { + margin-bottom: 12px; +} + +.model-group-header, +.model-subgroup-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 12px; + background-color: var(--primary-bg-color); + border-radius: 6px; + cursor: pointer; + transition: all 0.2s ease; + margin-bottom: 8px; +} + +.model-group-header:hover, +.model-subgroup-header:hover { + background-color: var(--secondary-color-transparent); +} + +.model-group-content { + padding-left: 12px; +} + +.model-subgroup { + margin-bottom: 8px; +} + +.model-subgroup-header { + font-size: 0.9em; + background-color: rgba(255, 255, 255, 0.05); +} + +.model-subgroup-content { + padding-left: 12px; +} + +.group-header-content { + display: flex; + align-items: center; + gap: 8px; +} + +.model-count { + font-size: 0.8em; + color: var(--secondary-color-transparent); + font-family: monospace; } \ No newline at end of file diff --git a/exo/tinychat/index.html b/exo/tinychat/index.html index 7ef552e9..ecc7a973 100644 --- a/exo/tinychat/index.html +++ b/exo/tinychat/index.html @@ -50,50 +50,78 @@ Loading models... - - - - - - - - - - - - Checking download status... - - - - - - - - - - - - - - - - - - + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + Checking download status... + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -178,6 +206,7 @@ + { topology: null, topologyInterval: null, + // Add these new properties + expandedGroups: {}, + init() { // Clean up any pending messages localStorage.removeItem("pendingMessage"); @@ -664,7 +667,55 @@ document.addEventListener("alpine:init", () => { `; vizElement.appendChild(nodeElement); }); - } + }, + + // Add these helper methods + countDownloadedModels(models) { + return Object.values(models).filter(model => model.downloaded).length; + }, + + getGroupCounts(groupModels) { + const total = Object.keys(groupModels).length; + const downloaded = this.countDownloadedModels(groupModels); + return `[${downloaded}/${total}]`; + }, + + // Update the existing groupModelsByPrefix method to include counts + groupModelsByPrefix(models) { + const groups = {}; + Object.entries(models).forEach(([key, model]) => { + const parts = key.split('-'); + const mainPrefix = parts[0].toUpperCase(); + + let subPrefix; + if (parts.length === 2) { + subPrefix = parts[1].toUpperCase(); + } else if (parts.length > 2) { + subPrefix = parts[1].toUpperCase(); + } else { + subPrefix = 'OTHER'; + } + + if (!groups[mainPrefix]) { + groups[mainPrefix] = {}; + } + if (!groups[mainPrefix][subPrefix]) { + groups[mainPrefix][subPrefix] = {}; + } + groups[mainPrefix][subPrefix][key] = model; + }); + return groups; + }, + + toggleGroup(prefix, subPrefix = null) { + const key = subPrefix ? `${prefix}-${subPrefix}` : prefix; + this.expandedGroups[key] = !this.expandedGroups[key]; + }, + + isGroupExpanded(prefix, subPrefix = null) { + const key = subPrefix ? `${prefix}-${subPrefix}` : prefix; + return this.expandedGroups[key] || false; + }, })); });