mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-19 00:01:14 +00:00
4eb8f7babe
Backend:
- Fix contact-create 500 (nil custom_fields, doubled slice, bad RETURNING SQL)
- Avatar upload: migration 000033, S3 public-read, PNG/JPG only,
client-resized to 512px + server dimension cap (1024px)
- Pull avatar_url through user + organization repo queries
Frontend:
- Settings restructured into nested routes with a rail layout
(/app/settings/{profile,notifications,security,members,roles,
workspace,billing,danger}); flat Section/Row primitives replace
the per-card rectangles; Save buttons only render when dirty
- Standalone /app/billing and /app/team removed; legacy URLs
redirect to the settings sections; UserNav trimmed accordingly
- CRM rebuilt: Pipelines CRUD + stage editor, Deals kanban with
HTML5 drag/drop, Tasks bucketed by due-date with inline toggle.
Frontend models realigned with backend (Deal.name, CRMTask.status
enum, paginated list shapes)
- Avatars: AvatarUploader component, client-side canvas resize,
wired into Profile + Workspace settings; UserNav + OrgSwitcher
render the uploaded image with initials fallback
- RBAC: lib/permissions.ts mirrors organization_permission.go;
inline role picker in Members; Roles & access section shows the
permission matrix and per-role member counts
- Audit log page at /app/audit, gated to owner+admin via canManage
- Plans aligned with warmbly-web pricing: Starter/Grow/Business/
Enterprise via lib/plans.ts; PlanPill, billing page, sidebar
badges and LockedSurface all read from the same catalogue
- Header PlanPill shows current plan with status-aware coloring;
sidebar locked rows show the required-plan badge instead of a
generic lock icon
Perf:
- QueryClient defaults (staleTime: 30s, refetchOnWindowFocus: false,
retry: 1) — kills 3-5 round-trip storm on every navigation
- useSubscription, usePlans → staleTime: Infinity (only invalidate
on plan-change mutations); useUser/Timezones/Orgs get long stales
with refetchOnMount: false
- vite.config: optimizeDeps for heavy libs + server.warmup for the
most-mounted entry pages
47 lines
1.3 KiB
TypeScript
47 lines
1.3 KiB
TypeScript
import { defineConfig } from "vite";
|
|
import react from "@vitejs/plugin-react";
|
|
import path from "path";
|
|
import tailwindcss from "@tailwindcss/vite";
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
react(),
|
|
tailwindcss(),
|
|
],
|
|
resolve: {
|
|
alias: {
|
|
"@": path.resolve(__dirname, "./src"),
|
|
},
|
|
},
|
|
// Pre-bundle heavy deps so the first request to the dev server
|
|
// doesn't trigger a cold compile of axios/framer-motion/etc. This
|
|
// shaves ~300-500ms off the first paint locally.
|
|
optimizeDeps: {
|
|
include: [
|
|
"react",
|
|
"react-dom",
|
|
"react-router-dom",
|
|
"axios",
|
|
"framer-motion",
|
|
"@tanstack/react-query",
|
|
"@tanstack/react-query-devtools",
|
|
"react-hot-toast",
|
|
"lucide-react",
|
|
"@remixicon/react",
|
|
],
|
|
},
|
|
server: {
|
|
// Warm up the most-mounted entry points before the user
|
|
// clicks them so navigation doesn't trigger a cold compile.
|
|
warmup: {
|
|
clientFiles: [
|
|
"./src/main.tsx",
|
|
"./src/app/app/layout.tsx",
|
|
"./src/app/app/emails/page.tsx",
|
|
"./src/app/app/campaigns/page.tsx",
|
|
"./src/app/app/contacts/page.tsx",
|
|
],
|
|
},
|
|
},
|
|
});
|