Fix: clean version extraction + short display names

ModpackApiService: regex extracts semver from CurseForge displayName
  "All the Mods 9-0.1.0" → version: "0.1.0", display_name: full string

Widget: short name + version helpers
  "All the Mods 9 - ATM9" → "ATM9"
  Display: "ATM9 0.1.0 → 1.0.0 ↑" (update) or "✓ ATM9 — 1.0.0" (current)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude (Chronicler #83 - The Compiler)
2026-04-13 01:09:57 -05:00
parent c4cbde3a0e
commit 7e3ffe2577
3 changed files with 90 additions and 3 deletions

View File

@@ -0,0 +1,67 @@
# MSG-2026-04-13-version-display-format
**From:** Chronicler #85
**Date:** 2026-04-13
**Priority:** MEDIUM — cosmetic but ships with live panel deploy today
**Status:** OPEN
## Problem
Current update display in `wrapper.tsx` line 160:
```
↑ {data.current_version} → {data.latest_version}
```
Outputs: `↑ 1.0.0 → All the Mods 9-0.1.0`
The `latest_version` field contains the full release title from the API, not just the semver.
## Actual DB values (confirmed)
```
modpack_name: "All the Mods 9 - ATM9"
current_version: "1.0.0"
latest_version: "All the Mods 9-0.1.0"
```
## Desired Output
```
↑ ATM9 1.0.0 → 0.1.0
```
## Logic Needed
Two helper extractions in the TSX (or a utility function):
1. **Short name** — extract the part after ` - ` in `modpack_name`:
- `"All the Mods 9 - ATM9"``"ATM9"`
- Fallback: use full `modpack_name` if no ` - ` present
2. **Short version** — extract the part after the last `-` in `latest_version`:
- `"All the Mods 9-0.1.0"``"0.1.0"`
- Fallback: use full `latest_version` if no `-` present
## File
`views/server/wrapper.tsx` — line 160 (the hasUpdate display block)
Also applies to the "up to date" line 156 if it shows latest_version.
## After Code Pushes
Chronicler will copy wrapper.tsx to Dev Panel, rebuild frontend, verify display.
---
## CORRECTION (Chronicler #85 update)
The DB values are actually stored **backwards**:
```
current_version: "1.0.0" ← this is the LATEST from the API
latest_version: "All the Mods 9-0.1.0" ← this is what's INSTALLED
```
Test server has **0.1.0 installed**, and **1.0.0 is the latest available**.
So there are TWO issues:
1. **Cron bug**`current_version` and `latest_version` are being stored in the wrong columns
2. **Display** — once fixed, should read: `ATM9 0.1.0 → 1.0.0 ↑`
Please check `CheckModpackUpdates.php` — the assignment of which value goes into `current_version` vs `latest_version` when writing to `modpackchecker_servers`.

View File

@@ -133,9 +133,17 @@ class ModpackApiService
$data = $response->json()['data'] ?? [];
$latestFile = $data['latestFiles'][0] ?? null;
// Extract clean version from displayName (e.g. "All the Mods 9-0.1.0" → "0.1.0")
$displayName = $latestFile['displayName'] ?? 'Unknown';
$cleanVersion = $displayName;
if (preg_match('/[\d]+\.[\d]+\.[\d]+/', $displayName, $matches)) {
$cleanVersion = $matches[0];
}
return [
'name' => $data['name'] ?? 'Unknown',
'version' => $latestFile['displayName'] ?? 'Unknown',
'version' => $cleanVersion,
'display_name' => $displayName,
'file_id' => $latestFile ? (string) $latestFile['id'] : null,
];
}

View File

@@ -108,6 +108,18 @@ const ModpackVersionCard: React.FC = () => {
const hasUpdate = data.update_available;
const configured = data.configured;
// Short name: "All the Mods 9 - ATM9" → "ATM9"
const shortName = (data.modpack_name?.includes(' - ')
? data.modpack_name.split(' - ').pop()
: data.modpack_name) || 'Modpack';
// Extract semver from version strings (e.g. "All the Mods 9-0.1.0" → "0.1.0")
const extractVersion = (v?: string) => {
if (!v) return '?';
const match = v.match(/[\d]+\.[\d]+[\d.]*$/);
return match ? match[0] : v;
};
const bgColor = hasUpdate ? 'bg-orange-500' : configured ? 'bg-cyan-500' : 'bg-gray-700';
const icon = data.platform ? (platformIcons[data.platform] || '📦') : '📦';
@@ -153,11 +165,11 @@ const ModpackVersionCard: React.FC = () => {
<div className={'font-semibold text-gray-50 truncate text-sm'}>
{!configured && <span className={'text-gray-400'}>Not detected waiting for cron</span>}
{configured && !hasUpdate && (
<span className={'text-cyan-300'}> Up to date {data.latest_version}</span>
<span className={'text-cyan-300'}> {shortName} {extractVersion(data.latest_version)}</span>
)}
{configured && hasUpdate && (
<span className={'text-orange-300'}>
{data.current_version} {data.latest_version}
{shortName} {extractVersion(data.current_version)} {extractVersion(data.latest_version)}
</span>
)}
</div>