Frontend State Management
Relevant source files
The following files were used as context for generating this wiki page:
- apps/portal/app/store/auth/reducers/AuthReducer.ts
- apps/portal/app/store/panel/reducers/PanelReducer.ts
- apps/extensions/src/app/store/auth/actions/AuthAC.ts
- apps/portal/pages/media/workspace/[workspaceId]/settings/index.tsx
- apps/extensions/src/content/panel/hooks/useFetchWorkspacesData.ts
- apps/portal/pages/media/whiteboards.tsx
- apps/extensions/src/app/services/general.ts
- apps/extensions/src/content/panel/components/containers/dashboardLayout/elements/Sidebar/Sidebar.tsx
The ever-rec project utilizes Redux for robust and centralized state management across its frontend applications, including the portal and extensions. This approach provides a single source of truth, making the application state predictable, easier to debug, and maintain. The state is divided into logical slices, primarily auth, panel, and whiteboard, each managed by its own set of actions and reducers.
Components interact with the Redux store using react-redux hooks (useSelector to access state and useDispatch to trigger state changes). This ensures a unidirectional data flow, which is fundamental to the Redux architecture and contributes to the stability of the applications.
Core Architecture
The state management is built on the standard Redux pattern. Both the portal and extensions applications rely on redux and react-redux as core dependencies for managing application-wide state.
This diagram illustrates the fundamental Redux data flow within the application.
State Slices
The global state is organized into several slices, each responsible for a specific domain of the application.
Authentication State (auth)
This slice manages all user-related data, including authentication status, user profile information, and details of third-party integrations like Trello and Jira.
The auth state is primarily modified by actions defined in AuthAC.ts and handled by the AuthReducer.
State Structure
| Property | Type | Description |
|---|---|---|
user | IUser | Contains the authenticated user's profile data. |
isLoggedIn | boolean | Flag indicating if a user is currently logged in. |
loading | boolean | Flag for indicating loading states during authentication processes. |
Sources: apps/extensions/src/app/store/auth/actions/AuthAC.ts, apps/extensions/src/app/services/general.ts:28-36
Key Actions
| Action Type | Payload | Description |
|---|---|---|
SET_USER | { user: IUser } | Sets the authenticated user object in the state. |
SET_LOGGED_IN | { isLoggedIn: boolean } | Updates the login status. |
SET_LOADING | { loading: boolean } | Toggles the authentication loading state. |
SET_TRELLO_USER | { payload: { isIntegrated: boolean, email: string } } | Updates the user's Trello integration status and email. |
REMOVE_JIRA_USER | { user: IUser } | Removes Jira integration data from the user object. |
REMOVE_DROPBOX_USER | { user: IUser } | Removes Dropbox integration data from the user object. |
Sources: apps/extensions/src/app/store/auth/actions/AuthAC.ts:4-21, apps/extensions/src/app/services/general.ts:28-68
Trello Integration Flow
The following sequence diagram shows how the application handles connecting a Trello account and updating the auth state.
Panel State (panel)
The panel slice is responsible for managing the state of the main dashboard UI in both the portal and extensions. This includes data for file explorers (images/videos), workspace information, and other UI-specific flags.
State Structure
| Property | Type | Description |
|---|---|---|
workspaces | IWorkspace[] | A list of all workspaces the user is a member of. |
activeWorkspace | IWorkspace | The currently selected workspace. |
workspaceLoaded | boolean | A flag to indicate if the active workspace data has been fully loaded. |
explorerData | object | Data for the image file explorer. |
explorerDataVideos | object | Data for the video file explorer. |
jiraProjectData | any[] | Data related to Jira projects for integration purposes. |
trelloData | any[] | Data related to Trello boards for integration purposes. |
blobUrls | string[] | URLs of recorded video blobs before they are processed. |
videoDuration | number | The duration of a recorded video. |
Sources: apps/portal/app/store/panel/reducers/PanelReducer.ts, apps/extensions/src/content/panel/hooks/useFetchWorkspacesData.ts:14-22, apps/extensions/src/content/panel/hooks/useManageVideoData.ts:20-26
Key Actions
| Action Type | Payload | Description |
|---|---|---|
SET_WORKSPACES | { workspaces: IWorkspace[] } | Sets the list of user workspaces. |
SET_ACTIVE_WORKSPACE | { activeWorkspace: IWorkspace } | Sets the currently active workspace. |
SET_WORKSPACE_LOADED | { workspaceLoaded: boolean } | Updates the loading status for workspace data. |
SET_JIRA_PROJECT_DATA | { data: any[] } | Stores Jira project data fetched from the API. |
SET_TRELLO_DATA | { data: any[] } | Stores Trello board data fetched from the API. |
Sources: apps/portal/pages/media/workspace/[workspaceId]/settings/index.tsx:70-84, apps/extensions/src/content/panel/hooks/useFetchWorkspacesData.ts:60-65, apps/extensions/src/app/services/general.ts:93-111
Workspace Rename Flow
This diagram shows the process of renaming a workspace, from the user action to the final state update.
Whiteboard State (whiteboard)
This slice manages the state for the whiteboards feature, including the list of whiteboards and loading indicators.
State Structure & Actions
The whiteboard state is managed through actions dispatched from components like WhiteboardsScreen.
- State Properties:
whiteboards:IWhiteboard[]- List of user's whiteboards.loading:boolean- Loading state for whiteboard operations.
- Key Actions:
setWhiteboards: Populates the list of whiteboards.addWhiteboard: Adds a newly created whiteboard to the list.setLoading: Toggles the loading state.
The createWhiteboardHandler function demonstrates this flow by dispatching WhiteboardAC.addWhiteboard after a successful API call.
Sources: apps/portal/pages/media/whiteboards.tsx:11-17, 30-36, 40-42
Component Integration
Components access and manipulate the Redux store using hooks from the react-redux library.
useSelector((state) => state.slice.property)is used to subscribe to store updates and read state values.useDispatch()returns the store's dispatch function, allowing components to trigger state changes by dispatching actions.
Example: Fetching and Displaying Workspaces
The useFetchWorkspacesData hook demonstrates how to fetch data and populate the Redux store.
- It uses
useSelectorto check ifworkspacesalready exist in thepanelstate. - If not, it calls
getUserWorkspacesAPI. - On a successful response, it dispatches
PanelAC.setWorkspacesto update the store.
// apps/extensions/src/content/panel/hooks/useFetchWorkspacesData.ts
const workspaces = useSelector(
(state: RootStateOrAny) => state.panel.workspaces,
);
// ...
const fetchWorkspaces = async () => {
if (!workspaces || workspaces.length === 0) {
const response = await getUserWorkspacesAPI();
if (response.status !== ResStatusEnum.error) {
dispatch(
PanelAC.setWorkspaces({
workspaces: response.data as IWorkspace[],
}),
);
}
}
};
Sources: apps/extensions/src/content/panel/hooks/useFetchWorkspacesData.ts:20-22, 60-72
Example: Resetting Active Workspace
In the Sidebar component, clicking a main menu item dispatches an action to reset the active workspace, ensuring a clean state when navigating away from a workspace-specific view.
// apps/extensions/src/content/panel/components/containers/dashboardLayout/elements/Sidebar/Sidebar.tsx
const sidebarItemClicked = async (item: IMainMenuItem) => {
if (item.type !== 'favFolders' && !item?.isWorkspaceRoute) {
dispatch(PanelAC.setActiveWorkspace({ activeWorkspace: null }));
}
// ...
};