{groupConfig.map((group) => {
// Get modules in this group that are present in currentModules
- const groupModules = group.modules.filter((module) =>
- currentModules.includes(module)
- );
+ // and don't have variant "hidden"
+ const groupModules = group.modules.filter((module) => {
+ if (!currentModules.includes(module)) return false;
+ if (!Object.hasOwn(records, module)) return true;
+ const moduleRecord = records[module];
+ if (moduleRecord?.variant === 'hidden') return false;
+ return true;
+ });
if (groupModules.length === 0) return null;
return (
diff --git a/src/pages/Plan/navigation/aside/modal/AddBlockModal.tsx b/src/pages/Plan/navigation/aside/modal/AddBlockModal.tsx
index 8c7fa1d83..9f2f232d8 100644
--- a/src/pages/Plan/navigation/aside/modal/AddBlockModal.tsx
+++ b/src/pages/Plan/navigation/aside/modal/AddBlockModal.tsx
@@ -26,15 +26,24 @@ const AddBlockModal = () => {
const { t } = useTranslation();
const { modalRef, setModalRef } = usePlanNavContext();
const { activeTab } = usePlanContext();
- const { currentModules } = useAppSelector((state) => state.planModules);
+ const { currentModules, records } = useAppSelector(
+ (state) => state.planModules
+ );
const groupConfig = MODULE_GROUPS[activeTab.name] || [];
// Build grouped items with enabled/disabled state
+ // Filter out modules with variant "hidden"
const groupedItems = groupConfig.map((group) => {
- const items = group.modules.map((module_type) => ({
- type: module_type as components['schemas']['Module']['type'],
- enabled: !currentModules.includes(module_type),
- }));
+ const items = group.modules
+ .filter((module_type) => {
+ // Hide modules with variant "hidden" from the add modal
+ const module = records[module_type];
+ return module?.variant !== 'hidden';
+ })
+ .map((module_type) => ({
+ type: module_type as components['schemas']['Module']['type'],
+ enabled: !currentModules.includes(module_type),
+ }));
return {
id: group.id,
title: group.title,
diff --git a/tests/api/plans/pid/_get/200_draft_mandatory_and_acn_hidden_personas_module.json b/tests/api/plans/pid/_get/200_draft_mandatory_and_acn_hidden_personas_module.json
new file mode 100644
index 000000000..82cbe0242
--- /dev/null
+++ b/tests/api/plans/pid/_get/200_draft_mandatory_and_acn_hidden_personas_module.json
@@ -0,0 +1,54 @@
+{
+ "config": {
+ "modules": [
+ {
+ "output": "My Plan",
+ "type": "title",
+ "variant": "default"
+ },
+ {
+ "output": {
+ "start": "2041-12-17T08:00:00.000Z"
+ },
+ "type": "dates",
+ "variant": "default"
+ },
+ {
+ "type": "acn_saver_personas",
+ "variant": "hidden",
+ "output": [
+ "ACN.PRAGMATICO DIGITALE",
+ "ACN.EMERGENTE ASPIRAZIONALE",
+ "ACN.SOCIALE COLLABORATIVO",
+ "ACN.INVESTITORE SOFISTICATO",
+ "ACN.CONSERVATORE PRUDENTE"
+ ]
+ },
+ {
+ "output": [
+ {
+ "description": "description kind bug",
+ "kind": "bug",
+ "title": "Search for bugs",
+ "id": "bug-1"
+ },
+ {
+ "description": "description kind video",
+ "kind": "video",
+ "title": "Think aloud",
+ "id": "video-1"
+ }
+ ],
+ "type": "tasks",
+ "variant": "default"
+ }
+ ]
+ },
+ "id": 13,
+ "project": {
+ "id": 90,
+ "name": "MyProject"
+ },
+ "status": "draft",
+ "workspace_id": 1
+}
diff --git a/tests/e2e/plan/modules/goal.spec.ts b/tests/e2e/plan/modules/goal.spec.ts
index 7ccd4b217..5aebdc5a2 100644
--- a/tests/e2e/plan/modules/goal.spec.ts
+++ b/tests/e2e/plan/modules/goal.spec.ts
@@ -54,6 +54,31 @@ test.describe('The title module defines the Plan title.', () => {
);
});
+ test('It should show the correct label', async () => {
+ await expect(goalModule.elements().moduleLabel()).toContainText(
+ planPage.i18n.t('__PLAN_PAGE_MODULE_GOAL_LABEL')
+ );
+ });
+
+ test('It should show the placeholder when the input is empty', async () => {
+ await goalModule.elements().moduleInput().click();
+ await goalModule.elements().moduleInput().press('Control+a');
+ await goalModule.elements().moduleInput().press('Backspace');
+ await expect(goalModule.elements().editorParagraph()).toHaveAttribute(
+ 'data-placeholder',
+ planPage.i18n.t('__PLAN_PAGE_MODULE_GOAL_PLACEHOLDER')
+ );
+ });
+
+ test('It should show the info button next to the label', async () => {
+ await expect(goalModule.elements().infoButton()).toBeVisible();
+ });
+
+ test('It should show a tooltip when hovering the info button', async () => {
+ await goalModule.elements().infoButton().hover();
+ await expect(goalModule.elements().tooltipTitle()).toBeVisible();
+ });
+
test('It should allow improving the goal with AI only when word count >= 4', async ({
page,
}) => {
diff --git a/tests/fixtures/pages/Plan/Module_goal.ts b/tests/fixtures/pages/Plan/Module_goal.ts
index 85b41c714..ed80d9d4b 100644
--- a/tests/fixtures/pages/Plan/Module_goal.ts
+++ b/tests/fixtures/pages/Plan/Module_goal.ts
@@ -19,6 +19,13 @@ export class GoalModule {
tab: () => this.page.getByTestId('setup-tab'),
moduleError: () => module.getByTestId('goal-error'),
moduleInput: () => module.locator('[role="textbox"]').first(),
+ moduleLabel: () => module.locator('label'),
+ infoButton: () => module.getByTestId('goal-info-button'),
+ tooltipTitle: () =>
+ this.page.getByText(
+ this.i18n.t('__PLAN_PAGE_MODULE_GOAL_TOOLTIP_TITLE')
+ ),
+ editorParagraph: () => module.locator('.ProseMirror p').first(),
aiButton: () =>
module.getByRole('button', {
name: this.i18n.t('GENERATE_WITH_AI_CTA_LABEL'),