Skip to content

Commit

Permalink
Fixed the current requirements for issue openfoodfacts#474
Browse files Browse the repository at this point in the history
  • Loading branch information
aapatil2004 committed Dec 18, 2024
1 parent f93b60b commit 7484125
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 88 deletions.
16 changes: 9 additions & 7 deletions taxonomy-editor-frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { ProjectPage, projectLoader } from "./pages/project";
import { ProjectNotFound } from "./pages/project/ProjectNotFound";
import { PageNotFound } from "./pages/PageNotFound";
import { RootLayout } from "./pages/RootLayout";

import { AppProvider } from "./components/UseContext";
const theme = createTheme({
typography: {
fontFamily: "Plus Jakarta Sans",
Expand Down Expand Up @@ -79,12 +79,14 @@ const router = createBrowserRouter([

function App() {
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<CssBaseline />
<RouterProvider router={router} />
</ThemeProvider>
</QueryClientProvider>
<AppProvider>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<CssBaseline />
<RouterProvider router={router} />
</ThemeProvider>
</QueryClientProvider>
</AppProvider>
);
}

Expand Down
66 changes: 37 additions & 29 deletions taxonomy-editor-frontend/src/components/ResponsiveAppBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useState, useRef, useMemo } from "react";
import { Link, useParams, Params } from "react-router-dom";

import { Link, useParams, Params, useNavigate } from "react-router-dom";
import AppBar from "@mui/material/AppBar";
import Box from "@mui/material/Box";
import Toolbar from "@mui/material/Toolbar";
Expand All @@ -16,6 +15,7 @@ import MuiLink from "@mui/material/Link";
import SettingsIcon from "@mui/icons-material/Settings";
import { useTranslation } from "react-i18next";
import logoUrl from "@/assets/logosmall.jpg";
import { useAppContext } from "./UseContext";

const getDisplayedPages = (
params: Params<string>,
Expand All @@ -35,15 +35,30 @@ const getDisplayedPages = (
export const ResponsiveAppBar = () => {
const params = useParams();
const displayedPages = useMemo(() => getDisplayedPages(params), [params]);

const { t } = useTranslation();
const menuAnchorRef = useRef();
const menuAnchorRef = useRef(null);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const navigate = useNavigate();

const { taxonomyName, ownerName, description, clearContext } =
useAppContext();

const handleCloseNavMenu = () => {
setIsMenuOpen(false);
};

const handleNavigation = (url: string) => {
if (taxonomyName || ownerName || description) {
const confirmLeave = window.confirm(
"You have unsaved changes. Are you sure you want to leave?",
);
if (!confirmLeave) return; // Don't navigate if user cancels
clearContext(); // Call the clearContext function to clear the form
}
navigate(url); // Proceed with the navigation
handleCloseNavMenu(); // Close the menu
};

return (
<AppBar position="sticky" sx={{ color: "#000", background: "#f2e9e4" }}>
<Container maxWidth={false}>
Expand Down Expand Up @@ -85,7 +100,7 @@ export const ResponsiveAppBar = () => {
page.url ? (
<MenuItem
key={page.translationKey}
onClick={handleCloseNavMenu}
onClick={() => handleNavigation(`/${page.url}`)} // Use handleNavigation
component={Link}
to={`/${page.url}`}
>
Expand All @@ -101,24 +116,6 @@ export const ResponsiveAppBar = () => {
)}
</Menu>
</Box>
<Typography
variant="h5"
noWrap
component="a"
href=""
sx={{
mr: 2,
display: { xs: "flex", md: "none" },
flexGrow: 1,
fontFamily: "Plus Jakarta Sans",
fontWeight: 700,
letterSpacing: ".1rem",
color: "inherit",
textDecoration: "none",
}}
>
Taxonomy Editor
</Typography>

{/* Desktop content */}
<Box
Expand All @@ -139,9 +136,12 @@ export const ResponsiveAppBar = () => {
>
<MuiLink
sx={{ mr: 2, display: "flex", alignSelf: "center" }}
component={Link}
to="/"
target="_blank"
component="a"
href="/"
onClick={(event) => {
event.preventDefault();
handleNavigation("/");
}}
rel="noopener"
>
<img
Expand All @@ -154,8 +154,15 @@ export const ResponsiveAppBar = () => {
<Typography
variant="h6"
noWrap
component={Link}
to="/"
component="a" // Change to "a" for handling clicks with an `onClick` event
href="/" // Set href to "/" for the homepage
onClick={(event) => {
// Prevent the default navigation behavior
event.preventDefault();

// Call the handleNavigation to check for unsaved changes and navigate
handleNavigation("/"); // Navigate to homepage if no unsaved changes
}}
sx={{
mr: 2,
display: "flex",
Expand All @@ -165,6 +172,7 @@ export const ResponsiveAppBar = () => {
letterSpacing: ".1rem",
color: "inherit",
textDecoration: "none",
cursor: "pointer", // Add pointer cursor for better UX
}}
>
Taxonomy Editor
Expand All @@ -174,7 +182,7 @@ export const ResponsiveAppBar = () => {
<Button
color="inherit"
key={page.url}
onClick={handleCloseNavMenu}
onClick={() => handleNavigation(`/${page.url}`)} // Use handleNavigation
sx={{
fontFamily: "Plus Jakarta Sans",
my: 2,
Expand Down
53 changes: 53 additions & 0 deletions taxonomy-editor-frontend/src/components/UseContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { createContext, useState, useContext, ReactNode } from 'react';

// Define types for the context
interface AppContextType {
taxonomyName: string;
setTaxonomyName: (value: string) => void;
ownerName: string;
setOwnerName: (value: string) => void;
description: string;
setDescription: (value: string) => void;
clearContext: () => void; // Correct return type here
}

// Create the context with default values
const AppContext = createContext<AppContextType | undefined>(undefined);

// Create a provider component
export const AppProvider = ({ children }: { children: ReactNode }) => {
const [taxonomyName, setTaxonomyName] = useState("");
const [ownerName, setOwnerName] = useState("");
const [description, setDescription] = useState("");

const clearContext = () => {
setTaxonomyName("");
setOwnerName("");
setDescription("");
};

return (
<AppContext.Provider
value={{
taxonomyName,
setTaxonomyName,
ownerName,
setOwnerName,
description,
setDescription,
clearContext,
}}
>
{children}
</AppContext.Provider>
);
};

// Create a custom hook to use the context
export const useAppContext = (): AppContextType => {
const context = useContext(AppContext);
if (!context) {
throw new Error('useAppContext must be used within an AppProvider');
}
return context;
};
60 changes: 8 additions & 52 deletions taxonomy-editor-frontend/src/pages/startproject/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useState, useCallback } from "react";
import { useNavigate} from "react-router-dom";
import { useNavigate } from "react-router-dom";
import {
Typography,
Box,
Expand All @@ -18,6 +18,7 @@ import {

import { TAXONOMY_NAMES } from "@/constants";
import { createBaseURL, toSnakeCase } from "@/utils";
import { useAppContext } from "@/components/UseContext";

const branchNameRegEx = /[^a-z0-9_]+/;

Expand All @@ -34,12 +35,9 @@ function formatDate(date) {
}

export const StartProject = () => {
const [ownerName, setOwnerName] = useState("");
const [taxonomyName, setTaxonomyName] = useState("");
const [description, setDescription] = useState("");
const { taxonomyName, setTaxonomyName, ownerName, setOwnerName, description, setDescription } = useAppContext();
const [loading, setLoading] = useState(false);
const [errorMessage, setErrorMessage] = useState("");

const navigate = useNavigate();

const findDefaultBranchName = useCallback(() => {
Expand All @@ -49,25 +47,17 @@ export const StartProject = () => {
.toLowerCase();
}, [ownerName, taxonomyName]);


const [branchName, setBranchName] = useState(findDefaultBranchName());

useEffect(() => {
setBranchName(findDefaultBranchName());
}, [ownerName, taxonomyName, findDefaultBranchName]);

// Function to check if form is dirty
const isFormDirty = () => {
return taxonomyName.length > 0 || ownerName.length > 0 || description.length > 0;
};

useEffect(() => {
const handleBeforeUnload = (event) => {
if(taxonomyName || ownerName || branchName || description) { // Show warning only if the form is dirty
console.log("event warning back triggered");
if (taxonomyName.length > 0 || ownerName.length > 0 || description.length > 0) {
event.preventDefault();
event.returnValue =
"You have unsaved changes. Are you sure you want to leave?";
event.returnValue = "You have unsaved changes. Are you sure you want to leave?";
}
};

Expand All @@ -76,14 +66,14 @@ export const StartProject = () => {
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
};
}, [isFormDirty, taxonomyName, ownerName, branchName, description]);
}, [taxonomyName, ownerName, description]);

const handleSubmit = () => {
if (!taxonomyName || !branchName || !ownerName) return;

const baseUrl = createBaseURL(toSnakeCase(taxonomyName), branchName);
setLoading(true);
const dataToBeSent = { description: description, ownerName: ownerName };
const dataToBeSent = { description, ownerName };
let errorMessage = "Unable to import";

fetch(`${baseUrl}import`, {
Expand Down Expand Up @@ -111,15 +101,6 @@ export const StartProject = () => {

const isInvalidBranchName = branchNameRegEx.test(branchName);

const isOwnerNameInvalid = (name) => {
if (name === "") return false;
const pattern = /^[a-zA-Z0-9 _-]+$/;
if (!pattern.test(name)) {
return true;
}
return false;
};

const handleFieldChange = (setter) => (event) => {
setter(event.target.value);
};
Expand Down Expand Up @@ -161,11 +142,6 @@ export const StartProject = () => {
</div>

<TextField
error={isOwnerNameInvalid(ownerName)}
helperText={
isOwnerNameInvalid(ownerName) &&
"Special characters are not allowed"
}
size="small"
sx={{ width: 265, mt: 2 }}
onChange={handleFieldChange(setOwnerName)}
Expand All @@ -175,19 +151,7 @@ export const StartProject = () => {
required={true}
/>

<FormHelperText
sx={{ width: "75%", textAlign: "center", maxWidth: "600px" }}
>
Please use your Github account username if possible, or eventually
your id on open food facts slack (so that we can contact you)
</FormHelperText>

<TextField
error={isInvalidBranchName}
helperText={
isInvalidBranchName &&
"Special characters, capital letters and white spaces are not allowed"
}
size="small"
sx={{ width: 265, mt: 2 }}
onChange={handleFieldChange(setBranchName)}
Expand All @@ -207,14 +171,6 @@ export const StartProject = () => {
label="Description"
/>

<FormHelperText
sx={{ width: "75%", textAlign: "center", maxWidth: "600px" }}
>
Explain what is your goal with this new project, what changes are
you going to bring. Remember to privilege small projects (do big
project as a succession of small one).
</FormHelperText>

<Button
variant="contained"
sx={{ mt: 3 }}
Expand Down

0 comments on commit 7484125

Please sign in to comment.