From fc9097e2d458d2af66cb56bef0427391d73107d5 Mon Sep 17 00:00:00 2001 From: Usama <59267656+ussaama@users.noreply.github.com> Date: Fri, 3 Apr 2026 19:29:15 +0500 Subject: [PATCH 1/6] Fixes after demo 3 apr (#509) Co-authored-by: Sameer Pashikanti --- .../directus/sync/collections/operations.json | 36 +- echo/directus/sync/collections/policies.json | 4 + .../prompt_template_preference.json | 28 - .../collections/prompt_template_rating.json | 28 - .../quick_access_preferences.json} | 28 +- .../date_created.json | 48 -- .../fields/prompt_template_preference/id.json | 46 -- .../prompt_template_id.json | 48 -- .../prompt_template_preference/sort.json | 44 -- .../template_type.json | 44 -- .../user_created.json | 48 -- .../chat_message_id.json | 48 -- .../prompt_template_rating/date_created.json | 48 -- .../prompt_template_rating/date_updated.json | 48 -- .../fields/prompt_template_rating/id.json | 46 -- .../prompt_template_id.json | 49 -- .../fields/prompt_template_rating/rating.json | 48 -- .../prompt_template_rating/user_created.json | 48 -- .../prompt_template_rating/user_updated.json | 48 -- .../prompt_template_id.json | 25 - .../user_created.json | 25 - .../chat_message_id.json | 25 - .../prompt_template_id.json | 25 - .../prompt_template_rating/user_created.json | 25 - .../prompt_template_rating/user_updated.json | 25 - ...template-community-report-anonymization.md | 695 ++++++++++++++++++ ...e-community-report-anonymization-design.md | 130 ++++ .../src/components/chat/ChatTemplatesMenu.tsx | 26 +- .../src/components/chat/CommunityTab.tsx | 144 ---- .../components/chat/CommunityTemplateCard.tsx | 159 ---- .../components/chat/PublishTemplateForm.tsx | 184 ----- .../chat/QuickAccessConfigurator.tsx | 144 ---- .../components/chat/TemplateRatingPills.tsx | 87 --- .../src/components/chat/TemplatesModal.tsx | 217 +----- .../chat/hooks/useCommunityTemplates.ts | 107 --- .../components/chat/hooks/useUserTemplates.ts | 75 +- .../src/components/chat/templateKey.ts | 6 + .../participant/ParticipantBody.tsx | 17 +- .../ParticipantConversationAudioContent.tsx | 1 + .../ParticipantConversationText.tsx | 1 + .../project/ProjectPortalEditor.tsx | 85 ++- .../components/report/CreateReportForm.tsx | 4 +- .../components/report/ReportFocusSelector.tsx | 14 +- .../report/UpdateReportModalButton.tsx | 6 +- echo/frontend/src/lib/api.ts | 137 +--- echo/frontend/src/locales/de-DE.po | 535 +++++++------- echo/frontend/src/locales/de-DE.ts | 2 +- echo/frontend/src/locales/en-US.po | 536 +++++++------- echo/frontend/src/locales/en-US.ts | 2 +- echo/frontend/src/locales/es-ES.po | 535 +++++++------- echo/frontend/src/locales/es-ES.ts | 2 +- echo/frontend/src/locales/fr-FR.po | 535 +++++++------- echo/frontend/src/locales/fr-FR.ts | 2 +- echo/frontend/src/locales/it-IT.po | 535 +++++++------- echo/frontend/src/locales/it-IT.ts | 2 +- echo/frontend/src/locales/nl-NL.po | 538 +++++++------- echo/frontend/src/locales/nl-NL.ts | 2 +- .../routes/project/chat/ProjectChatRoute.tsx | 92 +-- .../project/report/ProjectReportRoute.tsx | 27 +- echo/server/dembrane/api/participant.py | 2 + echo/server/dembrane/api/project.py | 22 +- echo/server/dembrane/api/project_webhook.py | 10 +- echo/server/dembrane/api/template.py | 526 ++----------- echo/server/dembrane/tasks.py | 37 +- 64 files changed, 2848 insertions(+), 4268 deletions(-) delete mode 100644 echo/directus/sync/snapshot/collections/prompt_template_preference.json delete mode 100644 echo/directus/sync/snapshot/collections/prompt_template_rating.json rename echo/directus/sync/snapshot/fields/{prompt_template_preference/static_template_id.json => directus_users/quick_access_preferences.json} (62%) delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_preference/date_created.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_preference/id.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_preference/prompt_template_id.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_preference/sort.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_preference/template_type.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_preference/user_created.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_rating/chat_message_id.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_rating/date_created.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_rating/date_updated.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_rating/id.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_rating/prompt_template_id.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_rating/rating.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_rating/user_created.json delete mode 100644 echo/directus/sync/snapshot/fields/prompt_template_rating/user_updated.json delete mode 100644 echo/directus/sync/snapshot/relations/prompt_template_preference/prompt_template_id.json delete mode 100644 echo/directus/sync/snapshot/relations/prompt_template_preference/user_created.json delete mode 100644 echo/directus/sync/snapshot/relations/prompt_template_rating/chat_message_id.json delete mode 100644 echo/directus/sync/snapshot/relations/prompt_template_rating/prompt_template_id.json delete mode 100644 echo/directus/sync/snapshot/relations/prompt_template_rating/user_created.json delete mode 100644 echo/directus/sync/snapshot/relations/prompt_template_rating/user_updated.json create mode 100644 echo/docs/superpowers/plans/2026-04-03-template-community-report-anonymization.md create mode 100644 echo/docs/superpowers/specs/2026-04-03-template-community-report-anonymization-design.md delete mode 100644 echo/frontend/src/components/chat/CommunityTab.tsx delete mode 100644 echo/frontend/src/components/chat/CommunityTemplateCard.tsx delete mode 100644 echo/frontend/src/components/chat/PublishTemplateForm.tsx delete mode 100644 echo/frontend/src/components/chat/QuickAccessConfigurator.tsx delete mode 100644 echo/frontend/src/components/chat/TemplateRatingPills.tsx delete mode 100644 echo/frontend/src/components/chat/hooks/useCommunityTemplates.ts diff --git a/echo/directus/sync/collections/operations.json b/echo/directus/sync/collections/operations.json index df2d31c5..c169726e 100644 --- a/echo/directus/sync/collections/operations.json +++ b/echo/directus/sync/collections/operations.json @@ -79,7 +79,7 @@ "resolve": null, "reject": null, "flow": "17703446-fef0-49e9-bdc4-385db1311137", - "_syncId": "84c38ea6-5d15-429f-8c24-9485d54ba7be" + "_syncId": "615a54cd-a72e-41ad-9403-9577c80280d6" }, { "name": "Email Send Operation Failed Dutch", @@ -93,7 +93,7 @@ "resolve": null, "reject": null, "flow": "17703446-fef0-49e9-bdc4-385db1311137", - "_syncId": "615a54cd-a72e-41ad-9403-9577c80280d6" + "_syncId": "84c38ea6-5d15-429f-8c24-9485d54ba7be" }, { "name": "failed", @@ -107,7 +107,7 @@ "resolve": null, "reject": null, "flow": "17703446-fef0-49e9-bdc4-385db1311137", - "_syncId": "eb6f8253-647f-4fb1-9010-e93594ba065e" + "_syncId": "8d8d787a-dbc4-44f9-9ab4-28e3f3d5f31c" }, { "name": "failed", @@ -121,7 +121,7 @@ "resolve": null, "reject": null, "flow": "17703446-fef0-49e9-bdc4-385db1311137", - "_syncId": "8d8d787a-dbc4-44f9-9ab4-28e3f3d5f31c" + "_syncId": "eb6f8253-647f-4fb1-9010-e93594ba065e" }, { "name": "Filter Emails", @@ -132,10 +132,10 @@ "options": { "code": "module.exports = async function(data) {\n\n const submissions = data.get_all_participants;\n \n // Filter submissions to only include those where email_opt_in is true\n const filteredSubmissions = submissions.filter(sub => sub.email_opt_in === true);\n\n // Create an array with email, project_id and an email_opt_out token for each submission\n const result = filteredSubmissions.map(sub => ({\n project_name: data.project_data[0].name || '',\n\t\tdefault_conversation_title: data.project_data[0].default_conversation_title || '',\n\t\tconversation_name: sub.conversation_id.participant_name || '',\n email: sub.email,\n project_id: sub.project_id || '',\n token: sub.email_opt_out_token,\n language: data.check_report_language[0].language || 'empty',\n ADMIN_BASE_URL: \"{{ $env.ADMIN_BASE_URL }}\" || \"http://localhost:5173\",\n PARTICIPANT_BASE_URL: \"{{ $env.PARTICIPANT_BASE_URL }}\" || \"http://localhost:5174\", \n }));\n \n return result;\n};" }, - "resolve": "e101f00d-2fb8-4f40-9e0e-4d24da5bb1e9", + "resolve": "b8144cee-59f6-40d9-a849-dd0c639e4e31", "reject": null, "flow": "ec4e7ea5-72de-4365-b66f-d8f11b549495", - "_syncId": "efb3982e-5703-4c07-8982-a6e1b5218e4a" + "_syncId": "ca1ffbc5-cfce-4fb4-8f15-c128ea407d41" }, { "name": "Filter Emails", @@ -146,10 +146,10 @@ "options": { "code": "module.exports = async function(data) {\n\n const submissions = data.get_all_participants;\n \n // Filter submissions to only include those where email_opt_in is true\n const filteredSubmissions = submissions.filter(sub => sub.email_opt_in === true);\n\n // Create an array with email, project_id and an email_opt_out token for each submission\n const result = filteredSubmissions.map(sub => ({\n project_name: data.project_data[0].name || '',\n\t\tdefault_conversation_title: data.project_data[0].default_conversation_title || '',\n\t\tconversation_name: sub.conversation_id.participant_name || '',\n email: sub.email,\n project_id: sub.project_id || '',\n token: sub.email_opt_out_token,\n language: data.check_report_language[0].language || 'empty',\n ADMIN_BASE_URL: \"{{ $env.ADMIN_BASE_URL }}\" || \"http://localhost:5173\",\n PARTICIPANT_BASE_URL: \"{{ $env.PARTICIPANT_BASE_URL }}\" || \"http://localhost:5174\", \n }));\n \n return result;\n};" }, - "resolve": "b8144cee-59f6-40d9-a849-dd0c639e4e31", + "resolve": "e101f00d-2fb8-4f40-9e0e-4d24da5bb1e9", "reject": null, "flow": "ec4e7ea5-72de-4365-b66f-d8f11b549495", - "_syncId": "ca1ffbc5-cfce-4fb4-8f15-c128ea407d41" + "_syncId": "efb3982e-5703-4c07-8982-a6e1b5218e4a" }, { "name": "log environment vars", @@ -213,7 +213,7 @@ "resolve": null, "reject": null, "flow": "ec4e7ea5-72de-4365-b66f-d8f11b549495", - "_syncId": "e8274ad4-5844-42cd-8a6b-d40d08cf83d3" + "_syncId": "84852456-3f3a-4906-be94-8b750159883b" }, { "name": "Report Not Published", @@ -227,7 +227,7 @@ "resolve": null, "reject": null, "flow": "ec4e7ea5-72de-4365-b66f-d8f11b549495", - "_syncId": "84852456-3f3a-4906-be94-8b750159883b" + "_syncId": "e8274ad4-5844-42cd-8a6b-d40d08cf83d3" }, { "name": "Send Email Dutch", @@ -256,9 +256,9 @@ ] }, "resolve": null, - "reject": "615a54cd-a72e-41ad-9403-9577c80280d6", + "reject": "84c38ea6-5d15-429f-8c24-9485d54ba7be", "flow": "17703446-fef0-49e9-bdc4-385db1311137", - "_syncId": "ea78ec02-364d-4f18-80f8-ea5ac4c787ed" + "_syncId": "34fb6ee5-2813-484a-a1cc-f97de097509b" }, { "name": "Send Email Dutch", @@ -287,9 +287,9 @@ ] }, "resolve": null, - "reject": "84c38ea6-5d15-429f-8c24-9485d54ba7be", + "reject": "615a54cd-a72e-41ad-9403-9577c80280d6", "flow": "17703446-fef0-49e9-bdc4-385db1311137", - "_syncId": "34fb6ee5-2813-484a-a1cc-f97de097509b" + "_syncId": "ea78ec02-364d-4f18-80f8-ea5ac4c787ed" }, { "name": "Send Email English", @@ -318,9 +318,9 @@ ] }, "resolve": null, - "reject": "920bd181-b2a2-4f0d-94dc-3b1a08c3f4ef", + "reject": "2b24450b-6a2e-4452-aba1-9814d17fef42", "flow": "17703446-fef0-49e9-bdc4-385db1311137", - "_syncId": "3dbf2ea1-17f8-4bde-aa89-43278fe9a00f" + "_syncId": "9390ed2f-7dc6-4a6a-83da-2d87d478261d" }, { "name": "Send Email English", @@ -349,9 +349,9 @@ ] }, "resolve": null, - "reject": "2b24450b-6a2e-4452-aba1-9814d17fef42", + "reject": "920bd181-b2a2-4f0d-94dc-3b1a08c3f4ef", "flow": "17703446-fef0-49e9-bdc4-385db1311137", - "_syncId": "9390ed2f-7dc6-4a6a-83da-2d87d478261d" + "_syncId": "3dbf2ea1-17f8-4bde-aa89-43278fe9a00f" }, { "name": "Trigger Email Flow", diff --git a/echo/directus/sync/collections/policies.json b/echo/directus/sync/collections/policies.json index 5687fce3..1dff0924 100644 --- a/echo/directus/sync/collections/policies.json +++ b/echo/directus/sync/collections/policies.json @@ -11,6 +11,10 @@ { "role": "_sync_default_admin_role", "sort": 1 + }, + { + "role": null, + "sort": null } ], "_syncId": "_sync_default_admin_policy" diff --git a/echo/directus/sync/snapshot/collections/prompt_template_preference.json b/echo/directus/sync/snapshot/collections/prompt_template_preference.json deleted file mode 100644 index e3034b06..00000000 --- a/echo/directus/sync/snapshot/collections/prompt_template_preference.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "collection": "prompt_template_preference", - "meta": { - "accountability": "all", - "archive_app_filter": true, - "archive_field": null, - "archive_value": null, - "collapse": "open", - "collection": "prompt_template_preference", - "color": null, - "display_template": null, - "group": null, - "hidden": false, - "icon": null, - "item_duplication_fields": null, - "note": null, - "preview_url": null, - "singleton": false, - "sort": null, - "sort_field": null, - "translations": null, - "unarchive_value": null, - "versioning": false - }, - "schema": { - "name": "prompt_template_preference" - } -} diff --git a/echo/directus/sync/snapshot/collections/prompt_template_rating.json b/echo/directus/sync/snapshot/collections/prompt_template_rating.json deleted file mode 100644 index f70534d8..00000000 --- a/echo/directus/sync/snapshot/collections/prompt_template_rating.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "collection": "prompt_template_rating", - "meta": { - "accountability": "all", - "archive_app_filter": true, - "archive_field": null, - "archive_value": null, - "collapse": "open", - "collection": "prompt_template_rating", - "color": null, - "display_template": null, - "group": null, - "hidden": false, - "icon": null, - "item_duplication_fields": null, - "note": null, - "preview_url": null, - "singleton": false, - "sort": null, - "sort_field": null, - "translations": null, - "unarchive_value": null, - "versioning": false - }, - "schema": { - "name": "prompt_template_rating" - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_preference/static_template_id.json b/echo/directus/sync/snapshot/fields/directus_users/quick_access_preferences.json similarity index 62% rename from echo/directus/sync/snapshot/fields/prompt_template_preference/static_template_id.json rename to echo/directus/sync/snapshot/fields/directus_users/quick_access_preferences.json index 37a971b8..932585ef 100644 --- a/echo/directus/sync/snapshot/fields/prompt_template_preference/static_template_id.json +++ b/echo/directus/sync/snapshot/fields/directus_users/quick_access_preferences.json @@ -1,34 +1,36 @@ { - "collection": "prompt_template_preference", - "field": "static_template_id", - "type": "string", + "collection": "directus_users", + "field": "quick_access_preferences", + "type": "json", "meta": { - "collection": "prompt_template_preference", + "collection": "directus_users", "conditions": null, "display": null, "display_options": null, - "field": "static_template_id", + "field": "quick_access_preferences", "group": null, "hidden": false, - "interface": "input", + "interface": "input-code", "note": null, "options": null, "readonly": false, "required": false, "searchable": true, - "sort": 5, - "special": null, + "sort": 9, + "special": [ + "cast-json" + ], "translations": null, "validation": null, "validation_message": null, "width": "full" }, "schema": { - "name": "static_template_id", - "table": "prompt_template_preference", - "data_type": "character varying", - "default_value": null, - "max_length": 100, + "name": "quick_access_preferences", + "table": "directus_users", + "data_type": "json", + "default_value": [], + "max_length": null, "numeric_precision": null, "numeric_scale": null, "is_nullable": true, diff --git a/echo/directus/sync/snapshot/fields/prompt_template_preference/date_created.json b/echo/directus/sync/snapshot/fields/prompt_template_preference/date_created.json deleted file mode 100644 index cbb38b73..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_preference/date_created.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "collection": "prompt_template_preference", - "field": "date_created", - "type": "timestamp", - "meta": { - "collection": "prompt_template_preference", - "conditions": null, - "display": "datetime", - "display_options": { - "relative": true - }, - "field": "date_created", - "group": null, - "hidden": true, - "interface": "datetime", - "note": null, - "options": null, - "readonly": true, - "required": false, - "searchable": true, - "sort": 3, - "special": [ - "date-created" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "half" - }, - "schema": { - "name": "date_created", - "table": "prompt_template_preference", - "data_type": "timestamp with time zone", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": null, - "foreign_key_column": null - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_preference/id.json b/echo/directus/sync/snapshot/fields/prompt_template_preference/id.json deleted file mode 100644 index dd78fcc3..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_preference/id.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "collection": "prompt_template_preference", - "field": "id", - "type": "uuid", - "meta": { - "collection": "prompt_template_preference", - "conditions": null, - "display": null, - "display_options": null, - "field": "id", - "group": null, - "hidden": true, - "interface": "input", - "note": null, - "options": null, - "readonly": true, - "required": false, - "searchable": true, - "sort": 1, - "special": [ - "uuid" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "full" - }, - "schema": { - "name": "id", - "table": "prompt_template_preference", - "data_type": "uuid", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": false, - "is_unique": true, - "is_indexed": false, - "is_primary_key": true, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": null, - "foreign_key_column": null - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_preference/prompt_template_id.json b/echo/directus/sync/snapshot/fields/prompt_template_preference/prompt_template_id.json deleted file mode 100644 index 461d1c05..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_preference/prompt_template_id.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "collection": "prompt_template_preference", - "field": "prompt_template_id", - "type": "uuid", - "meta": { - "collection": "prompt_template_preference", - "conditions": null, - "display": null, - "display_options": null, - "field": "prompt_template_id", - "group": null, - "hidden": false, - "interface": "select-dropdown-m2o", - "note": null, - "options": { - "template": "{{title}}" - }, - "readonly": false, - "required": false, - "searchable": true, - "sort": 6, - "special": [ - "m2o" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "full" - }, - "schema": { - "name": "prompt_template_id", - "table": "prompt_template_preference", - "data_type": "uuid", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": "prompt_template", - "foreign_key_column": "id" - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_preference/sort.json b/echo/directus/sync/snapshot/fields/prompt_template_preference/sort.json deleted file mode 100644 index 25ebccbb..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_preference/sort.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "collection": "prompt_template_preference", - "field": "sort", - "type": "integer", - "meta": { - "collection": "prompt_template_preference", - "conditions": null, - "display": null, - "display_options": null, - "field": "sort", - "group": null, - "hidden": false, - "interface": "input", - "note": null, - "options": null, - "readonly": false, - "required": false, - "searchable": true, - "sort": 7, - "special": null, - "translations": null, - "validation": null, - "validation_message": null, - "width": "full" - }, - "schema": { - "name": "sort", - "table": "prompt_template_preference", - "data_type": "integer", - "default_value": null, - "max_length": null, - "numeric_precision": 32, - "numeric_scale": 0, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": null, - "foreign_key_column": null - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_preference/template_type.json b/echo/directus/sync/snapshot/fields/prompt_template_preference/template_type.json deleted file mode 100644 index fae89fca..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_preference/template_type.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "collection": "prompt_template_preference", - "field": "template_type", - "type": "string", - "meta": { - "collection": "prompt_template_preference", - "conditions": null, - "display": null, - "display_options": null, - "field": "template_type", - "group": null, - "hidden": false, - "interface": "input", - "note": null, - "options": null, - "readonly": false, - "required": true, - "searchable": true, - "sort": 4, - "special": null, - "translations": null, - "validation": null, - "validation_message": null, - "width": "full" - }, - "schema": { - "name": "template_type", - "table": "prompt_template_preference", - "data_type": "character varying", - "default_value": null, - "max_length": 100, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": false, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": null, - "foreign_key_column": null - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_preference/user_created.json b/echo/directus/sync/snapshot/fields/prompt_template_preference/user_created.json deleted file mode 100644 index 4df92e93..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_preference/user_created.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "collection": "prompt_template_preference", - "field": "user_created", - "type": "uuid", - "meta": { - "collection": "prompt_template_preference", - "conditions": null, - "display": "user", - "display_options": null, - "field": "user_created", - "group": null, - "hidden": true, - "interface": "select-dropdown-m2o", - "note": null, - "options": { - "template": "{{avatar}} {{first_name}} {{last_name}}" - }, - "readonly": true, - "required": false, - "searchable": true, - "sort": 2, - "special": [ - "user-created" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "half" - }, - "schema": { - "name": "user_created", - "table": "prompt_template_preference", - "data_type": "uuid", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": "directus_users", - "foreign_key_column": "id" - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_rating/chat_message_id.json b/echo/directus/sync/snapshot/fields/prompt_template_rating/chat_message_id.json deleted file mode 100644 index 3db86d4c..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_rating/chat_message_id.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "chat_message_id", - "type": "uuid", - "meta": { - "collection": "prompt_template_rating", - "conditions": null, - "display": null, - "display_options": null, - "field": "chat_message_id", - "group": null, - "hidden": false, - "interface": "select-dropdown-m2o", - "note": null, - "options": { - "enableLink": true - }, - "readonly": false, - "required": false, - "searchable": true, - "sort": 8, - "special": [ - "m2o" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "full" - }, - "schema": { - "name": "chat_message_id", - "table": "prompt_template_rating", - "data_type": "uuid", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": "project_chat_message", - "foreign_key_column": "id" - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_rating/date_created.json b/echo/directus/sync/snapshot/fields/prompt_template_rating/date_created.json deleted file mode 100644 index 66497b80..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_rating/date_created.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "date_created", - "type": "timestamp", - "meta": { - "collection": "prompt_template_rating", - "conditions": null, - "display": "datetime", - "display_options": { - "relative": true - }, - "field": "date_created", - "group": null, - "hidden": true, - "interface": "datetime", - "note": null, - "options": null, - "readonly": true, - "required": false, - "searchable": true, - "sort": 3, - "special": [ - "date-created" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "half" - }, - "schema": { - "name": "date_created", - "table": "prompt_template_rating", - "data_type": "timestamp with time zone", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": null, - "foreign_key_column": null - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_rating/date_updated.json b/echo/directus/sync/snapshot/fields/prompt_template_rating/date_updated.json deleted file mode 100644 index 0cfe9684..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_rating/date_updated.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "date_updated", - "type": "timestamp", - "meta": { - "collection": "prompt_template_rating", - "conditions": null, - "display": "datetime", - "display_options": { - "relative": true - }, - "field": "date_updated", - "group": null, - "hidden": true, - "interface": "datetime", - "note": null, - "options": null, - "readonly": true, - "required": false, - "searchable": true, - "sort": 5, - "special": [ - "date-updated" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "half" - }, - "schema": { - "name": "date_updated", - "table": "prompt_template_rating", - "data_type": "timestamp with time zone", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": null, - "foreign_key_column": null - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_rating/id.json b/echo/directus/sync/snapshot/fields/prompt_template_rating/id.json deleted file mode 100644 index aa7bae23..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_rating/id.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "id", - "type": "uuid", - "meta": { - "collection": "prompt_template_rating", - "conditions": null, - "display": null, - "display_options": null, - "field": "id", - "group": null, - "hidden": true, - "interface": "input", - "note": null, - "options": null, - "readonly": true, - "required": false, - "searchable": true, - "sort": 1, - "special": [ - "uuid" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "full" - }, - "schema": { - "name": "id", - "table": "prompt_template_rating", - "data_type": "uuid", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": false, - "is_unique": true, - "is_indexed": false, - "is_primary_key": true, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": null, - "foreign_key_column": null - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_rating/prompt_template_id.json b/echo/directus/sync/snapshot/fields/prompt_template_rating/prompt_template_id.json deleted file mode 100644 index bef4fb66..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_rating/prompt_template_id.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "prompt_template_id", - "type": "uuid", - "meta": { - "collection": "prompt_template_rating", - "conditions": null, - "display": null, - "display_options": null, - "field": "prompt_template_id", - "group": null, - "hidden": false, - "interface": "select-dropdown-m2o", - "note": null, - "options": { - "enableLink": true, - "template": "{{title}}" - }, - "readonly": false, - "required": false, - "searchable": true, - "sort": 6, - "special": [ - "m2o" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "full" - }, - "schema": { - "name": "prompt_template_id", - "table": "prompt_template_rating", - "data_type": "uuid", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": "prompt_template", - "foreign_key_column": "id" - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_rating/rating.json b/echo/directus/sync/snapshot/fields/prompt_template_rating/rating.json deleted file mode 100644 index 08e9008b..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_rating/rating.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "rating", - "type": "integer", - "meta": { - "collection": "prompt_template_rating", - "conditions": null, - "display": null, - "display_options": null, - "field": "rating", - "group": null, - "hidden": false, - "interface": "slider", - "note": null, - "options": { - "maxValue": 5, - "minValue": 1, - "stepInterval": 1 - }, - "readonly": false, - "required": true, - "searchable": true, - "sort": 7, - "special": null, - "translations": null, - "validation": null, - "validation_message": null, - "width": "full" - }, - "schema": { - "name": "rating", - "table": "prompt_template_rating", - "data_type": "integer", - "default_value": null, - "max_length": null, - "numeric_precision": 32, - "numeric_scale": 0, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": null, - "foreign_key_column": null - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_rating/user_created.json b/echo/directus/sync/snapshot/fields/prompt_template_rating/user_created.json deleted file mode 100644 index 63e32188..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_rating/user_created.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "user_created", - "type": "uuid", - "meta": { - "collection": "prompt_template_rating", - "conditions": null, - "display": "user", - "display_options": null, - "field": "user_created", - "group": null, - "hidden": true, - "interface": "select-dropdown-m2o", - "note": null, - "options": { - "template": "{{avatar}} {{first_name}} {{last_name}}" - }, - "readonly": true, - "required": false, - "searchable": true, - "sort": 2, - "special": [ - "user-created" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "half" - }, - "schema": { - "name": "user_created", - "table": "prompt_template_rating", - "data_type": "uuid", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": "directus_users", - "foreign_key_column": "id" - } -} diff --git a/echo/directus/sync/snapshot/fields/prompt_template_rating/user_updated.json b/echo/directus/sync/snapshot/fields/prompt_template_rating/user_updated.json deleted file mode 100644 index 04cd40a9..00000000 --- a/echo/directus/sync/snapshot/fields/prompt_template_rating/user_updated.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "user_updated", - "type": "uuid", - "meta": { - "collection": "prompt_template_rating", - "conditions": null, - "display": "user", - "display_options": null, - "field": "user_updated", - "group": null, - "hidden": true, - "interface": "select-dropdown-m2o", - "note": null, - "options": { - "template": "{{avatar}} {{first_name}} {{last_name}}" - }, - "readonly": true, - "required": false, - "searchable": true, - "sort": 4, - "special": [ - "user-updated" - ], - "translations": null, - "validation": null, - "validation_message": null, - "width": "half" - }, - "schema": { - "name": "user_updated", - "table": "prompt_template_rating", - "data_type": "uuid", - "default_value": null, - "max_length": null, - "numeric_precision": null, - "numeric_scale": null, - "is_nullable": true, - "is_unique": false, - "is_indexed": false, - "is_primary_key": false, - "is_generated": false, - "generation_expression": null, - "has_auto_increment": false, - "foreign_key_table": "directus_users", - "foreign_key_column": "id" - } -} diff --git a/echo/directus/sync/snapshot/relations/prompt_template_preference/prompt_template_id.json b/echo/directus/sync/snapshot/relations/prompt_template_preference/prompt_template_id.json deleted file mode 100644 index 48c00710..00000000 --- a/echo/directus/sync/snapshot/relations/prompt_template_preference/prompt_template_id.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "collection": "prompt_template_preference", - "field": "prompt_template_id", - "related_collection": "prompt_template", - "meta": { - "junction_field": null, - "many_collection": "prompt_template_preference", - "many_field": "prompt_template_id", - "one_allowed_collections": null, - "one_collection": "prompt_template", - "one_collection_field": null, - "one_deselect_action": "nullify", - "one_field": null, - "sort_field": null - }, - "schema": { - "table": "prompt_template_preference", - "column": "prompt_template_id", - "foreign_key_table": "prompt_template", - "foreign_key_column": "id", - "constraint_name": "prompt_template_preference_prompt_template_id_foreign", - "on_update": "NO ACTION", - "on_delete": "SET NULL" - } -} diff --git a/echo/directus/sync/snapshot/relations/prompt_template_preference/user_created.json b/echo/directus/sync/snapshot/relations/prompt_template_preference/user_created.json deleted file mode 100644 index 610fc944..00000000 --- a/echo/directus/sync/snapshot/relations/prompt_template_preference/user_created.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "collection": "prompt_template_preference", - "field": "user_created", - "related_collection": "directus_users", - "meta": { - "junction_field": null, - "many_collection": "prompt_template_preference", - "many_field": "user_created", - "one_allowed_collections": null, - "one_collection": "directus_users", - "one_collection_field": null, - "one_deselect_action": "nullify", - "one_field": null, - "sort_field": null - }, - "schema": { - "table": "prompt_template_preference", - "column": "user_created", - "foreign_key_table": "directus_users", - "foreign_key_column": "id", - "constraint_name": "prompt_template_preference_user_created_foreign", - "on_update": "NO ACTION", - "on_delete": "NO ACTION" - } -} diff --git a/echo/directus/sync/snapshot/relations/prompt_template_rating/chat_message_id.json b/echo/directus/sync/snapshot/relations/prompt_template_rating/chat_message_id.json deleted file mode 100644 index c73dcdf3..00000000 --- a/echo/directus/sync/snapshot/relations/prompt_template_rating/chat_message_id.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "chat_message_id", - "related_collection": "project_chat_message", - "meta": { - "junction_field": null, - "many_collection": "prompt_template_rating", - "many_field": "chat_message_id", - "one_allowed_collections": null, - "one_collection": "project_chat_message", - "one_collection_field": null, - "one_deselect_action": "nullify", - "one_field": null, - "sort_field": null - }, - "schema": { - "table": "prompt_template_rating", - "column": "chat_message_id", - "foreign_key_table": "project_chat_message", - "foreign_key_column": "id", - "constraint_name": "prompt_template_rating_chat_message_id_foreign", - "on_update": "NO ACTION", - "on_delete": "SET NULL" - } -} diff --git a/echo/directus/sync/snapshot/relations/prompt_template_rating/prompt_template_id.json b/echo/directus/sync/snapshot/relations/prompt_template_rating/prompt_template_id.json deleted file mode 100644 index 0380b510..00000000 --- a/echo/directus/sync/snapshot/relations/prompt_template_rating/prompt_template_id.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "prompt_template_id", - "related_collection": "prompt_template", - "meta": { - "junction_field": null, - "many_collection": "prompt_template_rating", - "many_field": "prompt_template_id", - "one_allowed_collections": null, - "one_collection": "prompt_template", - "one_collection_field": null, - "one_deselect_action": "nullify", - "one_field": null, - "sort_field": null - }, - "schema": { - "table": "prompt_template_rating", - "column": "prompt_template_id", - "foreign_key_table": "prompt_template", - "foreign_key_column": "id", - "constraint_name": "prompt_template_rating_prompt_template_id_foreign", - "on_update": "NO ACTION", - "on_delete": "SET NULL" - } -} diff --git a/echo/directus/sync/snapshot/relations/prompt_template_rating/user_created.json b/echo/directus/sync/snapshot/relations/prompt_template_rating/user_created.json deleted file mode 100644 index 0f00c9c9..00000000 --- a/echo/directus/sync/snapshot/relations/prompt_template_rating/user_created.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "user_created", - "related_collection": "directus_users", - "meta": { - "junction_field": null, - "many_collection": "prompt_template_rating", - "many_field": "user_created", - "one_allowed_collections": null, - "one_collection": "directus_users", - "one_collection_field": null, - "one_deselect_action": "nullify", - "one_field": null, - "sort_field": null - }, - "schema": { - "table": "prompt_template_rating", - "column": "user_created", - "foreign_key_table": "directus_users", - "foreign_key_column": "id", - "constraint_name": "prompt_template_rating_user_created_foreign", - "on_update": "NO ACTION", - "on_delete": "NO ACTION" - } -} diff --git a/echo/directus/sync/snapshot/relations/prompt_template_rating/user_updated.json b/echo/directus/sync/snapshot/relations/prompt_template_rating/user_updated.json deleted file mode 100644 index f71c64e9..00000000 --- a/echo/directus/sync/snapshot/relations/prompt_template_rating/user_updated.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "collection": "prompt_template_rating", - "field": "user_updated", - "related_collection": "directus_users", - "meta": { - "junction_field": null, - "many_collection": "prompt_template_rating", - "many_field": "user_updated", - "one_allowed_collections": null, - "one_collection": "directus_users", - "one_collection_field": null, - "one_deselect_action": "nullify", - "one_field": null, - "sort_field": null - }, - "schema": { - "table": "prompt_template_rating", - "column": "user_updated", - "foreign_key_table": "directus_users", - "foreign_key_column": "id", - "constraint_name": "prompt_template_rating_user_updated_foreign", - "on_update": "NO ACTION", - "on_delete": "NO ACTION" - } -} diff --git a/echo/docs/superpowers/plans/2026-04-03-template-community-report-anonymization.md b/echo/docs/superpowers/plans/2026-04-03-template-community-report-anonymization.md new file mode 100644 index 00000000..f5d293c4 --- /dev/null +++ b/echo/docs/superpowers/plans/2026-04-03-template-community-report-anonymization.md @@ -0,0 +1,695 @@ +# Template Fixes, Community Removal, Report Colors, Anonymization UX + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Fix template quick access bugs by simplifying to JSON storage, remove dead community marketplace code, fix report button colors to match brand, and add anonymization UX for participants and hosts. + +**Architecture:** Four independent changes. Template preferences move from a separate Directus collection to a JSON field on `directus_users`. Community code is fully deleted. Report buttons change from teal to blue. Anonymization adds a muted notice in the participant recording view and a confirmation modal in the host portal editor. + +**Tech Stack:** Python/FastAPI, React/Mantine, Lingui i18n, Directus SDK + +--- + +## File Map + +| Change | Files to Modify | Files to Delete | +|--------|----------------|-----------------| +| Template preferences | `server/dembrane/api/template.py`, `frontend/src/lib/api.ts`, `frontend/src/components/chat/TemplatesModal.tsx`, `frontend/src/components/chat/templateKey.ts` | `frontend/src/components/chat/QuickAccessConfigurator.tsx` (if unused elsewhere) | +| Community removal | `server/dembrane/api/template.py`, `frontend/src/lib/api.ts`, `frontend/src/components/chat/TemplatesModal.tsx` | `frontend/src/components/chat/hooks/useCommunityTemplates.ts`, `frontend/src/components/chat/PublishTemplateForm.tsx` | +| Report colors | `frontend/src/components/report/CreateReportForm.tsx`, `frontend/src/components/report/UpdateReportModalButton.tsx`, `frontend/src/routes/project/report/ProjectReportRoute.tsx` | None | +| Anonymization UX | `frontend/src/components/participant/ParticipantBody.tsx`, `frontend/src/components/participant/ParticipantConversationAudio.tsx`, `frontend/src/components/participant/ParticipantConversationText.tsx`, `frontend/src/components/project/ProjectPortalEditor.tsx`, `frontend/src/locales/*.po` | None | + +--- + +### Task 1: Report Buttons -- Teal to Blue + +The simplest change. All primary buttons in the report feature use `color="teal"` but should use `color="blue"` per brand guidelines. + +**Files:** +- Modify: `frontend/src/components/report/CreateReportForm.tsx:258,295` +- Modify: `frontend/src/components/report/UpdateReportModalButton.tsx:149,274,311` +- Modify: `frontend/src/routes/project/report/ProjectReportRoute.tsx:548,992` + +- [ ] **Step 1: Change CreateReportForm.tsx buttons** + +In `frontend/src/components/report/CreateReportForm.tsx`, change both instances of `color="teal"` to `color="blue"`: + +Line 258 (Schedule Report button): +```tsx +color="blue" +``` + +Line 295 (Generate now button): +```tsx +color="blue" +``` + +- [ ] **Step 2: Change UpdateReportModalButton.tsx buttons** + +In `frontend/src/components/report/UpdateReportModalButton.tsx`, change all three instances of `color="teal"` to `color="blue"`: + +Line 149 (Update Report trigger button): +```tsx +color="blue" +``` + +Line 274 (Schedule Report button): +```tsx +color="blue" +``` + +Line 311 (Generate now button): +```tsx +color="blue" +``` + +- [ ] **Step 3: Change ProjectReportRoute.tsx buttons** + +In `frontend/src/routes/project/report/ProjectReportRoute.tsx`, change both instances of `color="teal"` to `color="blue"`: + +Line 548 (Confirm reschedule button): +```tsx +color="blue" +``` + +Line 992 (Publish toggle Switch): +```tsx +color="blue" +``` + +- [ ] **Step 4: Visual check** + +Run `cd frontend && pnpm build` to confirm no build errors. + +- [ ] **Step 5: Commit** + +```bash +git add frontend/src/components/report/CreateReportForm.tsx frontend/src/components/report/UpdateReportModalButton.tsx frontend/src/routes/project/report/ProjectReportRoute.tsx +git commit -m "fix: change report buttons from teal to blue per brand guidelines" +``` + +--- + +### Task 2: Remove Community Marketplace Code + +Full deletion of all community endpoints, schemas, frontend hooks, and API client functions. The `prompt_template_rating` Directus collection stays in the database (no destructive migration). + +**Files:** +- Modify: `server/dembrane/api/template.py` +- Delete: `frontend/src/components/chat/hooks/useCommunityTemplates.ts` +- Delete: `frontend/src/components/chat/PublishTemplateForm.tsx` +- Modify: `frontend/src/components/chat/TemplatesModal.tsx` +- Modify: `frontend/src/lib/api.ts` + +- [ ] **Step 1: Remove community schemas from template.py** + +In `server/dembrane/api/template.py`, delete lines 67-102 (the following schemas and constant): + +```python +# DELETE these blocks entirely: + +class PromptTemplateRatingIn(BaseModel): + prompt_template_id: str + rating: Literal[1, 2] # 1 = thumbs down, 2 = thumbs up + chat_message_id: Optional[str] = None + + +class PromptTemplateRatingOut(BaseModel): + id: str + prompt_template_id: str + rating: int + chat_message_id: Optional[str] = None + date_created: Optional[str] = None + + +ALLOWED_TAGS = ["Workshop", "Interview", "Focus Group", "Meeting", "Research", "Community", "Education", "Analysis"] + + +class CommunityTemplateOut(BaseModel): + id: str + title: str + description: Optional[str] = None + content: str + tags: Optional[List[str]] = None + language: Optional[str] = None + author_display_name: Optional[str] = None + star_count: int = 0 + use_count: int = 0 + date_created: Optional[str] = None + is_own: bool = False + + +class PublishTemplateIn(BaseModel): + description: Optional[str] = Field(default=None, max_length=500) + tags: Optional[List[str]] = Field(default=None) + language: Optional[str] = Field(default=None, max_length=10) + is_anonymous: bool = False +``` + +- [ ] **Step 2: Remove community endpoints from template.py** + +Delete the entire `# -- Community Marketplace --` section (lines 228-505), which contains these endpoints: +- `GET /community` (list_community_templates) +- `GET /community/my-stars` (get_my_community_stars) +- `POST /{id}/publish` (publish_template) +- `POST /{id}/unpublish` (unpublish_template) +- `POST /{id}/star` (toggle_star) +- `POST /{id}/copy` (copy_template) + +- [ ] **Step 3: Remove ratings endpoints from template.py** + +Delete the entire `# -- Ratings --` section (lines 584-681), which contains: +- `POST /ratings` (rate_prompt_template) +- `DELETE /ratings/{id}` (delete_rating) +- `GET /ratings` (list_my_ratings) + +- [ ] **Step 4: Clean up unused imports in template.py** + +After deletions, check if `List`, `Literal`, `Field` are still needed. `List` is used in remaining endpoints. `Literal` is used in `AiSuggestionsToggleIn` and remaining schemas. `Field` is used in remaining schemas. Keep all imports. + +- [ ] **Step 5: Delete frontend community hook file** + +Delete the entire file `frontend/src/components/chat/hooks/useCommunityTemplates.ts`. + +- [ ] **Step 6: Delete PublishTemplateForm component** + +Delete the entire file `frontend/src/components/chat/PublishTemplateForm.tsx`. + +- [ ] **Step 7: Remove community imports and code from TemplatesModal.tsx** + +In `frontend/src/components/chat/TemplatesModal.tsx`: + +Remove the community hooks import (lines 54-61): +```tsx +// DELETE: +import { + useCommunityTemplates, + useCopyTemplate, + useMyCommunityStars, + usePublishTemplate, + useToggleStar, + useUnpublishTemplate, +} from "./hooks/useCommunityTemplates"; +``` + +Remove the PublishTemplateForm import (line 62): +```tsx +// DELETE: +import { PublishTemplateForm } from "./PublishTemplateForm"; +``` + +Remove the `showCommunity` variable (lines 228-230): +```tsx +// DELETE: +// Community features disabled until Directus fields are created +// (author_display_name, use_count, star_count, copied_from) +const showCommunity = false; +``` + +Then search through the component for all references to `showCommunity`, community hooks (`useCommunityTemplates`, `useMyCommunityStars`, `usePublishTemplate`, `useUnpublishTemplate`, `useToggleStar`, `useCopyTemplate`), and community-related UI sections (any JSX gated by `showCommunity` or referencing community templates). Remove them all. + +Also remove unused imports from `@phosphor-icons/react` that were only used by community UI (e.g., `Globe`, `ShareNetwork`, `Star`, `Copy` -- check each is not used elsewhere in the file before removing). + +- [ ] **Step 8: Remove community API functions from api.ts** + +In `frontend/src/lib/api.ts`, delete the following sections: + +The `// -- Community Marketplace --` section (around lines 1849-1923): +```tsx +// DELETE all of: +export type CommunityTemplateResponse = { ... } +export type CommunityTemplateParams = { ... } +export const getCommunityTemplates = async (...) +export const getMyCommunityStars = async (...) +export const publishTemplate = async (...) +export const unpublishTemplate = async (...) +export const toggleTemplateStar = async (...) +export const copyTemplate = async (...) +``` + +The `// -- Prompt Template Ratings --` section (around lines 1925-1955): +```tsx +// DELETE all of: +export type PromptTemplateRatingResponse = { ... } +export const ratePromptTemplate = async (...) +export const deletePromptTemplateRating = async (...) +export const getMyRatings = async (...) +``` + +- [ ] **Step 9: Verify build** + +```bash +cd frontend && pnpm build +``` + +Fix any remaining import errors or references to deleted code. + +- [ ] **Step 10: Run server lint** + +```bash +cd /workspaces/echo && ./check-code.sh +``` + +- [ ] **Step 11: Commit** + +```bash +git add -A +git commit -m "feat: remove community marketplace code (endpoints, hooks, UI, API client)" +``` + +--- + +### Task 3: Simplify Template Quick Access to JSON + +Replace the `prompt_template_preference` Directus collection with a JSON field on `directus_users`. + +**Files:** +- Modify: `server/dembrane/api/template.py` +- Modify: `frontend/src/lib/api.ts` +- Modify: `frontend/src/components/chat/TemplatesModal.tsx` +- Modify: `frontend/src/components/chat/templateKey.ts` +- Delete: `frontend/src/components/chat/QuickAccessConfigurator.tsx` (if unused) + +**Prerequisite:** User must create a JSON field `quick_access_preferences` on `directus_users` in Directus admin. Type: JSON, default: `[]`, nullable: true. + +- [ ] **Step 1: Replace backend quick-access endpoints in template.py** + +Delete the old `# -- Quick-Access Preferences --` section (lines 508-581 after community removal) and replace with: + +```python +# -- Quick-Access Preferences -- + + +class QuickAccessItemIn(BaseModel): + type: Literal["static", "user"] + id: str + + +@TemplateRouter.get("/quick-access") +async def get_quick_access( + auth: DependencyDirectusSession, +) -> list: + """Get the user's quick access preferences as a JSON array.""" + try: + users = directus.get_users( + { + "query": { + "filter": {"id": {"_eq": auth.user_id}}, + "fields": ["quick_access_preferences"], + "limit": 1, + } + } + ) + if not isinstance(users, list) or len(users) == 0: + return [] + prefs = users[0].get("quick_access_preferences") + if not isinstance(prefs, list): + return [] + return prefs + except Exception as e: + logger.error(f"Failed to get quick access preferences: {e}") + raise HTTPException(status_code=500, detail="Failed to get preferences") from None + + +@TemplateRouter.put("/quick-access") +async def save_quick_access( + body: List[QuickAccessItemIn], + auth: DependencyDirectusSession, +) -> list: + """Save the user's quick access preferences as a JSON array.""" + if len(body) > 5: + raise HTTPException(status_code=400, detail="Maximum 5 quick access items") + + # Validate no duplicates + seen = set() + for item in body: + key = (item.type, item.id) + if key in seen: + raise HTTPException(status_code=400, detail=f"Duplicate item: {item.type}:{item.id}") + seen.add(key) + + # Validate user templates exist and belong to user + for item in body: + if item.type == "user": + try: + template = directus.get_item("prompt_template", item.id) + if not template or template.get("user_created") != auth.user_id: + raise HTTPException(status_code=400, detail=f"Template not found: {item.id}") + except HTTPException: + raise + except Exception: + raise HTTPException(status_code=400, detail=f"Template not found: {item.id}") from None + + prefs = [{"type": item.type, "id": item.id} for item in body] + + try: + directus.update_user(auth.user_id, {"quick_access_preferences": prefs}) + return prefs + except Exception as e: + logger.error(f"Failed to save quick access preferences: {e}") + raise HTTPException(status_code=500, detail="Failed to save preferences") from None +``` + +Also delete the old schemas that are no longer needed: +- `PromptTemplatePreferenceOut` (lines 48-53) +- `QuickAccessPreferenceIn` (lines 56-60) + +- [ ] **Step 2: Update frontend API client** + +In `frontend/src/lib/api.ts`, find the quick-access preference functions (around lines 1818-1836) and replace with: + +```typescript +// -- Quick-Access Preferences -- + +export type QuickAccessPreference = { + type: "static" | "user"; + id: string; +}; + +export const getQuickAccessPreferences = async (): Promise< + QuickAccessPreference[] +> => { + return api.get("/templates/quick-access"); +}; + +export const saveQuickAccessPreferences = async ( + preferences: QuickAccessPreference[], +): Promise => { + return api.put( + "/templates/quick-access", + preferences, + ); +}; +``` + +Also delete the old types that referenced the Directus collection shape (e.g., `QuickAccessPreferenceResponse` with `template_type`, `static_template_id`, `prompt_template_id`, `sort` fields). Search for any type that mentions `template_type` or `static_template_id` in the quick-access context. + +- [ ] **Step 3: Update TemplatesModal.tsx to use new preference shape** + +The modal currently converts between the old Directus shape (`template_type`, `static_template_id`, `prompt_template_id`) and the internal `QuickAccessItem` format. With the new JSON shape (`type`, `id`), the conversion becomes trivial. + +Update the hook/query that fetches preferences to map the new shape. The `QuickAccessItem` type from `QuickAccessConfigurator.tsx` has: +```typescript +type QuickAccessItem = { + type: "static" | "user"; + id: string; + title: string; +}; +``` + +The new API returns `{ type, id }` directly -- just add `title` by looking up the template. Update all code that previously transformed `template_type` -> `type` and `static_template_id`/`prompt_template_id` -> `id`. + +Also update the save function to send the new shape directly instead of converting to the old format. + +- [ ] **Step 4: Move QuickAccessItem type inline** + +If `QuickAccessConfigurator.tsx` is only imported for its `QuickAccessItem` type, move the type definition into `TemplatesModal.tsx` or `templateKey.ts` and delete `QuickAccessConfigurator.tsx`. + +Check first: +```bash +grep -r "QuickAccessConfigurator" frontend/src/ --include="*.tsx" --include="*.ts" +``` + +If only imported as a type in TemplatesModal.tsx (line 63), delete the file and inline the type. + +- [ ] **Step 5: Verify build and lint** + +```bash +cd /workspaces/echo && ./check-code.sh +``` + +- [ ] **Step 6: Commit** + +```bash +git add -A +git commit -m "feat: simplify quick access preferences to JSON field on directus_users" +``` + +--- + +### Task 4: Anonymization Notice for Participants + +Add a muted text notice in the participant recording view when the conversation is anonymized. + +**Files:** +- Modify: `frontend/src/components/participant/ParticipantBody.tsx` +- Modify: `frontend/src/components/participant/ParticipantConversationAudio.tsx` +- Modify: `frontend/src/components/participant/ParticipantConversationText.tsx` +- Modify: `frontend/src/locales/en-US.po` (and all other locale files) + +- [ ] **Step 1: Add isAnonymized prop to ParticipantBody** + +In `frontend/src/components/participant/ParticipantBody.tsx`, add an `isAnonymized` prop: + +At line 28-40 (component signature), add the prop: +```tsx +export const ParticipantBody = ({ + projectId, + conversationId, + viewResponses = false, + children, + interleaveMessages = true, + isRecording = false, + isAnonymized = false, +}: PropsWithChildren<{ + projectId: string; + conversationId: string; + viewResponses?: boolean; + interleaveMessages?: boolean; + isRecording?: boolean; + isAnonymized?: boolean; +}>) => { +``` + +- [ ] **Step 2: Add muted anonymization notice in ParticipantBody** + +After the existing `SystemMessage` for recording instructions (line 196), add a conditional notice: + +```tsx + + + {isAnonymized && ( + + + Your transcription will be anonymized and your host will not be able to listen to your recording. + + + )} +``` + +Add `Text` to the Mantine imports at line 4 if not already imported (it's not currently in the import list -- `Title` is imported but not `Text`). + +- [ ] **Step 3: Pass isAnonymized from ParticipantConversationAudio** + +In `frontend/src/components/participant/ParticipantConversationAudio.tsx`, the `conversationQuery` is already available (line 76). Find where `ParticipantBody` is rendered via `ParticipantConversationAudioContent.tsx` and pass the prop. + +Check the chain: `ParticipantConversationAudio` -> renders `ParticipantConversationAudioContent` -> renders `ParticipantBody`. + +In `frontend/src/components/participant/ParticipantConversationAudioContent.tsx` (line 136), add the prop: +```tsx + +``` + +The `isAnonymized` value needs to be passed down from `ParticipantConversationAudio.tsx`. Add it to the props of `ParticipantConversationAudioContent` and derive it from: +```tsx +const isAnonymized = conversationQuery.data?.is_anonymized ?? false; +``` + +- [ ] **Step 4: Pass isAnonymized from ParticipantConversationText** + +In `frontend/src/components/participant/ParticipantConversationText.tsx` (line 189), the component also renders `ParticipantBody`. Add the same pattern: + +```tsx +const conversationQuery = useConversationQuery(projectId, conversationId); +const isAnonymized = conversationQuery.data?.is_anonymized ?? false; +``` + +Then pass to `ParticipantBody`: +```tsx + +``` + +Check if `useConversationQuery` is already imported and used in this file. If not, add the import from `./hooks`. + +- [ ] **Step 5: Extract and compile translations** + +```bash +cd frontend +pnpm messages:extract +``` + +Edit each locale file to add the translation for `participant.anonymization.notice`: + +- `en-US.po`: "Your transcription will be anonymized and your host will not be able to listen to your recording." +- `nl-NL.po`: "Je transcriptie wordt geanonimiseerd en je host kan niet naar je opname luisteren." +- `de-DE.po`: "Ihre Transkription wird anonymisiert und Ihr Host kann Ihre Aufnahme nicht anhoren." +- `fr-FR.po`: "Votre transcription sera anonymisee et votre hote ne pourra pas ecouter votre enregistrement." +- `es-ES.po`: "Tu transcripcion sera anonimizada y tu anfitrion no podra escuchar tu grabacion." +- `it-IT.po`: "La tua trascrizione sara anonimizzata e il tuo host non potra ascoltare la tua registrazione." + +```bash +pnpm messages:compile +``` + +- [ ] **Step 6: Verify build** + +```bash +cd frontend && pnpm build +``` + +- [ ] **Step 7: Commit** + +```bash +git add -A +git commit -m "feat: add anonymization notice for participants on recording page" +``` + +--- + +### Task 5: Host Confirmation Modal for Disabling Anonymization + +Add a confirmation modal when the project owner toggles anonymization from ON to OFF. + +**Files:** +- Modify: `frontend/src/components/project/ProjectPortalEditor.tsx` +- Modify: `frontend/src/locales/en-US.po` (and all other locale files) + +- [ ] **Step 1: Add modal state and imports** + +In `frontend/src/components/project/ProjectPortalEditor.tsx`, add `useDisclosure` from `@mantine/hooks` (if not already imported) and `Modal` from `@mantine/core` (if not already imported). + +Add modal state near the top of the component: +```tsx +const [anonymizeModalOpened, { open: openAnonymizeModal, close: closeAnonymizeModal }] = useDisclosure(false); +``` + +- [ ] **Step 2: Modify the anonymize toggle onChange handler** + +Replace the current simple toggle (lines 1496-1498): +```tsx +onChange={(e) => + field.onChange(e.currentTarget.checked) +} +``` + +With a handler that intercepts turning OFF: +```tsx +onChange={(e) => { + const newValue = e.currentTarget.checked; + if (!newValue && field.value) { + // Turning OFF -- show confirmation + openAnonymizeModal(); + } else { + field.onChange(newValue); + } +}} +``` + +- [ ] **Step 3: Add the confirmation modal** + +Right after the `` for anonymize_transcripts (after line 1502), add: + +```tsx + + + + + Turning off anonymization while recordings are ongoing may + have unintended consequences. Active conversations will also + be affected mid-recording. Please use this with caution. + + + + + + + + +``` + +Note: Check how `setValue` is obtained from `useForm` in this component. It should already be destructured alongside `control` and `formState`. If not, add it to the destructuring. + +- [ ] **Step 4: Extract and compile translations** + +```bash +cd frontend +pnpm messages:extract +``` + +Add translations for `portal.anonymization.disable.warning` and `portal.anonymization.disable.confirm` in all locale files: + +- `en-US.po`: (as written above) +- `nl-NL.po`: Warning: "Het uitschakelen van anonimisering terwijl opnames gaande zijn kan onbedoelde gevolgen hebben. Actieve gesprekken worden ook beinvloed tijdens de opname. Gebruik dit met voorzichtigheid." / Confirm: "Uitschakelen" +- `de-DE.po`: Warning: "Das Deaktivieren der Anonymisierung wahrend laufender Aufnahmen kann unbeabsichtigte Folgen haben. Aktive Gesprache werden auch wahrend der Aufnahme betroffen. Bitte verwenden Sie dies mit Vorsicht." / Confirm: "Ausschalten" +- `fr-FR.po`: Warning: "La desactivation de l'anonymisation pendant les enregistrements en cours peut avoir des consequences inattendues. Les conversations actives seront egalement affectees en cours d'enregistrement. Veuillez utiliser cette option avec prudence." / Confirm: "Desactiver" +- `es-ES.po`: Warning: "Desactivar la anonimizacion mientras hay grabaciones en curso puede tener consecuencias no deseadas. Las conversaciones activas tambien se veran afectadas durante la grabacion. Por favor, use esto con precaucion." / Confirm: "Desactivar" +- `it-IT.po`: Warning: "Disattivare l'anonimizzazione durante le registrazioni in corso puo avere conseguenze indesiderate. Anche le conversazioni attive saranno interessate durante la registrazione. Si prega di usare questa opzione con cautela." / Confirm: "Disattiva" + +```bash +pnpm messages:compile +``` + +- [ ] **Step 5: Verify build** + +```bash +cd frontend && pnpm build +``` + +- [ ] **Step 6: Commit** + +```bash +git add -A +git commit -m "feat: add confirmation modal when disabling transcript anonymization" +``` + +--- + +### Task 6: Final Verification + +- [ ] **Step 1: Run full check** + +```bash +cd /workspaces/echo && ./check-code.sh +``` + +- [ ] **Step 2: Commit any remaining fixes** + +If check-code.sh reveals issues, fix and commit. + +- [ ] **Step 3: Tell user about Directus changes needed** + +Remind user to: +1. Create `quick_access_preferences` JSON field on `directus_users` (default: `[]`, nullable: true) +2. Delete the `prompt_template_preference` collection from Directus diff --git a/echo/docs/superpowers/specs/2026-04-03-template-community-report-anonymization-design.md b/echo/docs/superpowers/specs/2026-04-03-template-community-report-anonymization-design.md new file mode 100644 index 00000000..0b579feb --- /dev/null +++ b/echo/docs/superpowers/specs/2026-04-03-template-community-report-anonymization-design.md @@ -0,0 +1,130 @@ +# Design: Template Fixes, Community Removal, Report Colors, Anonymization UX + +**Date**: 2026-04-03 +**Status**: Approved + +## 1. Template Quick Access -- Simplify to JSON + +### Problem + +The current `prompt_template_preference` collection stores each quick access item as a separate Directus record. This causes: +- Duplicate entries (same template appearing multiple times) +- Orphaned entries (`template_type: "user"` with `prompt_template_id: null`) +- No backend validation (saves whatever frontend sends) +- Unnecessary complexity for a simple ordered list + +### Solution + +Replace separate Directus records with a single JSON field on the user settings. + +**New field**: `quick_access_preferences` (JSON) on `directus_users` or appropriate user settings collection. + +**Schema**: +```json +[ + {"type": "static", "id": "summarize"}, + {"type": "static", "id": "meeting-notes"}, + {"type": "user", "id": "abc-123"} +] +``` + +**Backend**: +- New `GET /templates/quick-access` endpoint: reads the JSON field, returns the array (empty array default) +- New `PUT /templates/quick-access` endpoint: validates and writes the JSON field +- Validation rules: + - Max 5 items + - No duplicate (type, id) pairs + - Each entry must have `type` in ("static", "user") and non-empty `id` + - For `type: "user"`, verify the template exists and belongs to the user +- Remove old preference CRUD endpoints that interact with `prompt_template_preference` collection +- Remove `PromptTemplatePreferenceOut` and `QuickAccessPreferenceIn` schemas + +**Frontend**: +- Update API client functions to use new endpoints +- Update hooks (`useQuickAccessPreferences` or equivalent) to work with the new JSON shape +- Add client-side dedup as a safety net before saving +- Remove `QuickAccessConfigurator.tsx` if unused + +**Directus field needed** (user to create manually): +- Collection: `directus_users` (or user settings collection -- confirm with user) +- Field name: `quick_access_preferences` +- Type: JSON +- Default: `[]` +- Nullable: true + +## 2. Community Code -- Full Removal + +### What to delete + +**Backend** (`server/dembrane/api/template.py`): +- Endpoints: `GET /community`, `GET /community/my-stars`, `POST /{id}/publish`, `POST /{id}/unpublish`, `POST /{id}/star`, `POST /{id}/copy`, `POST /ratings`, `DELETE /ratings/{id}`, `GET /ratings` +- Schemas: `CommunityTemplateOut`, `PublishTemplateIn`, `PromptTemplateRatingIn`, `PromptTemplateRatingOut`, `ALLOWED_TAGS` + +**Frontend**: +- Hook file: `frontend/src/components/chat/hooks/useCommunityTemplates.ts` (delete entire file) +- Community sections in `TemplatesModal.tsx` (community tab/list, publish/unpublish UI, star UI, copy UI) +- API client functions in `frontend/src/lib/api.ts` (community-related fetch/mutation functions) + +**Not deleted**: The `prompt_template_rating` and related Directus collections remain in the database (no destructive migration). They just become unused. + +## 3. Report Buttons -- Teal to Blue + +### Problem + +All primary action buttons in the report feature use `color="teal"`. The brand style guide specifies Royal Blue (#4169e1) for primary buttons. + +### Fix + +Change `color="teal"` to `color="blue"` in these 6 instances: + +1. `frontend/src/components/report/CreateReportForm.tsx` -- "Schedule Report" button +2. `frontend/src/components/report/CreateReportForm.tsx` -- "Generate now" button +3. `frontend/src/components/report/UpdateReportModalButton.tsx` -- "Update Report"/"New Report" trigger button +4. `frontend/src/components/report/UpdateReportModalButton.tsx` -- "Schedule Report" button +5. `frontend/src/components/report/UpdateReportModalButton.tsx` -- "Generate now" button +6. `frontend/src/routes/project/report/ProjectReportRoute.tsx` -- "Confirm reschedule" button + +Mantine's `color="blue"` maps to a blue range that aligns with Royal Blue. + +## 4. Anonymization UX + +### 4a. Participant Anonymization Notice (Recording Page) + +**Where**: The initial message/instruction area shown to participants before they start recording (in `ParticipantConversationAudio` and `ParticipantConversationText` or their shared parent). + +**When shown**: When the conversation's `is_anonymized` flag is true. + +**Content**: Muted text appended to the existing welcome/instruction content: +> "Your transcription will be anonymized and your host will not be able to listen to your recording." + +**Style**: +- Muted/dimmed text (e.g., `c="dimmed"`, smaller font size) +- Part of the existing instruction flow, not a separate banner or alert +- Should feel informational, not alarming + +**Translations**: All 6 languages (en-US, nl-NL, de-DE, fr-FR, es-ES, it-IT). + +**Data flow**: The `is_anonymized` field is already on the conversation object returned by the API. The participant components already have access to conversation data. + +### 4b. Host Confirmation Modal (Portal Editor) + +**Where**: `ProjectPortalEditor.tsx`, on the anonymize transcripts toggle. + +**When triggered**: Only when toggling from ON to OFF (not when turning ON). + +**Modal content**: +- Title: "Turn off anonymization?" +- Body: "Turning off anonymization while recordings are ongoing may have unintended consequences. Active conversations will also be affected mid-recording. Please use this with caution." +- Buttons: "Cancel" (default) and "Turn off" (destructive/red) + +**Behavior**: +- If user confirms: proceed with the toggle, save the setting +- If user cancels: revert the toggle, no change saved +- No modal when turning ON (enabling anonymization is always safe) + +## Out of Scope + +- Migration of existing `prompt_template_preference` data to new JSON format (old records can be ignored; users get fresh defaults) +- Delete the `prompt_template_preference` Directus collection (replaced by JSON field) +- Deleting `prompt_template_rating` Directus collection +- Changing other button colors outside the report feature diff --git a/echo/frontend/src/components/chat/ChatTemplatesMenu.tsx b/echo/frontend/src/components/chat/ChatTemplatesMenu.tsx index 7765791b..4fcd4a55 100644 --- a/echo/frontend/src/components/chat/ChatTemplatesMenu.tsx +++ b/echo/frontend/src/components/chat/ChatTemplatesMenu.tsx @@ -18,9 +18,8 @@ import { AnalyticsEvents as events } from "@/lib/analyticsEvents"; import type { ChatMode } from "@/lib/api"; import { testId } from "@/lib/testUtils"; import { MODE_COLORS } from "./ChatModeSelector"; -import type { QuickAccessItem } from "./QuickAccessConfigurator"; import { TemplatesModal } from "./TemplatesModal"; -import { decodeTemplateKey, encodeTemplateKey } from "./templateKey"; +import { type QuickAccessItem, decodeTemplateKey, encodeTemplateKey } from "./templateKey"; import { agenticQuickAccessTemplates, quickAccessTemplates, @@ -71,25 +70,12 @@ type ChatTemplatesMenuProps = { // AI suggestions toggle hideAiSuggestions?: boolean; onToggleAiSuggestions?: (hide: boolean) => void; - // Favorites - favoriteTemplateIds?: Set; - onToggleFavorite?: (promptTemplateId: string, isFavorited: boolean) => void; // External open control externalOpen?: boolean; onExternalClose?: () => void; // Save as template prefill saveAsTemplateContent?: string | null; onClearSaveAsTemplate?: () => void; - // Community publish context - userTemplateDetails?: Array<{ - id: string; - is_public: boolean; - star_count: number; - copied_from: string | null; - author_display_name: string | null; - }>; - defaultLanguage?: string; - userName?: string | null; }; // Reusable chip for both dynamic suggestions and pinned templates @@ -175,13 +161,8 @@ export const ChatTemplatesMenu = ({ isSavingQuickAccess = false, hideAiSuggestions = false, onToggleAiSuggestions, - favoriteTemplateIds = new Set(), - onToggleFavorite, externalOpen = false, onExternalClose, - userTemplateDetails = [], - defaultLanguage, - userName, saveAsTemplateContent, onClearSaveAsTemplate, }: ChatTemplatesMenuProps) => { @@ -398,11 +379,6 @@ export const ChatTemplatesMenu = ({ isSavingQuickAccess={isSavingQuickAccess} hideAiSuggestions={hideAiSuggestions} onToggleAiSuggestions={onToggleAiSuggestions} - favoriteTemplateIds={favoriteTemplateIds} - onToggleFavorite={onToggleFavorite} - userTemplateDetails={userTemplateDetails} - defaultLanguage={defaultLanguage} - userName={userName} saveAsTemplateContent={saveAsTemplateContent} onClearSaveAsTemplate={onClearSaveAsTemplate} /> diff --git a/echo/frontend/src/components/chat/CommunityTab.tsx b/echo/frontend/src/components/chat/CommunityTab.tsx deleted file mode 100644 index 928805dd..00000000 --- a/echo/frontend/src/components/chat/CommunityTab.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { t } from "@lingui/core/macro"; -import { Trans } from "@lingui/react/macro"; -import { - Badge, - Group, - ScrollArea, - Select, - Stack, - Text, -} from "@mantine/core"; -import { useDebouncedValue } from "@mantine/hooks"; -import { useState } from "react"; -import { CommunityTemplateCard } from "./CommunityTemplateCard"; -import { - useCommunityTemplates, - useCopyTemplate, - useMyCommunityStars, - useToggleStar, -} from "./hooks/useCommunityTemplates"; - -const ALLOWED_TAGS = [ - "Workshop", - "Interview", - "Focus Group", - "Meeting", - "Research", - "Community", - "Education", - "Analysis", -]; - -const getSortOptions = () => [ - { value: "newest", label: t`Newest` }, - { value: "most_starred", label: t`Most popular` }, - { value: "most_used", label: t`Most used` }, -]; - -type CommunityTabProps = { - searchQuery: string; -}; - -export const CommunityTab = ({ searchQuery }: CommunityTabProps) => { - const [selectedTag, setSelectedTag] = useState(null); - const [sortBy, setSortBy] = useState("newest"); - const [expandedId, setExpandedId] = useState(null); - const sortOptions = getSortOptions(); - - const [debouncedSearch] = useDebouncedValue(searchQuery, 300); - - const communityQuery = useCommunityTemplates({ - search: debouncedSearch || undefined, - tag: selectedTag ?? undefined, - sort: sortBy as "newest" | "most_starred" | "most_used", - }); - - const starsQuery = useMyCommunityStars(); - const toggleStarMutation = useToggleStar(); - const copyMutation = useCopyTemplate(); - - const starredIds = starsQuery.data ?? new Set(); - const templates = communityQuery.data ?? []; - - return ( - - {/* Filters row */} - - - - setSelectedTag(null)} - > - All - - {ALLOWED_TAGS.map((tag) => ( - - setSelectedTag(selectedTag === tag ? null : tag) - } - > - {tag} - - ))} - - -