Skip to content
48 changes: 46 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"d3-geo-projection": "^4.0.0",
"date-fns": "^2.29.3",
"file-saver": "^2.0.5",
"formidable": "^3.5.2",
"formik": "^2.2.9",
"framer-motion": "^7.5.3",
"gray-matter": "^4.0.3",
Expand Down Expand Up @@ -84,6 +85,7 @@
"devDependencies": {
"@babel/core": "^7.25.9",
"@types/chance": "^1.1.3",
"@types/formidable": "^3.4.5",
"@types/lodash": "^4.14.186",
"@types/node": "^18.7.23",
"@types/react": "^18.2.56",
Expand Down
21 changes: 16 additions & 5 deletions src/contexts/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { NextApiResponse } from 'next';
import qs from 'qs';

// types
import { DashboardContextProps, DashboardState, DashboardStatePatch, WorksetList } from 'types/torchlite';
import { DashboardContextProps, DashboardState, DashboardStatePatch, DataCleaningSettings, WorksetList } from 'types/torchlite';
import { useSession } from 'next-auth/react';
import { getAvailableDashboards, getAvailableWorksets, getDashboardState, updateDashboardState } from 'services';
import CustomBackdrop from 'components/Backdrop';
Expand Down Expand Up @@ -54,8 +54,10 @@ function AppProvider({ children }: AppProviderProps) {
// Get workset and filter from router query
const { worksetId } = router.query;
const filters: any = qs.parse(router.query.filters as string, { comma: true });
const dataClean = qs.parse(router.query.datacleaning as string, { comma: true });
let selectedWorksetId: string,
appliedFilters: any = {};
appliedFilters: any = {},
dataCleaning: DataCleaningSettings;

// Get worksets
let worksets: WorksetList = await getAvailableWorksets();
Expand Down Expand Up @@ -134,26 +136,33 @@ function AppProvider({ children }: AppProviderProps) {
}
}
}

dataCleaning = dataClean

try {
await updateDashboardState(dashboardState.id, {
importedId: selectedWorksetId,
filters: appliedFilters
filters: appliedFilters,
datacleaning: dataCleaning
});
} catch (err) {
console.error(`Error loading workset from URL: ${err}`);
setErrorAlert(true);
setErrorText('This dashboard’s workset is private. Contact the workset’s owner to make the workset is public to see their dashboard.');
}

dashboardState = await getDashboardState(dashboardState.id);
} else {
selectedWorksetId = dashboardState.importedId;
appliedFilters = dashboardState.filters;
dataCleaning = dashboardState.datacleaning;
router.push({
pathname: router.pathname,
query: {
...router.query,
worksetId: selectedWorksetId,
filters: qs.stringify(appliedFilters, { arrayFormat: 'comma', encode: false })
filters: qs.stringify(appliedFilters, { arrayFormat: 'comma', encode: false }),
datacleaning: qs.stringify(dataCleaning, { arrayFormat: 'comma', encode: false })
}
});
}
Expand Down Expand Up @@ -182,12 +191,14 @@ function AppProvider({ children }: AppProviderProps) {
if (dashboardState) {
const selectedWorksetId = dashboardState.worksetId;
const appliedFilters = dashboardState.filters;
const dataCleaning = dashboardState.datacleaning;
router.push({
pathname: router.pathname,
query: {
...router.query,
worksetId: selectedWorksetId,
filters: qs.stringify(appliedFilters, { arrayFormat: 'comma', encode: false })
filters: qs.stringify(appliedFilters, { arrayFormat: 'comma', encode: false }),
datacleaning: qs.stringify(dataCleaning, { arrayFormat: 'comma', encode: false })
}
});
}
Expand Down
116 changes: 100 additions & 16 deletions src/layout/MainLayout/SideBar/CleanDataWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import CustomButton from 'components/Button';
import { colourStyles } from 'styles/react-select';
import { BootstrapTooltip } from 'components/BootstrapTooltip';
import CustomStopwordsModal from 'sections/sidebar/CustomStopwordsModal';
import useDashboardState from 'hooks/useDashboardState';
import { getStopwordsData } from '../../../../src/services/index';
import { uploadStopwordsData } from '../../../../src/services/index';
import { useRouter } from 'next/router';
import qs from 'qs';

interface IMockState {
label: string;
Expand All @@ -17,10 +22,38 @@ interface IMockState {

//stopwords dropdown
const defaultStopwordsOptions = [
{ value: 'English', label: 'English' },
{ value: 'French', label: 'French' },
{ value: 'German', label: 'German' },
{ value: 'Spanish', label: 'Spanish' },
{ value: 'English', label: 'English' },
{ value: 'French', label: 'French' },
{ value: 'German', label: 'German' },
{ value: 'Spanish', label: 'Spanish' },
{ value: 'Albanian', label: 'Albanian' },
{ value: 'Arabic', label: 'Arabic' },
{ value: 'Azerbaijani', label: 'Azerbaijani' },
{ value: 'Basque', label: 'Basque' },
{ value: 'Belarusian', label: 'Belarusian' },
{ value: 'Bengali', label: 'Bengali' },
{ value: 'Catalan', label: 'Catalan' },
{ value: 'Chinese', label: 'Chinese' },
{ value: 'Danish', label: 'Danish' },
{ value: 'Dutch', label: 'Dutch' },
{ value: 'Finnish', label: 'Finnish' },
{ value: 'Greek', label: 'Greek' },
{ value: 'Hebrew', label: 'Hebrew' },
{ value: 'Hinglish', label: 'Hinglish' },
{ value: 'Hungarian', label: 'Hungarian' },
{ value: 'Indonesian', label: 'Indonesian' },
{ value: 'Italian', label: 'Italian' },
{ value: 'Kazakh', label: 'Kazakh' },
{ value: 'Nepali', label: 'Nepali' },
{ value: 'Norwegian', label: 'Norwegian' },
{ value: 'Portuguese', label: 'Portuguese' },
{ value: 'Romanian', label: 'Romanian' },
{ value: 'Russian', label: 'Russian' },
{ value: 'Slovene', label: 'Slovene' },
{ value: 'Swedish', label: 'Swedish' },
{ value: 'Tajik', label: 'Tajik' },
{ value: 'Tamil', label: 'Tamil' },
{ value: 'Turkish', label: 'Turkish' },
// Add other options as needed
];

Expand Down Expand Up @@ -61,16 +94,21 @@ const animatedComponents = makeAnimated();

const CleanDataWidget = () => {
const theme = useTheme();
const router = useRouter();
const [typeGroup, setTypeGroup] = useState<IMockState[]>(dataTypes);
const fileInputRef = useRef(null);
const [fileName, setFileName] = useState(null);
const { dashboardState, onChangeDashboardState } = useDashboardState();
//const [selectedValue, setSelectedValue] = useState('default');
const [stopwordsOptions, setStopwordsOptions] = useState(defaultStopwordsOptions)
const [selectedOption, setSelectedOption] = useState('');
const [modalOpen, setModalOpen] = useState(false);
const [stopwordsName, setStopwordsName] = useState('');
const [applyStopwordsChecked, setApplyStopwordsChecked] = useState(false);
const [selectedFilters, setSelectedFilters] = useState([]);

// Temp variable to store fetched data
let downloadData: any = null;


//old handler for the upload stopwords button
Expand All @@ -90,6 +128,30 @@ const CleanDataWidget = () => {
setModalOpen(false);
};

const handleApplyButton = (dataCleaning: any) => {
console.log("onApplyDataCleaning", dataCleaning)
onChangeDashboardState({
datacleaning: {language: dataCleaning as string}
});
console.log(onChangeDashboardState)
// Reset checkboxes and radios to their original state
/* setTypeGroup((prevTypeGroup) =>
prevTypeGroup.map((item) => ({
...item,
checked: false,
value: item.label === 'Apply Stopwords' ? null : (item.label === 'Page Features' ? [
{ subLabel: 'Remove headers', checked: false },
{ subLabel: 'Remove footers', checked: false },
{ subLabel: 'Remove body', checked: false }
] : item.label === 'Filter by parts-of-speech' ? []
: item.value )// Reset specific values if needed
}))
);
// Reset other state variables if needed
setSelectedOption('');
setSelectedFilters([]); */
}

const handleClearButton = () => {
// Reset checkboxes and radios to their original state
setTypeGroup((prevTypeGroup) =>
Expand All @@ -107,11 +169,21 @@ const CleanDataWidget = () => {
// Reset other state variables if needed
setSelectedOption('');
setSelectedFilters([]);
onChangeDashboardState({
datacleaning: {language: selectedOption}
});
}

//stopwords selection change
const handleSelectChange = (event: React.ChangeEvent<{ value: unknown }>) => {
setSelectedOption(event.target.value as string);
const queryString = {language: event.target.value as string};

console.log("languageoption", queryString)
router.push({
pathname: router.pathname,
query: { ...router.query, datacleaning: queryString}
});
};

//stopwords -- saving user selection
Expand All @@ -133,22 +205,33 @@ const handleSaveName = (name: string) => {
console.log("Selected Option State:", selectedOption);
}, [selectedOption]);

const handleDownload = () => {
const fname = 'example.txt';
const fileContent = 'This is an example file content.';

const element = document.createElement('a');
const file = new Blob([fileContent], { type: 'text/plain' });
element.href = URL.createObjectURL(file);
element.download = fname;
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
const handleDownload = async () => {
const fname = 'stopwords.json';
try {
const language = selectedOption;
const dashboardId = dashboardState?.id;
console.log("Test Download", dashboardId, language);
downloadData = await getStopwordsData(dashboardId, language);

if (downloadData) {
const blob = new Blob([JSON.stringify(downloadData, null, 2)], { type: 'application/json' });
saveAs(blob, fname);
downloadData = null; // Clear data after download
}
}
catch (error) {
console.log('Error downloading:', error);
}
};
//@router.get("/{dashboard_id}/stopwords", description=““)

const handleFileChange = (event: any) => {
const selectedFile = event.target.files[0];
setFileName(selectedFile.name);

if (!selectedFile) {
return;
}
};

const handleRadioChange = (event: any) => {
Expand Down Expand Up @@ -408,6 +491,7 @@ const isButtonEnabled = (
textAlign: 'center',
textTransform: 'none'
}}
onClick={() => handleApplyButton(selectedOption)}
disabled={!isButtonEnabled}
>
Apply cleaning
Expand Down
1 change: 0 additions & 1 deletion src/layout/MainLayout/SideBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const SideBar = () => {
const { dashboardState } = useDashboardState();
const [isWorksetExpanded, setWorksetExpanded] = useState(!!dashboardState?.worksetId);
const [isFilterExpanded, setFilterExpanded] = useState(hasFilters(dashboardState?.filters));

useEffect(() => {
setFilterExpanded(hasFilters(dashboardState?.filters));
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
Loading