@acms-subir/core 0.3.41 → 0.3.43

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/cli/migrations.generated.mjs +15 -0
  3. package/docs/mobile.md +10 -1
  4. package/integration.mjs +2 -0
  5. package/mobile-template/recipes/push/files/app/link-phone.tsx +43 -0
  6. package/mobile-template/recipes/push/files/app/notifications.tsx +14 -4
  7. package/mobile-template/recipes/push/recipe.json +4 -2
  8. package/package.json +1 -1
  9. package/src/components/Announcements.tsx +11 -2
  10. package/src/components/EmailSettings.tsx +1 -1
  11. package/src/components/MobileApp.tsx +20 -8
  12. package/src/components/TestPhones.tsx +177 -0
  13. package/src/lib/announcements/api.ts +19 -2
  14. package/src/lib/announcements/service.ts +1 -1
  15. package/src/lib/email/service.ts +19 -2
  16. package/src/lib/email/store.ts +9 -1
  17. package/src/lib/email/templates.ts +20 -0
  18. package/src/lib/forms/alert-mail.ts +124 -0
  19. package/src/lib/forms/alerts.ts +137 -0
  20. package/src/lib/forms/schema.ts +15 -1
  21. package/src/lib/forms/store.ts +26 -8
  22. package/src/lib/legal/app-privacy.ts +2 -2
  23. package/src/lib/legal/text-en.ts +2 -2
  24. package/src/lib/legal/text-es.ts +2 -2
  25. package/src/lib/mobile/forms.ts +2 -1
  26. package/src/lib/mobile/guest.ts +2 -1
  27. package/src/lib/mobile/openapi.ts +18 -3
  28. package/src/lib/mobile/schemas.ts +4 -0
  29. package/src/lib/push/api.ts +37 -8
  30. package/src/lib/push/service.ts +6 -2
  31. package/src/lib/push/staff.ts +162 -0
  32. package/src/lib/push/store.ts +49 -2
  33. package/src/lib/push/types.ts +8 -1
  34. package/src/lib/repo/migrations.ts +15 -0
  35. package/src/lib/repo/sql.ts +4 -1
  36. package/src/lib/sync/catalog.ts +2 -1
  37. package/src/pages/admin/forms/[id]/share.astro +49 -12
  38. package/src/pages/api/announcements.ts +2 -2
  39. package/src/pages/api/push/admin.ts +1 -1
  40. package/src/pages/api/push/phones.ts +25 -0
  41. package/src/pages/api/v1/devices/[token]/staff-link.ts +20 -0
  42. package/src/pages/forms/[id].astro +2 -1
  43. package/src/styles/forms-admin.css +8 -0
  44. package/src/styles/test-phones.css +30 -0
@@ -4,6 +4,7 @@ import { getRepo } from '../../lib/repo';
4
4
  import { renderForm } from '../../lib/forms/render';
5
5
  import { collectResponse } from '../../lib/forms/service';
6
6
  import { readForm, readAnswers, submissionGuard } from '../../lib/forms/http';
7
+ import { saveResponse } from '../../lib/forms/alerts';
7
8
  import { ApiError } from '../../lib/api';
8
9
  const repo = await getRepo(Astro.locals);
9
10
  const form = await repo.forms.get(Astro.params.id || '');
@@ -18,7 +19,7 @@ if (Astro.request.method === 'POST') {
18
19
  requestId = await submissionGuard(repo, data, Astro.clientAddress, `form:${form.id}`);
19
20
  values = readAnswers(data, form.definition);
20
21
  const response = await collectResponse(form.definition, values, String(data.get('formVersion') || ''));
21
- await repo.forms.submit(form.id, response, requestId);
22
+ await saveResponse(repo, form, response, requestId, { via: 'web', locals: Astro.locals });
22
23
  success = true;
23
24
  } catch (e) { error = e instanceof ApiError ? e.message : 'Could not save your response. Please try again.'; Astro.response.status = e instanceof ApiError ? e.status : 500; }
24
25
  }
@@ -153,6 +153,14 @@ input.mono { font-family: ui-monospace, 'SF Mono', monospace; font-size: 12.5px;
153
153
  .fs-used small { color: var(--muted); font-size: 12px; }
154
154
  .fs-used .status { font-size: 12px; }
155
155
  .fs-none { margin-top: 0; }
156
+ .fs-alerts { max-width: 560px; }
157
+ .fs-alerts .check-row { margin: 0 0 12px; }
158
+ .fs-alerts .check-row small { display: block; margin-top: 2px; }
159
+ .fs-alerts .notice { margin: 0 0 12px; }
160
+ /* the list and its options only matter while emails are on */
161
+ .fs-alerts:not(:has(input[name="enabled"]:checked)) .fs-alerts-more { display: none; }
162
+ .fs-alerts-more { padding-left: 23px; }
163
+ .fs-alerts-more > .hint { margin: 0 0 12px; }
156
164
 
157
165
  @media (max-width: 767px) {
158
166
  .fh-row { gap: 8px 10px; }
@@ -0,0 +1,30 @@
1
+ /* Test phones panel and "Send test to my phone" (Admin → Announcements and
2
+ Admin → Mobile app). Scoped under .tp; admin.css tokens only. */
3
+ .tp { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; scroll-margin-top: 72px; }
4
+ .tp > * { align-self: stretch; }
5
+ .tp > .btn { align-self: flex-start; }
6
+ .tp-head h2 { font-size: 14.5px; margin: 0; letter-spacing: -0.01em; }
7
+ .tp-head p { margin: 2px 0 0; color: var(--muted); font-size: 13px; max-width: 64ch; }
8
+ .tp-note { margin: 0; max-width: 64ch; }
9
+ .tp-intro { margin: 0 0 14px; max-width: 64ch; }
10
+ .tp-empty { margin: 0; color: var(--text-2); font-size: 13px; }
11
+ .tp-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
12
+ .tp-list li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--line); }
13
+ .tp-phone { display: flex; flex-direction: column; min-width: 0; }
14
+ .tp-phone b { font-size: 13.5px; }
15
+ .tp-phone small { color: var(--muted); font-size: 12px; }
16
+ .tp-code { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 4px 16px; background: var(--panel-2); border-radius: var(--r-md); padding: 12px 14px; }
17
+ .tp-code p { margin: 0; color: var(--text-2); font-size: 13px; max-width: 52ch; }
18
+ .tp-code .btn { grid-column: 2; justify-self: start; margin-top: 4px; }
19
+ .tp-digits { grid-row: span 2; font: 700 30px/1.1 ui-monospace, 'SF Mono', Menlo, monospace; letter-spacing: 0.18em; font-variant-numeric: tabular-nums; }
20
+ .tp-flash .flash { margin: 0; }
21
+ /* an always-present live region; no gap while empty */
22
+ .tp > .tp-flash:empty { margin-top: -12px; }
23
+ .tp-send > .tp-flash:empty { margin-top: -8px; }
24
+ .tp-send { display: flex; flex-direction: column; align-items: center; gap: 8px; align-self: stretch; }
25
+ .tp-send .tp-flash { align-self: stretch; text-align: center; }
26
+ @media (max-width: 560px) {
27
+ .tp-code { grid-template-columns: minmax(0, 1fr); }
28
+ .tp-digits { grid-row: auto; }
29
+ .tp-code .btn { grid-column: 1; }
30
+ }