From da42a4e4a1c82cd148dc6ce3524f243958f06feb Mon Sep 17 00:00:00 2001 From: Gabriel Jablonski Date: Fri, 16 Jan 2026 00:51:16 -0300 Subject: [PATCH 01/11] ci: fixed bundler version to avoid bundler 4.0.4 incompatibility (#13290) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Problem Docker builds started failing with a misleading dependency resolution error: ``` Could not find compatible versions Because every version of devise-secure_password depends on railties >= 5.0.0, < 8.0.0 ... ``` ### Root Cause [Bundler 4.0.4](https://github.com/ruby/rubygems/releases/tag/bundler-v4.0.4) was released on January 14, 2026. The Dockerfile used `gem install bundler` without version pinning, which installed the latest (4.0.4) instead of the version specified in `Gemfile.lock` (2.5.16). ### Fix - Pin Bundler installation to match `Gemfile.lock`: `gem install bundler -v "$BUNDLER_VERSION"` - Update `BUNDLER_VERSION` from 2.5.11 to 2.5.16 ### ⚠️ Note Fix found by Claude while checking why the deploy was failing, and have not yet checked for alternatives which might be more appropriate, so further investigation might be required. --- docker/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index ea15f0c85..bd135e962 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,7 +11,7 @@ ENV PNPM_VERSION=${PNPM_VERSION} # For development docker-compose file overrides ARGS ARG BUNDLE_WITHOUT="development:test" ENV BUNDLE_WITHOUT ${BUNDLE_WITHOUT} -ENV BUNDLER_VERSION=2.5.11 +ENV BUNDLER_VERSION=2.5.16 ARG RAILS_SERVE_STATIC_FILES=true ENV RAILS_SERVE_STATIC_FILES ${RAILS_SERVE_STATIC_FILES} @@ -35,7 +35,7 @@ RUN apk update && apk add --no-cache \ curl \ xz \ && mkdir -p /var/app \ - && gem install bundler + && gem install bundler -v "$BUNDLER_VERSION" COPY --from=node /usr/local/bin/node /usr/local/bin/ COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules @@ -105,7 +105,7 @@ ENV PNPM_VERSION=${PNPM_VERSION} ARG BUNDLE_WITHOUT="development:test" ENV BUNDLE_WITHOUT ${BUNDLE_WITHOUT} -ENV BUNDLER_VERSION=2.5.11 +ENV BUNDLER_VERSION=2.5.16 ARG EXECJS_RUNTIME="Disabled" ENV EXECJS_RUNTIME ${EXECJS_RUNTIME} @@ -128,7 +128,7 @@ RUN apk update && apk add --no-cache \ imagemagick \ git \ vips \ - && gem install bundler + && gem install bundler -v "$BUNDLER_VERSION" COPY --from=node /usr/local/bin/node /usr/local/bin/ COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules From a8b302d4cd1950c76184488b4b1ae01ca4faba7b Mon Sep 17 00:00:00 2001 From: Pranav Date: Thu, 15 Jan 2026 19:53:57 -0800 Subject: [PATCH 02/11] feat(ee): Review Notes for CSAT Reports (#13289) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CSAT scores are helpful, but on their own they rarely tell the full story. A drop in rating can come from delayed timelines, unclear expectations, or simple misunderstandings, even when the issue itself was handled correctly. Review Notes for CSAT let admins/report manager roles add internal-only context next to each CSAT response. This makes it easier to interpret scores properly and focus on patterns and root causes, not just numbers. image ### Why this matters * Capture the real context behind individual CSAT ratings * Clarify whether a low score points to a genuine service issue or a process gap * Spot recurring themes across conversations and teams * Make CSAT reviews more useful for leadership reviews and retrospectives ### How Review Notes work **View CSAT responses** Open the CSAT report to see overall metrics, rating distribution, and individual responses. **Add a Review Note** For any CSAT entry, managers can add a Review Note directly below the customer’s feedback. **Document internal insights** Use Review Notes to capture things like: * Why a score was lower or higher than expected * Patterns you are seeing across similar cases * Observations around communication, timelines, or customer expectations Review Notes are visible only to administrators and people with report access only. We may expand visibility to agents in the future based on feedback. However, customers never see them. Each note clearly shows who added it and when, making it easy to review context and changes over time. --- .../csat_survey_responses_controller.rb | 2 + .../components/ui/DatePicker/DatePicker.vue | 6 +- .../dashboard/components/widgets/ShowMore.vue | 2 +- .../dashboard/i18n/locale/en/report.json | 55 +++- .../settings/reports/CsatResponses.vue | 15 +- .../reports/components/ConversationCell.vue | 26 -- .../components/Csat/CsatFilterHelpers.js | 36 +++ .../reports/components/Csat/CsatFilters.vue | 267 ++++++++++++++++++ .../reports/components/CsatContactCell.vue | 52 ++++ .../reports/components/CsatEmptyState.vue | 32 +++ .../reports/components/CsatExpandedRow.vue | 162 +++++++++++ .../components/CsatMetricCard.story.vue | 53 ++++ .../reports/components/CsatMetricCard.vue | 41 +++ .../reports/components/CsatMetrics.vue | 180 ++++-------- .../CsatRatingDistribution.story.vue | 75 +++++ .../components/CsatRatingDistribution.vue | 101 +++++++ .../components/CsatReviewNotesPaywall.vue | 28 ++ .../settings/reports/components/CsatTable.vue | 264 +++++++++++------ .../reports/components/CsatTableLoader.vue | 36 +++ .../components/specs/CSATMetrics.spec.js | 42 ++- .../__snapshots__/CSATMetrics.spec.js.snap | 10 - .../dashboard/store/modules/csat.js | 11 + .../store/modules/specs/csat/getters.spec.js | 15 + .../dashboard/store/mutation-types.js | 1 + app/models/csat_survey_response.rb | 1 + app/models/user.rb | 2 + .../csat_survey_responses/download.csv.erb | 28 +- .../update.json.jbuilder | 1 + .../_csat_survey_response.json.jbuilder | 8 + config/features.yml | 4 + config/locales/en.yml | 1 + config/routes.rb | 3 + ...l_observations_to_csat_survey_responses.rb | 5 + ...rvations_audit_to_csat_survey_responses.rb | 6 + db/schema.rb | 6 +- .../csat_survey_responses_controller.rb | 12 + .../enterprise/csat_survey_response_policy.rb | 4 + .../billing/handle_stripe_event_service.rb | 2 +- enterprise/config/premium_features.yml | 1 + .../csat_survey_responses_controller_spec.rb | 85 ++++++ 40 files changed, 1376 insertions(+), 305 deletions(-) delete mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/ConversationCell.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/Csat/CsatFilterHelpers.js create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/Csat/CsatFilters.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatContactCell.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatEmptyState.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatExpandedRow.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatMetricCard.story.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatMetricCard.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatRatingDistribution.story.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatRatingDistribution.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatReviewNotesPaywall.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatTableLoader.vue delete mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/specs/__snapshots__/CSATMetrics.spec.js.snap create mode 100644 app/views/api/v1/accounts/csat_survey_responses/update.json.jbuilder create mode 100644 db/migrate/20260114192518_add_internal_observations_to_csat_survey_responses.rb create mode 100644 db/migrate/20260114201315_add_observations_audit_to_csat_survey_responses.rb create mode 100644 enterprise/app/controllers/enterprise/api/v1/accounts/csat_survey_responses_controller.rb create mode 100644 spec/enterprise/controllers/enterprise/api/v1/accounts/csat_survey_responses_controller_spec.rb diff --git a/app/controllers/api/v1/accounts/csat_survey_responses_controller.rb b/app/controllers/api/v1/accounts/csat_survey_responses_controller.rb index f5bed6c34..0cde5f5c1 100644 --- a/app/controllers/api/v1/accounts/csat_survey_responses_controller.rb +++ b/app/controllers/api/v1/accounts/csat_survey_responses_controller.rb @@ -50,3 +50,5 @@ class Api::V1::Accounts::CsatSurveyResponsesController < Api::V1::Accounts::Base @current_page = params[:page] || 1 end end + +Api::V1::Accounts::CsatSurveyResponsesController.prepend_mod_with('Api::V1::Accounts::CsatSurveyResponsesController') diff --git a/app/javascript/dashboard/components/ui/DatePicker/DatePicker.vue b/app/javascript/dashboard/components/ui/DatePicker/DatePicker.vue index bbb31d72c..886bc30a0 100644 --- a/app/javascript/dashboard/components/ui/DatePicker/DatePicker.vue +++ b/app/javascript/dashboard/components/ui/DatePicker/DatePicker.vue @@ -206,10 +206,14 @@ const emitDateRange = () => { emit('dateRangeChanged', [selectedStartDate.value, selectedEndDate.value]); } }; + +const closeDatePicker = () => { + showDatePicker.value = false; +};