Skip to content

Commit 146818c

Browse files
committed
#7048 Updated Epic plan
1 parent db706b1 commit 146818c

1 file changed

Lines changed: 24 additions & 63 deletions

File tree

apps/email/EPIC_PLAN.md

Lines changed: 24 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,98 +2,59 @@
22

33
This document outlines the plan for refactoring the `apps/email` application into a showcase for the Neo.mjs functional component architecture and multi-window capabilities.
44

5-
## Phase 1: Foundation and Basic Layout (Completed)
5+
## Architectural Milestones & Key Learnings
66

7-
**Goal:** Implement the main 3-pane layout as a functional `MainView` component and set it as the content of the existing classic `Viewport`.
7+
This epic has driven significant architectural improvements to the functional component system. For a full understanding of the current state, review these tickets:
88

9-
**Sub-Tasks:**
9+
- **[#ticket-functional-child-component-diffing.md](/.github/ticket-functional-child-component-diffing.md):** The most critical enhancement. We implemented a VDOM config diffing mechanism in `FunctionalBase` to prevent the re-creation of stateful child components (like stores). This allows for a truly declarative VDOM while preserving child state.
10+
- **[#ticket-functional-base-windowid-propagation.md](/.github/ticket-functional-base-windowid-propagation.md):** Fixed a crucial bug where the `windowId` was not being propagated to child components, which is essential for multi-window support and event handling.
11+
- **[#ticket-functional-recursive-config-diffing.md](/.github/ticket-functional-recursive-config-diffing.md):** A plan for a future enhancement to make the diffing logic recursive, allowing for deep, declarative control over nested component configurations.
1012

11-
1. **Create `view/MainView.mjs`:**
12-
- Used `defineComponent` to create a new functional component.
13-
- Implemented a flexbox-based 3-pane layout (Folders, Email List, Email Detail).
14-
2. **Update `view/Viewport.mjs`:**
15-
- Configured the `Viewport` with `layout: 'fit'`.
16-
- Replaced the old `TabContainer` with the new `MainView` component as its single item.
17-
3. **Cleanup:**
18-
- Removed the `stateProvider` from the `Viewport` as it is not currently needed.
13+
---
1914

20-
**Learnings & Decisions:**
15+
## Phase 1: Foundation and Basic Layout (Completed)
2116

22-
- **Interoperability:** Decided to keep the classic `Viewport` and embed the new functional `MainView` component within it. This is a pragmatic approach that leverages existing structures and showcases the interoperability between classic and functional components.
23-
- **Naming:** Renamed the main functional component from `Main.mjs` to `MainView.mjs` for better clarity and to align with the `mainView` config in `app.mjs`.
17+
**Goal:** Implement the main 3-pane layout as a functional `MainView` component and set it as the content of the existing classic `Viewport`.
2418

19+
**Learnings & Decisions:**
20+
- **Interoperability:** Kept the classic `Viewport` and embedded the new functional `MainView` component, showcasing seamless integration.
21+
- **Naming:** Renamed `Main.mjs` to `MainView.mjs` for clarity.
2522

2623
---
2724

2825
## Phase 2: Email List View (Completed)
2926

30-
**Goal:** Implement the email list pane using a Neo.mjs grid to display a list of emails.
31-
32-
**Sub-Tasks:**
33-
34-
1. **Create Mock Data:**
35-
- Populated the `apps/email/store/Emails.mjs` with hardcoded sample email data.
36-
2. **Integrate Grid:**
37-
- Replaced the "Email List" placeholder in `MainView.mjs` with a `Neo.grid.Container`.
38-
- Configured the grid to use the `Emails` store and defined the columns.
39-
3. **Styling & Layout:**
40-
- Wrapped the grid in a styled `div` to ensure correct flexbox layout.
41-
- Used the `wrapperStyle` config on the grid to control its internal dimensions, which is necessary for the grid's layout engine.
42-
4. **Enable Interoperability:**
43-
- Enhanced `functional.component.Base` to propagate the parent's `windowId` to all child components. This was a critical fix to ensure the classic grid component could function correctly when rendered inside our functional `MainView`.
27+
**Goal:** Implement the email list pane using a `Neo.grid.Container`.
4428

4529
**Learnings & Decisions:**
46-
47-
- **Complex Component Integration:** Integrating a complex classic component like `grid.Container` into a functional component requires more than just placing it in the VDOM. We must provide layout-critical styles (like `height` and `width`) via the component's specific config (`wrapperStyle`) for it to render correctly.
48-
- **`windowId` is Crucial:** The `windowId` must be manually propagated from functional parents to classic children. This is a fundamental requirement for interoperability and ensuring that events, theming, and other window-specific functionalities work correctly. This led to enhancing `functional.component.Base` and creating a dedicated ticket for it.
49-
50-
**Next Steps:**
51-
- Implement selection handling on the grid to prepare for the detail view.
52-
30+
- **Complex Component Integration:** Discovered that complex classic components require specific configs (e.g., `wrapperStyle`) to manage their own layout when nested inside functional components.
31+
- **Stateful Child Problem:** Uncovered the core issue of stateful children (stores, columns) being re-created on every parent render. This led directly to the architectural work on VDOM diffing.
5332

5433
---
5534

5635
## Phase 3: Email Detail View (Completed)
5736

5837
**Goal:** Display the content of a selected email from the grid.
59-
60-
**Sub-Tasks:**
61-
62-
1. **Grid Selection:**
63-
- Configured a `selection.RowModel` on the grid's `bodyConfig`.
64-
- Set `singleSelect: true` to allow only one row to be selected.
65-
2. **State Management:**
66-
- Used the `useConfig()` hook in `MainView` to create a `selectedEmail` state variable.
67-
3. **Event Handling:**
68-
- Added a `selectionChange` listener to the selection model.
69-
- The listener updates the `selectedEmail` state with the selected record.
70-
4. **Detail View:**
71-
- The "Email Details" pane now conditionally renders the `title`, `sender`, and `content` of the `selectedEmail`.
72-
- If no email is selected, it displays a placeholder message.
73-
74-
**Next Steps:**
75-
- Implement "Compose" functionality.
76-
38+
- Implemented a `selection.RowModel` on the grid and used a `useConfig` state variable (`selectedEmail`) to drive a conditional render of the detail pane.
7739

7840
---
7941

80-
## Phase 4: Compose Email Functionality
42+
## Phase 4: Compose Email Functionality (Next)
8143

8244
**Goal:** Implement the ability to compose a new email, initially within the main window.
8345

84-
**Potential Tools to Explore:**
85-
86-
- `src/dialog/Base.mjs`: To create a modal or non-modal dialog for the compose window.
87-
- Custom Functional Overlay: Build a new overlay component from scratch using functional components.
88-
89-
**Sub-Tasks:**
90-
*(To be defined)*
46+
**Proposed Plan:**
47+
1. **Compose Button:** Add a `Neo.button.Base` to the "Folders" pane.
48+
2. **State Management:** Use `useConfig` in `MainView` to manage an `isComposing` boolean state.
49+
3. **Compose View:** Create a new functional component, `view/ComposeView.mjs`, containing the form for the new email.
50+
4. **Conditional Rendering:** Use the `isComposing` flag to conditionally render the `ComposeView` as an overlay on top of the main view.
51+
5. **Event Handling:** The "Compose" button will set `isComposing` to `true`. The `ComposeView` will have a "Close" button that sets it back to `false`.
52+
6. **Overlay Implementation:** We will build a custom functional overlay for this, as it's a good exercise and provides maximum flexibility.
9153

9254
---
9355

9456
## Phase 5: Multi-Window Detach
9557

9658
**Goal:** Implement the "detach" functionality to move the compose view into a separate browser window.
59+
**Sub-Tasks:** *(To be defined)*
9760

98-
**Sub-Tasks:**
99-
*(To be defined)*

0 commit comments

Comments
 (0)