Task #603: distinct, non-purple home-tile colours
The four default home-screen tiles (Notes / Services / Meetings /
Admin) showed up as three blue tiles + one orange one. Root cause was
NOT the DB — seed.ts already gave each app a distinct hex — but the
`gradientForColor()` mapper in `artifacts/tx-os/src/pages/home.tsx`
only recognised blue/purple/green/orange/pink/teal, so yellow
(#eab308), red (#ef4444), and the dark navy meetings colour all fell
through to the default blue gradient.
Changes:
1. `artifacts/tx-os/src/index.css` — added `.icon-tile-red` and
`.icon-tile-yellow` gradients matching the existing tile style.
2. `artifacts/tx-os/src/pages/home.tsx` — `gradientForColor()` now
maps red/dc2626 and yellow/facc15 first. Purple branch stays for
admin-custom apps but no seeded row uses it.
3. `scripts/src/seed.ts` —
- Meetings: `#0B1E3F` → `#22c55e` (green).
- Notifications: `#8b5cf6` → `#06b6d4` (cyan) — kills the last
purple in the default palette per user direction.
4. `scripts/src/update-app-colors.ts` (new) — idempotent migration
that bumps existing rows ONLY when they still hold the exact old
default colour, so admin customisations from the Apps editor are
preserved. Wired into `scripts/package.json` as
`pnpm run update-app-colors`.
5. `scripts/redeploy.sh` — new step 5/6 runs the colour migration
after seed and before `docker compose up -d`, on the same one-shot
`migrate` container pattern as other one-shot scripts.
No schema changes, no new deps. tx-os tsc passes, scripts tsc passes.
After `./scripts/redeploy.sh` on Mac, home shows four distinct hues
(yellow / orange / green / red) and no tile is purple anywhere.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
"seed": "tsx ./src/seed.ts",
|
||||
"remove-chat": "tsx ./src/remove-chat.ts",
|
||||
"disable-deprecated-apps": "tsx ./src/disable-deprecated-apps.ts",
|
||||
"update-app-colors": "tsx ./src/update-app-colors.ts",
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit",
|
||||
"test": "node --test 'tests/**/*.test.mjs'"
|
||||
},
|
||||
|
||||
+15
-6
@@ -72,13 +72,13 @@ fi
|
||||
step() { echo; echo "==> $*"; }
|
||||
|
||||
if [ "$PULL" -eq 1 ]; then
|
||||
step "1/4 git pull"
|
||||
step "1/6 git pull"
|
||||
git pull --ff-only
|
||||
else
|
||||
step "1/4 git pull (skipped via --no-pull)"
|
||||
step "1/6 git pull (skipped via --no-pull)"
|
||||
fi
|
||||
|
||||
step "2/5 docker compose build api web (rebuilds SPA + API images)"
|
||||
step "2/6 docker compose build api web (rebuilds SPA + API images)"
|
||||
# Stamp the API image with the current git SHA + UTC build time so the
|
||||
# admin "System Updates" panel shows visible proof that the new image
|
||||
# is actually running (instead of the old, hand-edited version.json).
|
||||
@@ -88,14 +88,23 @@ export BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
echo "[redeploy] GIT_SHA=$GIT_SHA BUILD_DATE=$BUILD_DATE"
|
||||
"${DC[@]}" build api web
|
||||
|
||||
step "3/5 docker compose run --rm migrate (schema push + tolerant seed)"
|
||||
step "3/6 docker compose run --rm migrate (schema push + tolerant seed)"
|
||||
"${DC[@]}" run --rm migrate
|
||||
|
||||
step "4/5 explicit seed pass (fails hard on seed regressions)"
|
||||
step "4/6 explicit seed pass (fails hard on seed regressions)"
|
||||
"${DC[@]}" run --rm --no-deps --entrypoint "" migrate \
|
||||
pnpm --filter @workspace/scripts run seed
|
||||
|
||||
step "5/5 docker compose up -d (restart with the new images)"
|
||||
step "5/6 one-shot data migrations (idempotent)"
|
||||
# #603: bump seeded app tile colours on existing installs. The seed
|
||||
# step above uses onConflictDoNothing for `slug`, so already-seeded
|
||||
# rows keep their old colours forever without this. The script only
|
||||
# touches rows that still hold the OLD default — admin customisations
|
||||
# from the Apps editor are left alone.
|
||||
"${DC[@]}" run --rm --no-deps --entrypoint "" migrate \
|
||||
pnpm --filter @workspace/scripts run update-app-colors
|
||||
|
||||
step "6/6 docker compose up -d (restart with the new images)"
|
||||
"${DC[@]}" up -d
|
||||
|
||||
echo
|
||||
|
||||
+11
-2
@@ -230,7 +230,11 @@ async function main() {
|
||||
descriptionEn: "Manage your notifications and alerts",
|
||||
iconName: "Bell",
|
||||
route: "/notifications",
|
||||
color: "#8b5cf6",
|
||||
// #603: was #8b5cf6 (purple). Switched to cyan so no seeded app
|
||||
// ships with a purple tile. Existing installs are migrated by
|
||||
// scripts/src/update-app-colors.ts (only rows still on the old
|
||||
// default are touched — admin customisations are preserved).
|
||||
color: "#06b6d4",
|
||||
// #571: ship the Notifications app DISABLED by default so fresh
|
||||
// installs don't surface a redundant tile alongside the bell icon
|
||||
// already in the top bar. The bell stays the canonical entry
|
||||
@@ -313,7 +317,12 @@ async function main() {
|
||||
descriptionEn: "Schedule and track meetings",
|
||||
iconName: "CalendarClock",
|
||||
route: "/meetings",
|
||||
color: "#0B1E3F",
|
||||
// #603: was #0B1E3F (dark navy) which fell through to the default
|
||||
// blue tile gradient, making Meetings indistinguishable from
|
||||
// Admin/Notes on the home screen. Switched to green so the four
|
||||
// default tiles are visually distinct. Existing installs are
|
||||
// migrated by scripts/src/update-app-colors.ts.
|
||||
color: "#22c55e",
|
||||
isActive: true,
|
||||
isSystem: false,
|
||||
sortOrder: 7,
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { db, appsTable } from "@workspace/db";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
|
||||
// #603: One-shot migration that bumps the seeded app colours on
|
||||
// existing installs to the new #603 palette. The seed itself uses
|
||||
// `onConflictDoNothing` on `slug`, so previously-seeded rows would
|
||||
// otherwise keep their old hex values forever and continue to render
|
||||
// as three identical blue tiles on the home screen.
|
||||
//
|
||||
// Each update is gated on the row STILL holding the old default —
|
||||
// admins who customised an app colour from the Apps editor keep their
|
||||
// choice untouched.
|
||||
const MIGRATIONS: Array<{ slug: string; from: string; to: string }> = [
|
||||
// Meetings: dark navy → green (was falling through to default blue).
|
||||
{ slug: "executive-meetings", from: "#0B1E3F", to: "#22c55e" },
|
||||
// Notifications: purple → cyan (purple is no longer in the palette).
|
||||
{ slug: "notifications", from: "#8b5cf6", to: "#06b6d4" },
|
||||
];
|
||||
|
||||
async function main(): Promise<void> {
|
||||
console.log("Migrating app colours to the #603 palette...");
|
||||
let touched = 0;
|
||||
for (const m of MIGRATIONS) {
|
||||
const updated = await db
|
||||
.update(appsTable)
|
||||
.set({ color: m.to })
|
||||
.where(and(eq(appsTable.slug, m.slug), eq(appsTable.color, m.from)))
|
||||
.returning({ slug: appsTable.slug, color: appsTable.color });
|
||||
if (updated.length === 0) {
|
||||
console.log(
|
||||
` - ${m.slug}: skipped (row missing or already customised)`,
|
||||
);
|
||||
} else {
|
||||
touched += updated.length;
|
||||
for (const row of updated) {
|
||||
console.log(` - ${row.slug}: color → ${row.color}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`Done. Rows updated: ${touched}.`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(() => process.exit(0));
|
||||
Reference in New Issue
Block a user