mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: request a tool when home search finds nothing (#385)
Adds a prefilled 'Request a tool' affordance to the home search empty state and beneath weak results. Opens the in-app feedback dialog with a new search_miss source and a structured search_query when analytics is on; links to a prefilled GitHub Discussions (Ideas) post when off, so a request is never silently dropped. Reuses the existing feedback pipe, dialog, and analytics gate; no new storage. i18n across all 21 locales.
This commit is contained in:
@@ -8,8 +8,13 @@ import { analyticsEnabled, bakedEnabled } from "./analytics-gate.js";
|
||||
let posthogClient: PostHog | null = null;
|
||||
|
||||
export interface FeedbackEventProperties {
|
||||
source: "global" | "tool_result" | "failed_job" | "admin_installer";
|
||||
survey_id?: "global-feedback-v1" | "tool-result-v1" | "failed-job-v1" | "admin-install-v1";
|
||||
source: "global" | "tool_result" | "failed_job" | "admin_installer" | "search_miss";
|
||||
survey_id?:
|
||||
| "global-feedback-v1"
|
||||
| "tool-result-v1"
|
||||
| "failed-job-v1"
|
||||
| "admin-install-v1"
|
||||
| "search-miss-v1";
|
||||
prompt_variant?: string;
|
||||
sentiment?: "great" | "okay" | "issue" | "missing" | "bug" | "idea" | "other";
|
||||
feedback_type?: "bug" | "feature_request" | "confusing_ux" | "performance" | "other";
|
||||
@@ -19,6 +24,7 @@ export interface FeedbackEventProperties {
|
||||
contact_name?: string;
|
||||
company?: string;
|
||||
tool_id?: string;
|
||||
search_query?: string;
|
||||
job_status?: "completed" | "failed";
|
||||
install_method?: "docker" | "docker_compose" | "source" | "cloud" | "other";
|
||||
usage_type?: "personal" | "team_internal" | "business_workflow" | "education" | "evaluating";
|
||||
@@ -128,6 +134,9 @@ function cleanFeedbackProperties(properties: FeedbackEventProperties): Record<st
|
||||
copyString("contact_name");
|
||||
copyString("company");
|
||||
copyString("tool_id");
|
||||
// Intentional: this is the user-typed query from a missing-tool feature request,
|
||||
// not the tool-telemetry "search query" that analytics-allowlist.ts never forwards.
|
||||
copyString("search_query");
|
||||
copyString("job_status");
|
||||
copyString("install_method");
|
||||
copyString("usage_type");
|
||||
|
||||
@@ -4,12 +4,19 @@ import { captureFeedback, type FeedbackEventProperties } from "../lib/analytics.
|
||||
import { analyticsEnabled } from "../lib/analytics-gate.js";
|
||||
import { requireAuth } from "../plugins/auth.js";
|
||||
|
||||
const SOURCE_VALUES = ["global", "tool_result", "failed_job", "admin_installer"] as const;
|
||||
const SOURCE_VALUES = [
|
||||
"global",
|
||||
"tool_result",
|
||||
"failed_job",
|
||||
"admin_installer",
|
||||
"search_miss",
|
||||
] as const;
|
||||
const SURVEY_ID_VALUES = [
|
||||
"global-feedback-v1",
|
||||
"tool-result-v1",
|
||||
"failed-job-v1",
|
||||
"admin-install-v1",
|
||||
"search-miss-v1",
|
||||
] as const;
|
||||
const SENTIMENT_VALUES = ["great", "okay", "issue", "missing", "bug", "idea", "other"] as const;
|
||||
const FEEDBACK_TYPE_VALUES = [
|
||||
@@ -93,6 +100,7 @@ const feedbackBodySchema = z
|
||||
contactName: optionalText(120),
|
||||
company: optionalText(160),
|
||||
toolId: toolIdSchema.optional(),
|
||||
searchQuery: optionalText(200),
|
||||
jobStatus: z.enum(["completed", "failed"]).optional(),
|
||||
installMethod: z.enum(INSTALL_METHOD_VALUES).optional(),
|
||||
usageType: z.enum(USAGE_TYPE_VALUES).optional(),
|
||||
@@ -103,7 +111,11 @@ const feedbackBodySchema = z
|
||||
.superRefine((value, ctx) => {
|
||||
const hasText = Boolean(value.message?.trim());
|
||||
const hasChoice = Boolean(
|
||||
value.sentiment || value.feedbackType || value.installMethod || value.usageType,
|
||||
value.sentiment ||
|
||||
value.feedbackType ||
|
||||
value.installMethod ||
|
||||
value.usageType ||
|
||||
value.searchQuery,
|
||||
);
|
||||
if (!hasText && !hasChoice) {
|
||||
ctx.addIssue({
|
||||
@@ -127,6 +139,7 @@ function toPostHogProperties(body: z.infer<typeof feedbackBodySchema>): Feedback
|
||||
contact_name: body.contactOk ? body.contactName || undefined : undefined,
|
||||
company: body.contactOk ? body.company || undefined : undefined,
|
||||
tool_id: body.toolId,
|
||||
search_query: body.searchQuery,
|
||||
job_status: body.jobStatus,
|
||||
install_method: body.installMethod,
|
||||
usage_type: body.usageType,
|
||||
|
||||
Reference in New Issue
Block a user