Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance comments in Redux Store configuration for clarity on Persistence and Volatile slices #425

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions frontend/src/components/editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useFormatUtils } from "../../hooks/useFormatUtils";
import { useToolBar } from "../../hooks/useToolBar";
import { CodeKeyType, selectConfig } from "../../store/configSlice";
import { selectEditor, setCmView } from "../../store/editorSlice";
import { selectSetting } from "../../store/settingSlice";
import { selectFeatureSetting } from "../../store/featureSettingSlice";
import { selectWorkspace } from "../../store/workspaceSlice";
import { imageUploader } from "../../utils/imageUploader";
import { intelligencePivot } from "../../utils/intelligence/intelligencePivot";
Expand All @@ -34,7 +34,7 @@ function Editor(props: EditorProps) {
const [element, setElement] = useState<HTMLElement>();
const editorStore = useSelector(selectEditor);
const configStore = useSelector(selectConfig);
const settingStore = useSelector(selectSetting);
const featureSettingStore = useSelector(selectFeatureSetting);
const workspaceStore = useSelector(selectWorkspace);
const { mutateAsync: createUploadUrl } = useCreateUploadUrlMutation();
const { mutateAsync: uploadFile } = useUploadFileMutation();
Expand All @@ -51,7 +51,7 @@ function Editor(props: EditorProps) {
!element ||
!editorStore.doc ||
!editorStore.client ||
typeof settingStore.fileUpload?.enable !== "boolean"
typeof featureSettingStore.fileUpload?.enable !== "boolean"
) {
return;
}
Expand Down Expand Up @@ -87,7 +87,7 @@ function Editor(props: EditorProps) {
}),
yorkieCodeMirror(editorStore.doc, editorStore.client),
intelligencePivot,
...(settingStore.fileUpload.enable
...(featureSettingStore.fileUpload.enable
? [imageUploader(handleUploadImage, editorStore.doc)]
: []),
urlHyperlinkInserter(editorStore.doc),
Expand All @@ -107,7 +107,7 @@ function Editor(props: EditorProps) {
configStore.codeKey,
themeMode,
workspaceStore.data,
settingStore.fileUpload?.enable,
featureSettingStore.fileUpload?.enable,
dispatch,
createUploadUrl,
uploadFile,
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/editor/YorkieIntelligence.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { Button, Typography } from "@mui/material";
import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { useSelector } from "react-redux";
import { INTELLIGENCE_FOOTER_ID } from "../../constants/intelligence";
import { selectFeatureSetting } from "../../store/featureSettingSlice";
import YorkieIntelligenceFooter from "./YorkieIntelligenceFooter";
import { useSelector } from "react-redux";
import { selectSetting } from "../../store/settingSlice";

function YorkieIntelligence() {
const [footerOpen, setFooterOpen] = useState(false);
const [intelligenceFooterPivot, setIntelligenceFooterPivot] = useState<Element | null>(null);

const { yorkieIntelligence } = useSelector(selectSetting);
const { yorkieIntelligence } = useSelector(selectFeatureSetting);

useEffect(() => {
// initialize intelligence footer pivot
Expand Down
18 changes: 11 additions & 7 deletions frontend/src/components/editor/YorkieIntelligenceFeatureList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,28 @@ import {
Stack,
TextField,
} from "@mui/material";
import { useMemo, useState } from "react";
import { matchSorter } from "match-sorter";
import { selectSetting } from "../../store/settingSlice";
import { useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { selectFeatureSetting } from "../../store/featureSettingSlice";

interface YorkieIntelligenceFeatureListProps {
onSelectFeature: (feature: string, title: string) => void;
}

function YorkieIntelligenceFeatureList(props: YorkieIntelligenceFeatureListProps) {
const { onSelectFeature } = props;
const settingStore = useSelector(selectSetting);
const featureSettingStore = useSelector(selectFeatureSetting);
const [featureText, setFeatureText] = useState("");
const filteredFeatureInfoList = useMemo(() => {
return matchSorter(settingStore.yorkieIntelligence?.config.features ?? [], featureText, {
keys: ["title", "feature"],
});
}, [featureText, settingStore.yorkieIntelligence?.config.features]);
return matchSorter(
featureSettingStore.yorkieIntelligence?.config.features ?? [],
featureText,
{
keys: ["title", "feature"],
}
);
}, [featureText, featureSettingStore.yorkieIntelligence?.config.features]);

const handleFeatureTextChange: React.ChangeEventHandler<
HTMLInputElement | HTMLTextAreaElement
Expand Down
18 changes: 9 additions & 9 deletions frontend/src/components/headers/DocumentHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
import EditIcon from "@mui/icons-material/Edit";
import MoreVertIcon from "@mui/icons-material/MoreVert";
import VerticalSplitIcon from "@mui/icons-material/VerticalSplit";
import VisibilityIcon from "@mui/icons-material/Visibility";
import {
AppBar,
Grid2 as Grid,
IconButton,
Paper,
Stack,
ToggleButton,
ToggleButtonGroup,
Toolbar,
Tooltip,
Grid2 as Grid,
Typography,
} from "@mui/material";
import { useSnackbar } from "notistack";
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { useUpdateDocumentTitleMutation } from "../../hooks/api/workspaceDocument";
import { useUserPresence } from "../../hooks/useUserPresence";
import { selectDocument } from "../../store/documentSlice";
import { EditorModeType, selectEditor, setMode } from "../../store/editorSlice";
import { selectWorkspace } from "../../store/workspaceSlice";
import { ShareRole } from "../../utils/share";
import DownloadMenu from "../common/DownloadMenu";
import ShareButton from "../common/ShareButton";
import UserPresenceList from "./UserPresenceList";
import { selectDocument } from "../../store/documentSlice";
import { useUpdateDocumentTitleMutation } from "../../hooks/api/workspaceDocument";
import { useSnackbar } from "notistack";
import DocumentPopover from "../popovers/DocumentPopover";
import MoreVertIcon from "@mui/icons-material/MoreVert";
import UserPresenceList from "./UserPresenceList";

function DocumentHeader() {
const dispatch = useDispatch();
Expand All @@ -43,7 +43,7 @@ function DocumentHeader() {
);
const isEditingDisabled = Boolean(editorState.shareRole);
const { enqueueSnackbar } = useSnackbar();
const [moreButtonanchorEl, setMoreButtonAnchorEl] = useState<HTMLButtonElement | null>(null);
const [moreButtonAnchorEl, setMoreButtonAnchorEl] = useState<HTMLButtonElement | null>(null);

useEffect(() => {
if (editorState.shareRole === ShareRole.READ) {
Expand Down Expand Up @@ -162,8 +162,8 @@ function DocumentHeader() {
<MoreVertIcon />
</IconButton>
<DocumentPopover
open={Boolean(moreButtonanchorEl)}
anchorEl={moreButtonanchorEl}
open={Boolean(moreButtonAnchorEl)}
anchorEl={moreButtonAnchorEl}
onClose={handleDocumentMenuClose}
/>
</Stack>
Expand Down
16 changes: 11 additions & 5 deletions frontend/src/hooks/api/settings.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { GetSettingsResponse } from "./types/settings";
import { useDispatch, useSelector } from "react-redux";
import { selectSetting, setFileUpload, setYorkieIntelligence } from "../../store/settingSlice";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
selectFeatureSetting,
setFileUpload,
setYorkieIntelligence,
} from "../../store/featureSettingSlice";
import { GetSettingsResponse } from "./types/settings";

export const generateGetSettingsQueryKey = () => {
return ["settings"];
};

export const useGetSettingsQuery = () => {
const dispatch = useDispatch();
const settingStore = useSelector(selectSetting);
const featureSettingStore = useSelector(selectFeatureSetting);
const query = useQuery({
queryKey: generateGetSettingsQueryKey(),
enabled: settingStore.yorkieIntelligence === null && settingStore.fileUpload === null,
enabled:
featureSettingStore.yorkieIntelligence === null &&
featureSettingStore.fileUpload === null,
queryFn: async () => {
const res = await axios.get<GetSettingsResponse>("/settings");
return res.data;
Expand Down
13 changes: 5 additions & 8 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import { SnackbarProvider } from "notistack";
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { store } from "./store/store";
import ReactGA from "react-ga4";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { persistStore } from "redux-persist";
import { SnackbarProvider } from "notistack";
import ReactGA from "react-ga4";
import App from "./App";
import "./index.css";
import { persistor, store } from "./store/store";

const trackingCode = `${import.meta.env.VITE_APP_GOOGLE_ANALYTICS}`;
if (trackingCode) {
ReactGA.initialize(trackingCode);
}

const persistor = persistStore(store);

ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<Provider store={store}>
Expand Down
11 changes: 10 additions & 1 deletion frontend/src/store/authSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,13 @@ export const { setAccessToken, setRefreshToken, logout } = authSlice.actions;

export const selectAuth = (state: RootState) => state.auth;

export default authSlice.reducer;
/**
* Manages user authentication state, including login information and tokens.
*
* * This slice handles:
* - `accessToken`: The user's access token for authenticated API requests.
* - `refreshToken`: The user's refresh token for obtaining new access tokens.
*/
const reducer = authSlice.reducer;

export default reducer;
13 changes: 12 additions & 1 deletion frontend/src/store/configSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,15 @@ export const { setTheme, setDrawerOpen, setCodeKeyType, setDisableScrollSync } =

export const selectConfig = (state: RootState) => state.config;

export default configSlice.reducer;
/**
* Handles global application settings.
*
* * This slice handles:
* - `theme`: The application theme (default, dark, or light).
* - `drawerOpen`: Whether the application drawer (sidebar) is open.
* - `codeKey`: The preferred keybinding type for code editing (Sublime, Vim, etc.).
* - `disableScrollSync`: A flag to enable or disable scroll synchronization.
*/
const reducer = configSlice.reducer;

export default reducer;
12 changes: 9 additions & 3 deletions frontend/src/store/documentSlice.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createSlice } from "@reduxjs/toolkit";
import type { PayloadAction } from "@reduxjs/toolkit";
import { createSlice } from "@reduxjs/toolkit";
import { RootState } from "./store";

export interface Document {
Expand All @@ -20,7 +20,7 @@ const initialState: DocumentState = {
data: null,
};

export const documentSlice = createSlice({
const documentSlice = createSlice({
name: "document",
initialState,
reducers: {
Expand All @@ -34,4 +34,10 @@ export const { setDocumentData } = documentSlice.actions;

export const selectDocument = (state: RootState) => state.document;

export default documentSlice.reducer;
/**
* Handles document management state.
* This slice is designed to manage the currently active document, its metadata, and related state in the application.
*/
const reducer = documentSlice.reducer;

export default reducer;
14 changes: 13 additions & 1 deletion frontend/src/store/editorSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,16 @@ export const { setMode, setShareRole, setDoc, setClient, setCmView } = editorSli

export const selectEditor = (state: RootState) => state.editor;

export default editorSlice.reducer;
/**
* Manages the state of the collaborative code editor
*
* * This slice handles:
* - `mode`: The editor's current mode (edit, read, or both).
* - `shareRole`: The user's role in the session (e.g., viewer, editor).
* - `doc`: The Yorkie document for real-time collaboration.
* - `client`: The Yorkie client for syncing data with the server.
* - `cmView`: The CodeMirror editor instance.
*/
const reducer = editorSlice.reducer;

export default reducer;
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ interface FileUploadSetting {
enable: boolean;
}

export interface SettingState {
export interface FeatureSettingState {
yorkieIntelligence: YorkieIntelligenceSetting | null;
fileUpload: FileUploadSetting | null;
}

const initialState: SettingState = {
const initialState: FeatureSettingState = {
yorkieIntelligence: null,
fileUpload: null,
};

export const settingSlice = createSlice({
name: "setting",
export const featureSettingSlice = createSlice({
name: "featureSetting",
initialState,
reducers: {
setYorkieIntelligence: (state, action: PayloadAction<YorkieIntelligenceSetting>) => {
Expand All @@ -40,8 +40,17 @@ export const settingSlice = createSlice({
},
});

export const { setYorkieIntelligence, setFileUpload } = settingSlice.actions;
export const { setYorkieIntelligence, setFileUpload } = featureSettingSlice.actions;

export const selectSetting = (state: RootState) => state.setting;
export const selectFeatureSetting = (state: RootState) => state.featureSetting;

export default settingSlice.reducer;
/**
* Manages settings for specific features (e.g., experimental feature toggles).
*
* * This slice handles:
* - `yorkieIntelligence`: Settings for the Yorkie Intelligence feature
* - `fileUpload`: Settings for file upload functionality
*/
const reducer = featureSettingSlice.reducer;

export default reducer;
Loading
Loading