CoolFace
Apppublic

bunkalab/Argilla-Prompt-Exploration

sourceHugging Faceupdated 3y agoView on Hugging Face
5likes
UploadFileContext.jsx220 linesDownload Raw Back to src
1import { Alert, Box, Typography, Backdrop } from "@mui/material";2import CircularProgress from '@mui/material/CircularProgress';3import axios from "axios";4import PropTypes from "prop-types";5import React, { createContext, useCallback, useEffect, useMemo, useState } from "react";6 7// Create the Context8export const TopicsContext = createContext();9 10const { REACT_APP_API_ENDPOINT } = process.env;11 12const TOPICS_ENDPOINT_PATH = `${REACT_APP_API_ENDPOINT}/topics/csv/`;13const BOURDIEU_ENDPOINT_PATH = `${REACT_APP_API_ENDPOINT}/bourdieu/csv/`;14const REFRESH_BOURDIEU_ENDPOINT_PATH = `${REACT_APP_API_ENDPOINT}/bourdieu/refresh/`;15 16// Fetcher functions17const postForm = (url, data) =>18  axios19    .post(url, data, {20      headers: {21        "Content-Type": "multipart/form-data",22      },23    })24    .then((res) => res.data);25 26const postJson = (url, data) =>27  axios28    .post(url, data, {29      headers: {30        "Content-Type": "application/json",31      },32    })33    .then((res) => res.data);34 35// Provider Component36export function TopicsProvider({ children, onSelectView, selectedView }) {37  const [isLoading, setIsLoading] = useState(false);38  const [data, setData] = useState();39  const [bourdieuData, setBourdieuData] = useState();40  const [error, setError] = useState();41  const [errorText, setErrorText] = useState("");42  const [taskProgress, setTaskProgress] = useState(0); // TODO Add state for task progress when the backend is ready43  const [taskID, setTaskID] = useState(null); // Add state for task ID44  const [currentDatasetId, setCurrentDatasetId] = useState(null); // Current Dataset Id equals Task Id for the moment45 46  const monitorTaskProgress = async (selectedView, taskId) => {47    const evtSource = new EventSource(`${REACT_APP_API_ENDPOINT}/tasks/${selectedView === "map" ? "topics" : "bourdieu"}/${taskId}/progress`);48    evtSource.onmessage = function (event) {49      try {50        const data = JSON.parse(event.data);51        const progress = !isNaN(Math.ceil(data.progress)) ? Math.ceil(data.progress) : 0;52        console.log("Task Progress:", progress);53        setTaskProgress(progress); // Update progress in state54        if (data.state === "SUCCESS") {55          if (selectedView === "map") {56            setData({57              docs: data.result.docs,58              topics: data.result.topics59            });60            setBourdieuData(data.result.bourdieu_response);61          } else if (selectedView === "bourdieu") {62            setBourdieuData(data.result);63          }64          setTaskProgress(100);65          evtSource.close();66          setIsLoading(false);67          setTaskID(null);68          if (onSelectView) onSelectView(selectedView);69        } else if (data.state === "FAILURE") {70          setError(data.error);71          setTaskProgress(0);72          evtSource.close();73          setIsLoading(false);74          evtSource.close();75        }76      } catch (error) {77        console.error("EventSource exception");78        console.error(error);79        setError(error);80        evtSource.close();81        setIsLoading(false);82      }83    };84  };85 86  // Handle File Upload and POST Request87  const uploadFile = useCallback(88    async (file, params) => {89      setIsLoading(true);90      setErrorText("");91      const { nClusters, selectedColumn, selectedView, xLeftWord, xRightWord, yTopWord, yBottomWord, radiusSize } = params;92      const { nameLength, language, cleanTopics, minCountTerms } = params;93 94      try {95        // Generate SHA-256 hash of the file96        const formData = new FormData();97        formData.append("file", file);98        formData.append("selected_column", selectedColumn);99        formData.append("n_clusters", nClusters);100        formData.append("name_length", nameLength);101        formData.append("language", language);102        formData.append("clean_topics", cleanTopics);103        formData.append("min_count_terms", minCountTerms);104        // Append bourdieu parameters, processing activated by defaut105        formData.append("process_bourdieu", true);106        formData.append("x_left_words", xLeftWord);107        formData.append("x_right_words", xRightWord);108        formData.append("y_top_words", yTopWord);109        formData.append("y_bottom_words", yBottomWord);110        formData.append("radius_size", radiusSize);111 112        const apiURI = `${selectedView === "map" ? TOPICS_ENDPOINT_PATH : BOURDIEU_ENDPOINT_PATH}`;113        // Perform the POST request114        const response = await postForm(apiURI, formData);115        setTaskID(response.task_id);116        setCurrentDatasetId(response.task_id);117        await monitorTaskProgress(selectedView, response.task_id); // Start monitoring task progress118      } catch (errorExc) {119        // Handle error120        setError(errorExc);121        setTaskID(null);122        setCurrentDatasetId(null);123      } finally {124        setIsLoading(false);125      }126    },127    [monitorTaskProgress],128  );129 130  const refreshBourdieuQuery = useCallback(131    async (params) => {132      setIsLoading(true);133      setErrorText("");134      if (currentDatasetId !== null) {135        try {136          const apiURI = `${REFRESH_BOURDIEU_ENDPOINT_PATH}${currentDatasetId}`;137          // Perform the POST request138          const response = await postJson(apiURI, params);139          setBourdieuData(response);140        } catch (errorExc) {141          // Handle error142          setError(errorExc);143        } finally {144          setIsLoading(false);145        }146      } else {147        setIsLoading(false);148        setError("Please import a CSV from the Map view before querying");149      }150    },151    [monitorTaskProgress],152  );153 154  /**155   * Handle request errors156   */157  useEffect(() => {158    if (error) {159      const message = error.response?.data?.message || error.message || `${error}` || "An unknown error occurred";160      setErrorText(`Error uploading file.\n${message}`);161      console.error("Error uploading file:", message);162    }163  }, [error]);164 165  /**166   * Shared functions and variables of this TopicsContext and TopicsProvider167   */168  const providerValue = useMemo(169    () => ({170      data,171      bourdieuData,172      uploadFile,173      isLoading,174      error,175      selectedView,176      refreshBourdieuQuery177    }),178    [data, uploadFile, isLoading, error, selectedView, refreshBourdieuQuery],179  );180 181  // const normalisePercentage = (value) => Math.ceil((value * 100) / 100);182 183  return (184    <TopicsContext.Provider value={providerValue}>185      <>186        {isLoading && <div className="loader" />}187        {/* Display a progress bar based on task progress */}188        {taskID && (189          <Backdrop190            sx={{ zIndex: 99999 }}191            open={taskID !== undefined}192          >193            <Box display={"flex"} width="30%" alignItems={"center"} flexDirection={"column"} sx={{ backgrounColor: "#FFF", fontSize: 20, fontWeight: 'medium' }}>194              <Box minWidth={200}>195                <Typography variant="h4">Bunka is cooking your data, please wait few seconds</Typography>196              </Box>197              <CircularProgress />198              {/* <Box minWidth={35}>199                <Typography variant="subtitle">{`${normalisePercentage(taskProgress)}%`}</Typography>200              </Box> */}201            </Box>202          </Backdrop>203        )}204 205        {errorText && (206          <Alert severity="error" className="errorMessage">207            {errorText}208          </Alert>209        )}210        {children}211      </>212    </TopicsContext.Provider>213  );214}215 216TopicsProvider.propTypes = {217  children: PropTypes.func.isRequired,218  onSelectView: PropTypes.func.isRequired,219};220