Commit Graph

5430 Commits

Author SHA1 Message Date
Dhruwang 7d77ed04de refactor(analytics): drop unused dims, broaden CSAT and group-by surface
Remove sentiment, emotion, and the TopicsUnnested join from the Cube
schema, web registry, AI prompt, audit-allowlist, and i18n keys — these
required metadata enrichment that is no longer planned. Tests swap the
removed string dimensions for sourceType to keep coverage intact.

Add csatDissatisfiedCount and csatNeutralCount so dashboards can render
the standard satisfied/neutral/dissatisfied distribution alongside the
existing top-2-box metric.

Expose field_label, field_group_label, language, value_boolean,
value_date, created_at, and updated_at as Cube dimensions. fieldLabel
and fieldGroupLabel unlock "group by question" and the matrix/ranking
aggregations enabled by the recent composite-question PR; the others
round out coverage of the underlying feedback_records columns. Extend
FieldDefinition with a boolean type and matching filter operators.
2026-05-12 18:45:10 +05:30
Dhruwang 602ffd5bba feat(analytics): augment Cube measures with CSAT/CES + bug fixes (ENG-804)
Adds CSAT and CES measures, plus a couple of universal cross-type measures,
to the FeedbackRecords Cube. Also fixes correctness bugs in the existing NPS
measures and constrains the AI chart-query output to known measure / dimension
ids.

Measures added
- csatScore: % of answered CSAT responses rated 4 or 5 (top-2-box on 1-5).
- csatAverage: AVG of answered CSAT ratings.
- csatSatisfiedCount: count where field_type='csat' AND value_number >= 4.
- csatCount: count of answered CSAT responses.
- cesAverage: AVG of answered CES ratings (1-5 or 1-7 depending on the question).
- cesCount: count of answered CES responses.
- uniqueRespondents: countDistinct(user_id).
- uniqueResponses: countDistinct(submission_id).
- npsAverage: AVG of answered NPS ratings (replaces the old `averageScore`
  measure, which silently averaged every numeric value across all field types).

Bug fixes (existing NPS measures)
- promoterCount / passiveCount / detractorCount / npsScore now filter
  field_type = 'nps'. Before, any numeric value in the band was counted
  (so a CSAT 5/5 was lumped in as a detractor).
- npsScore now divides by *answered* NPS responses only (value_number IS NOT
  NULL); dismissed/abandoned NPS records no longer drag the score toward 0.
- npsScore returns NULL when no answered NPS responses exist instead of the
  literal 0, so empty-data days render as gaps rather than a misleading
  flat-zero line.
- Same NULL-safe denominator fix applied to csatScore.
- csatCount / cesCount now exclude dismissed (value_number IS NULL) responses
  so they match the score denominators.

Dimensions
- Renamed `npsValue` -> `valueNumber` (the underlying value_number column
  stores values for NPS, CSAT, CES, rating, and number field types).
- New `valueText` dimension for grouping by categorical / open-text answers.

AI chart generation
- ZGenerateAIQueryResponse now enum-constrains `measures`, `dimensions`,
  `timeDimensions.dimension`, and `filters.member` against the known ids
  derived from FEEDBACK_FIELDS. Vercel AI SDK + Gemini structured outputs
  enforce these at decoding time, so the model can no longer return invalid
  or hallucinated measure names.
- generateText now pins temperature: 0. Same prompt produces the same query.

Breaking changes
- Charts that referenced `FeedbackRecords.averageScore` need to switch to
  `FeedbackRecords.npsAverage`.
- Charts that referenced `FeedbackRecords.npsValue` need to switch to
  `FeedbackRecords.valueNumber`.

Pre-GA on epic/v5; no production charts are expected to be impacted yet.
2026-05-12 16:05:38 +05:30
Dhruwang Jariwala 037b005d48 fix(charts): pie tooltip spacing + scroll to chart-name on empty save (ENG-914, ENG-916) (#7970) 2026-05-12 13:22:00 +05:30
Dhruwang Jariwala 6777b284b3 fix(a11y): large selects are not scrollable (#7963) 2026-05-12 12:08:38 +05:30
Anshuman Pandey c6282632e0 fix: fixes read only issues in feedback sources UI (#7974) 2026-05-12 10:20:30 +04:00
Dhruwang Jariwala f84c409bc4 feat: add beta badge to unify feedback navigation section (#7968) 2026-05-12 11:38:09 +05:30
Dhruwang Jariwala 98b475a2a4 fix(charts): time-range crash + sentiment/emotion/response-id cube column mismatches (ENG-907, ENG-906, ENG-915) (#7973) 2026-05-12 10:02:50 +04:00
Dhruwang c48474b943 chore(charts): drop sonar S6478 JSDoc on PieTooltipRow
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 11:31:38 +05:30
Anshuman Pandey 3c0d1e3fd7 fix: fixes connector modal UI errors (#7971) 2026-05-11 16:40:35 +04:00
Bhagya Amarasinghe 1f7a496967 fix(helm): stop forcing TEI float16 dtype (#7967) 2026-05-11 17:24:57 +05:30
Dhruwang 99e378ae2e chore: drop verbose doc comments on ChartDialogFooter props
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:44:15 +05:30
Dhruwang c6e39c3103 refactor(charts): hoist pie tooltip formatter to module scope (sonar S6478)
Same pattern as CartesianChart's ChartTooltipRow — a module-level
component that calls useTranslation internally, plus a thin formatter
function passed to ChartTooltipContent. Resolves the nested-component
warning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:41:18 +05:30
Dhruwang 19472ca9d3 chore: inline form onSubmit to avoid deprecated FormEvent type alias
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:37:20 +05:30
Dhruwang 43feff0009 fix(charts): inline error styling for empty chart-name on submit
Switch from the native browser tooltip to the in-app inline error pattern:
red Label, isInvalid Input border, and helper text below the field. The
onInvalid handler suppresses the default tooltip and scrolls + focuses the
field via event.currentTarget — no ref needed. Typing clears the error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:36:45 +05:30
Dhruwang 507cec6958 feat(charts): show translated message on empty chart-name validation
Browsers default to "Please fill in this field"; use the existing
workspace.analysis.charts.please_enter_chart_name key so the message
matches the toast we surface elsewhere. Clear custom validity on change
so the form unblocks once the user types.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:27:52 +05:30
Dhruwang d874b65be9 refactor(charts): use native form validation for chart-name field (ENG-916)
Replace the imperative scrollIntoView + focus on Save click with a tiny
<form> wrapping the required Input. The Save button becomes type=submit
with form="create-chart-form", so the browser handles scroll, focus, and
the "Please fill in this field" tooltip natively when the name is empty.

ChartDialogFooter now accepts either onSaveClick (button mode) or formId
(submit-button mode). All sibling buttons in the footer are explicitly
type="button" so they don't accidentally submit the form.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:25:17 +05:30
Dhruwang Jariwala c159af1a26 fix: format toast (ENG-893) (#7966) 2026-05-11 16:22:24 +05:30
Dhruwang 3ce2ef6cf4 fix(charts): scroll/focus chart-name input when save is blocked by empty name (ENG-916)
Clicking Save Chart with the name field empty fired a toast but left the
modal scrolled wherever the user was (e.g. on the chart preview at the
bottom), so they couldn't see what was wrong. Scroll the name field into
view and focus it before delegating to the existing save handler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:20:57 +05:30
Dhruwang Jariwala baae6335c9 fix: validate workspace assignment on feedback directory create (ENG-900) (#7965)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: pandeymangg <anshuman.pandey9999@gmail.com>
2026-05-11 14:50:05 +04:00
Dhruwang 8e443db1f6 revert: drop YAxis integer-tick handling
The fractional-tick bar/line/area scenario isn't the bug we're shipping in
this PR. Keep only the pie tooltip spacing/formatting change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:13:40 +05:30
Dhruwang 18cd9afc2c fix(charts): space between value and name in pie tooltip
Returning [value, name] from the tooltip formatter rendered as two adjacent text nodes ("3Nps"). Return a fragment with an explicit space so it reads "3 Nps".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:08:22 +05:30
Dhruwang 680e1e1593 fix(charts): show integer y-axis ticks for COUNT measures and format pie tooltips
ENG-914

When a chart's measures are all whole numbers (e.g. COUNT grouped by a
dimension), Recharts was auto-generating fractional y-axis ticks like
0.5, 1.5, 2 — nonsensical for a discrete count. The pie tooltip also
rendered values via raw String() with no thousand separators.

- Add allValuesAreIntegers() + formatYAxisTick() to chart-utils.
- CartesianChart now passes allowDecimals={false} and a number-aware
  tickFormatter to YAxis when every measure value is an integer.
- ChartRenderer's pie tooltip routes the value through formatCellValue,
  matching the Cartesian tooltip behaviour.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:49:57 +05:30
Dhruwang 04bfdeef69 removed stale comment 2026-05-11 15:09:51 +05:30
Dhruwang 8a1db7b6aa reverted errorcode transform change 2026-05-11 15:08:58 +05:30
Dhruwang 1d22fe2da6 fix: surface translated inline form errors and prefer .at() over slice
- FormError ignored its children when an error was set, rendering the raw
  zod message instead of the translated text passed in. Prefer explicit
  children, fall back to the field error message.
- Use .at(-1) in getTranslatedFeedbackDirectoryError per SonarQube S7755.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:03:00 +05:30
Dhruwang d8a119712c revert: drop zero-workspace requirement on feedback directory create
Per Johannes on ENG-893: zero-workspace creation is acceptable — admins
move workspaces between directories and forcing at least one is an
arbitrary limitation. The unformatted-error fix
(getTranslatedFeedbackDirectoryError prefix stripping) is retained.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:54:54 +05:30
Cursor Agent 50089eeca4 feat: add beta badge to unify feedback section
Co-authored-by: Johannes <jobenjada@users.noreply.github.com>
2026-05-11 08:20:06 +00:00
Bhagya Amarasinghe d8fe832f5f fix(helm): stop forcing TEI float16 dtype 2026-05-11 13:24:49 +05:30
Dhruwang 1c904e2243 fix: require at least one workspace when creating a feedback directory
ENG-893

Why: A feedback directory with zero workspaces is useless — it groups
nothing. The create path allowed it, and any validation error that did
fire surfaced as a raw "field: CODE" string in the toast.

How:
- createFeedbackDirectory now rejects empty/missing workspaceIds with
  DIRECTORY_WORKSPACES_REQUIRED before touching the database.
- getTranslatedFeedbackDirectoryError strips the "<field>: " prefix that
  next-safe-action prepends to validation errors, so machine codes always
  map to a translated message.
- Add the new translation key across all 15 locales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 13:04:47 +05:30
Javi Aguilar 4dbecc2d58 fix/a11y-select-scroll 2026-05-11 05:52:55 +02:00
Dhruwang Jariwala 72f4e93432 fix: support Redis Cluster for BullMQ jobs (#7960) 5.0.0-beta.3 2026-05-08 15:28:10 +05:30
Dhruwang Jariwala 9007502804 feat(feedback-sources): add a Create Survey CTA if there are none (#7943) 2026-05-08 15:10:28 +05:30
Tiago Farto d84589452c Merge branch 'epic/v5' of https://github.com/formbricks/formbricks into fix/investigate-bullmq-issue
# Conflicts:
#	docs/development/technical-handbook/background-job-processing.mdx
2026-05-08 09:38:53 +00:00
Tiago Farto 43aaed3923 fix: support Redis Cluster for BullMQ jobs 2026-05-08 09:19:49 +00:00
Bhagya Amarasinghe 550bfc6a6c fix: update Hub runtime defaults for v5 staging (#7959) 2026-05-07 19:25:20 +02:00
Bhagya Amarasinghe 2c22b00ec6 fix: address Cube chart review feedback (#7956) 5.0.0-beta.2 2026-05-07 17:27:55 +02:00
Bhagya Amarasinghe d64fb546d3 feat: add internal cube helm deployment (#7955) 2026-05-07 16:06:24 +02:00
Dhruwang Jariwala f4ca7c46ef fix: add Hub and Cube env vars to Docker build secrets (#7950) 5.0.0-beta.1 2026-05-07 17:22:05 +05:30
Dhruwang c252d8c4c9 fix: update tests for required Cube and Hub env vars
Tests now expect validation failures when CUBEJS_API_URL, CUBEJS_API_SECRET,
or HUB_API_KEY are missing, and all test env helpers provide HUB_API_KEY.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 17:14:01 +05:30
Dhruwang 2bec3b040d fix: remove unused ZOptionalUrl variable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 17:06:23 +05:30
Dhruwang 3c49b33dad feat: make HUB_API_KEY required and add to Docker build secrets
Hub is mandatory in v5, so HUB_API_KEY should fail fast at startup
if not configured.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 16:56:55 +05:30
Dhruwang 0f2f3d337e fix: restore CUBEJS_JWT_AUDIENCE and CUBEJS_JWT_ISSUER in env schema
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 16:48:57 +05:30
Dhruwang 4d1df795ad feat: make CUBEJS_API_SECRET and CUBEJS_API_URL required
Makes Cube env vars mandatory in env.ts (per PR #7913) and adds them
as Docker build secrets with fallback values, following the same pattern
as DATABASE_URL, REDIS_URL, and HUB_API_URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 16:45:46 +05:30
Bhagya Amarasinghe 3ce2998d0d feat(helm): add Hub worker and embeddings runtime (#7945) 2026-05-07 16:35:32 +05:30
Bhagya Amarasinghe b9a6520e10 fix(helm): address embeddings review feedback 2026-05-07 16:21:42 +05:30
Dhruwang 55bb9a525e fix: use secrets.DUMMY_HUB_API_URL instead of hardcoded value
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 16:20:48 +05:30
Dhruwang 11055f812e fix: add HUB_API_URL to Docker build secrets
HUB_API_URL is required by the Zod env validation at build time but was
not provided as a Docker secret, causing the release build to fail.

Adds HUB_API_URL with a dummy fallback (http://localhost:4000) to the
build pipeline, following the same pattern as DATABASE_URL/REDIS_URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 16:18:35 +05:30
Anshuman Pandey ecf3aacca3 fix: removes auto feedback directory linking with workspaces (#7947) 2026-05-07 13:46:25 +04:00
Dhruwang Jariwala a0f3d2a651 chore: upgrade Hub to 0.3.0 and SDK to 0.5.0 (#7948) 2026-05-07 14:59:11 +05:30
Dhruwang 16bbd7a447 chore: upgrade Hub to 0.3.0 and SDK to 0.5.0
Hub 0.3.0 renames the `user_identifier` API field to `user_id` (breaking
change). This commit bumps the Hub Docker image, upgrades the
@formbricks/hub TypeScript SDK from 0.4.3 to 0.5.0, and renames every
`user_identifier` reference in Zod schemas, server actions, transform
pipeline, form components, CubeJS schema, connector types, and seed data
to match the new API contract.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:31:09 +05:30