@the-portland-company/shell 0.37.0 → 0.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## 0.37.1 — 2026-07-27
2
+
3
+ ### Fixed — cross-app navigation kept the user's active organization
4
+
5
+ Every link the Relationship tree emitted was bare: `Forms` / `Surveys` / `Polls`
6
+ went to their standalone apps, and every core route went to `app.politogyvrm.com`,
7
+ with no `?org=` selector. A multi-org user working in one organization clicked a
8
+ feature and landed in whichever organization the destination resolved by default
9
+ (reported: working in "We Need Steve", clicked Contacts, arrived in another org's
10
+ contacts). Intra-app links already carried the selector, so the jump only
11
+ happened when crossing apps.
12
+
13
+ `standardPolitogyNav` now stamps `?org=<full-uuid>` on EVERY link it builds, in
14
+ every tree — the Campaign and Petition trees already did. The full UUID is the
15
+ only collision-free selector (contacts-api matches exact id first, then a short
16
+ suffix that can collide across a user's orgs), and `isNavItemActive` already
17
+ excludes `org` from active-detection, so nothing changes about which row is
18
+ selected. The app-owned `contactsItem` override is still used verbatim; the
19
+ `politogy_active_org` cookie remains the fallback for a bare URL.
20
+
21
+ The same treatment applies to the chrome's own cross-app links — "Buy More Fuel"
22
+ / "Add fuel" and "View all" quarantined contacts, which all point into VRM core.
23
+
1
24
  ## 0.37.0 — 2026-07-27
2
25
 
3
26
  ### Fixed — organization logo renders in every app, not just VRM core
@@ -150,6 +150,10 @@ var CORE_APP_ORIGIN = "https://app.politogyvrm.com";
150
150
  var CORE_BILLING_PATH = "/organization-settings/subscription-billing/text-email";
151
151
  var CORE_BILLING_URL = `${CORE_APP_ORIGIN}${CORE_BILLING_PATH}`;
152
152
  var QUARANTINED_CONTACTS_URL = `${CORE_APP_ORIGIN}/relationship/contacts/quarantined`;
153
+ function withOrgParam(url, orgId) {
154
+ if (!orgId) return url;
155
+ return `${url}${url.includes("?") ? "&" : "?"}org=${orgId}`;
156
+ }
153
157
  function resolveOrgLogoUrl(url) {
154
158
  const raw = url?.trim();
155
159
  if (!raw) return void 0;
@@ -504,7 +508,7 @@ function FuelRow({
504
508
  ) })
505
509
  ] });
506
510
  }
507
- function LowFuelHint({ lowFuel }) {
511
+ function LowFuelHint({ lowFuel, orgId }) {
508
512
  const [dismissed, setDismissed] = react.useState(() => {
509
513
  if (typeof window === "undefined") return false;
510
514
  try {
@@ -548,7 +552,7 @@ function LowFuelHint({ lowFuel }) {
548
552
  /* @__PURE__ */ jsxRuntime.jsx(
549
553
  "a",
550
554
  {
551
- href: CORE_BILLING_URL,
555
+ href: withOrgParam(CORE_BILLING_URL, orgId),
552
556
  className: "mt-1 inline-block text-sm font-bold underline hover:opacity-90",
553
557
  children: "Buy More Fuel"
554
558
  }
@@ -615,7 +619,7 @@ function FuelAction({ orgId }) {
615
619
  label: "SMS Signal",
616
620
  channel: fuel?.signal ?? null,
617
621
  loading,
618
- addHref: CORE_BILLING_URL,
622
+ addHref: withOrgParam(CORE_BILLING_URL, orgId),
619
623
  addLabel: "Add SMS Signal fuel"
620
624
  }
621
625
  ),
@@ -625,7 +629,7 @@ function FuelAction({ orgId }) {
625
629
  label: "Email Broadcast",
626
630
  channel: fuel?.broadcast ?? null,
627
631
  loading,
628
- addHref: CORE_BILLING_URL,
632
+ addHref: withOrgParam(CORE_BILLING_URL, orgId),
629
633
  addLabel: "Add Email Broadcast fuel"
630
634
  }
631
635
  )
@@ -633,7 +637,7 @@ function FuelAction({ orgId }) {
633
637
  ] })
634
638
  }
635
639
  ),
636
- /* @__PURE__ */ jsxRuntime.jsx(LowFuelHint, { lowFuel: low })
640
+ /* @__PURE__ */ jsxRuntime.jsx(LowFuelHint, { lowFuel: low, orgId })
637
641
  ] })
638
642
  );
639
643
  }
@@ -928,7 +932,7 @@ function NotificationsAction({ orgId }) {
928
932
  /* @__PURE__ */ jsxRuntime.jsx(
929
933
  "a",
930
934
  {
931
- href: QUARANTINED_CONTACTS_URL,
935
+ href: withOrgParam(QUARANTINED_CONTACTS_URL, orgId),
932
936
  className: "text-[11px] font-semibold text-[color:var(--color-race-red)] hover:underline",
933
937
  children: "View all"
934
938
  }
@@ -1396,15 +1400,15 @@ function standardPolitogyNav(opts) {
1396
1400
  const base = opts.coreBaseUrl.replace(/\/+$/, "");
1397
1401
  const abs = (path) => `${base}${path.startsWith("/") ? path : `/${path}`}`;
1398
1402
  const icon = (key) => opts.icons?.[key];
1399
- const leaves = (children) => children.map((c) => ({ label: c.label, icon: icon(c.icon), href: abs(c.path) }));
1403
+ const orgParam = opts.activeOrgId ? `org=${opts.activeOrgId}` : "";
1404
+ const withOrg = (url) => orgParam ? `${url}${url.includes("?") ? "&" : "?"}${orgParam}` : url;
1405
+ const leaves = (children) => children.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(abs(c.path)) }));
1400
1406
  const branches = (children) => children.map((c) => ({
1401
1407
  label: c.label,
1402
1408
  icon: icon(c.icon),
1403
- href: abs(c.path),
1409
+ href: withOrg(abs(c.path)),
1404
1410
  children: c.children ? leaves(c.children) : void 0
1405
1411
  }));
1406
- const orgParam = opts.activeOrgId ? `org=${opts.activeOrgId}` : "";
1407
- const withOrg = (url) => orgParam ? `${url}${url.includes("?") ? "&" : "?"}${orgParam}` : url;
1408
1412
  const buildRelationship = () => {
1409
1413
  const contacts = opts.contactsItem ? {
1410
1414
  label: "Contacts",
@@ -1414,22 +1418,22 @@ function standardPolitogyNav(opts) {
1414
1418
  } : {
1415
1419
  label: "Contacts",
1416
1420
  icon: icon("users"),
1417
- href: abs("/relationship/contacts/dashboard"),
1421
+ href: withOrg(abs("/relationship/contacts/dashboard")),
1418
1422
  children: leaves(CONTACTS_DEFAULT_CHILDREN)
1419
1423
  };
1420
1424
  return [
1421
- { label: "Dashboard", icon: icon("home"), href: abs("/relationship/dashboard") },
1425
+ { label: "Dashboard", icon: icon("home"), href: withOrg(abs("/relationship/dashboard")) },
1422
1426
  contacts,
1423
1427
  {
1424
1428
  label: "Email Broadcast",
1425
1429
  icon: icon("mail"),
1426
- href: abs("/relationship/email/dashboard"),
1430
+ href: withOrg(abs("/relationship/email/dashboard")),
1427
1431
  children: leaves(EMAIL_CHILDREN)
1428
1432
  },
1429
1433
  {
1430
1434
  label: "SMS/MMS Blast",
1431
1435
  icon: icon("messageSquare"),
1432
- href: abs("/relationship/sms-mms-blast/dashboard"),
1436
+ href: withOrg(abs("/relationship/sms-mms-blast/dashboard")),
1433
1437
  children: leaves(SMS_CHILDREN)
1434
1438
  },
1435
1439
  // These two carry no top-level href in VRM core (parent row only toggles).
@@ -1437,25 +1441,25 @@ function standardPolitogyNav(opts) {
1437
1441
  {
1438
1442
  label: "Forms",
1439
1443
  icon: icon("activity"),
1440
- href: "https://forms.politogyvrm.com/",
1441
- children: APP_FORMS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: c.href }))
1444
+ href: withOrg("https://forms.politogyvrm.com/"),
1445
+ children: APP_FORMS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
1442
1446
  },
1443
1447
  {
1444
1448
  label: "Surveys",
1445
1449
  icon: icon("fileText"),
1446
- href: "https://surveys.politogyvrm.com/surveys",
1447
- children: APP_SURVEYS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: c.href }))
1450
+ href: withOrg("https://surveys.politogyvrm.com/surveys"),
1451
+ children: APP_SURVEYS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
1448
1452
  },
1449
1453
  {
1450
1454
  label: "Polls",
1451
1455
  icon: icon("barChart"),
1452
- href: "https://polls.politogyvrm.com/",
1453
- children: APP_POLLS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: c.href }))
1456
+ href: withOrg("https://polls.politogyvrm.com/"),
1457
+ children: APP_POLLS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
1454
1458
  },
1455
1459
  {
1456
1460
  label: "Organization Settings",
1457
1461
  icon: icon("briefcase"),
1458
- href: abs("/organization-settings"),
1462
+ href: withOrg(abs("/organization-settings")),
1459
1463
  children: branches(ORG_SETTINGS_CHILDREN)
1460
1464
  }
1461
1465
  ];