From 1208aff69b9050efe3083cd234549a92db056372 Mon Sep 17 00:00:00 2001 From: ddelpiano Date: Fri, 19 Sep 2025 09:39:54 +0200 Subject: [PATCH] minor fixes --- .../EditBulkTerms/EditBulkTermsDialog.jsx | 7 ++- .../Dashboard/EditBulkTerms/SearchTerms.jsx | 23 ++++++--- .../Dashboard/EditBulkTerms/TermsTable.jsx | 49 ++++++++++++++----- .../SingleTermView/OntologySearch.jsx | 34 ++++++++----- vite.config.js | 37 ++++++++++++++ 5 files changed, 117 insertions(+), 33 deletions(-) diff --git a/src/components/Dashboard/EditBulkTerms/EditBulkTermsDialog.jsx b/src/components/Dashboard/EditBulkTerms/EditBulkTermsDialog.jsx index 2e15717..513345b 100644 --- a/src/components/Dashboard/EditBulkTerms/EditBulkTermsDialog.jsx +++ b/src/components/Dashboard/EditBulkTerms/EditBulkTermsDialog.jsx @@ -15,7 +15,7 @@ import { patchTerm } from "../../../api/endpoints"; const initialSearchConditions = { attribute: '', value: '', condition: 'where', relation: SearchTermsData.objectOptions[0].value } -const HeaderRightSideContent = ({ handleClose, activeStep, handleNext, handleBack, setActiveStep, isAllFieldsFilled, selectedOntology, isUpdating }) => { +const HeaderRightSideContent = ({ handleClose, activeStep, handleNext, handleBack, setActiveStep, isAllFieldsFilled, selectedOntology, isUpdating, ontologyTerms }) => { return ( {isUpdating ? 'Saving Changes...' : 'Continue'} @@ -65,6 +65,8 @@ HeaderRightSideContent.propTypes = { setActiveStep: PropTypes.func.isRequired, isAllFieldsFilled: PropTypes.bool.isRequired, selectedOntology: PropTypes.object, + isUpdating: PropTypes.bool.isRequired, + ontologyTerms: PropTypes.array, }; const EditBulkTermsDialog = ({ open, handleClose, activeStep, setActiveStep }) => { @@ -218,6 +220,7 @@ const EditBulkTermsDialog = ({ open, handleClose, activeStep, setActiveStep }) = isAllFieldsFilled={isAllFieldsFilled(searchConditions)} selectedOntology={selectedOntology} isUpdating={isUpdating} + ontologyTerms={ontologyTerms} /> } sx={{ diff --git a/src/components/Dashboard/EditBulkTerms/SearchTerms.jsx b/src/components/Dashboard/EditBulkTerms/SearchTerms.jsx index d1ca3ec..59af63e 100644 --- a/src/components/Dashboard/EditBulkTerms/SearchTerms.jsx +++ b/src/components/Dashboard/EditBulkTerms/SearchTerms.jsx @@ -48,7 +48,7 @@ const styles = { }, } -const SearchTerms = ({ searchConditions, setSearchConditions, initialSearchConditions, setOntologyTerms, ontologyAttributes, setOntologyAttributes, selectedOntology, setSelectedOntology, setOriginalTerms }) => { +const SearchTerms = ({ searchConditions, setSearchConditions, initialSearchConditions, ontologyTerms, setOntologyTerms, ontologyAttributes, setOntologyAttributes, selectedOntology, setSelectedOntology, setOriginalTerms }) => { const [ontologyEditOption, setOntologyEditOption] = useState(Confirmation.Yes); const [attributesLoading, setAttributesLoading] = useState(false); const { user } = useContext(GlobalDataContext); @@ -292,13 +292,20 @@ const SearchTerms = ({ searchConditions, setSearchConditions, initialSearchCondi {ontologyEditOption === Confirmation.Yes && ( - + <> + + {selectedOntology && ontologyTerms.length === 0 && !attributesLoading && ( + + ⚠️ The selected ontology "{selectedOntology.label}" contains no terms to edit. + + )} + )} diff --git a/src/components/Dashboard/EditBulkTerms/TermsTable.jsx b/src/components/Dashboard/EditBulkTerms/TermsTable.jsx index 0a32a30..13d6977 100644 --- a/src/components/Dashboard/EditBulkTerms/TermsTable.jsx +++ b/src/components/Dashboard/EditBulkTerms/TermsTable.jsx @@ -112,7 +112,10 @@ const TermsTable = ({ setOpenEditAttributes, setAttributes, attributes, ontology }; const sortedRows = React.useMemo( - () => stableSort(terms || [], getComparator(order, orderBy)), + () => { + if (!terms || terms.length === 0) return []; + return stableSort(terms, getComparator(order, orderBy)); + }, [order, orderBy, terms] ); @@ -156,7 +159,7 @@ const TermsTable = ({ setOpenEditAttributes, setAttributes, attributes, ontology } return ( - terms.length > 0 ? ( + terms && terms.length > 0 ? ( Edit your terms or select an header to bulk edit that property @@ -243,11 +246,11 @@ const TermsTable = ({ setOpenEditAttributes, setAttributes, attributes, ontology attributes={attributes} /> - {sortedRows.map((row, index) => ( + {sortedRows && sortedRows.length > 0 ? sortedRows.map((row, index) => ( {filteredColumns.map((column) => { const isEditing = editingCell?.rowIndex === index && editingCell?.columnId === column.id; - const cellValue = row[column.id]; + const cellValue = row && row[column.id]; return ( - ) : Array.isArray(cellValue) ? ( + ) : Array.isArray(cellValue) && cellValue.length > 0 ? ( - {cellValue.map((chip, chipIndex) => ( - } onClick={() => handleChipClick(chip)} /> - ))} + {cellValue.map((chip, chipIndex) => { + const chipLabel = typeof chip === 'object' && chip !== null + ? chip['@value'] || chip.value || chip['@id'] || JSON.stringify(chip) + : chip || ''; + const chipValue = typeof chip === 'object' && chip !== null + ? chip['@id'] || chip.value || chip['@value'] + : chip; + return ( + } + onClick={() => handleChipClick(chipValue)} + /> + ); + })} ) : column.id === '@id' ? ( // Format the Interlex ID to show just the ID part - read-only display - {cellValue?.split('/').pop() || cellValue} + {(() => { + if (!cellValue) return ''; + if (typeof cellValue === 'object') { + const idValue = cellValue['@id'] || cellValue.id || cellValue['@value'] || JSON.stringify(cellValue); + return typeof idValue === 'string' ? idValue.split('/').pop() || idValue : idValue; + } + return typeof cellValue === 'string' ? cellValue.split('/').pop() || cellValue : cellValue; + })()} ) : ( - {cellValue} + {typeof cellValue === 'object' && cellValue !== null + ? cellValue['@value'] || cellValue.value || JSON.stringify(cellValue) + : cellValue || '' + } )} ); })} - ))} + )) : null} diff --git a/src/components/SingleTermView/OntologySearch.jsx b/src/components/SingleTermView/OntologySearch.jsx index e3372ef..ea1987f 100644 --- a/src/components/SingleTermView/OntologySearch.jsx +++ b/src/components/SingleTermView/OntologySearch.jsx @@ -227,11 +227,17 @@ const OntologySearch = ({ placeholder, fullWidth = false, disabled, extra, userG setSearchTerm(''); setSelectedValue(value); + // If value is null (cleared), also clear from context + if (!value) { + setOntologyData(null); + console.log('Ontology cleared from context'); + } + // Call the callback if provided if (onOntologySelect) { onOntologySelect(value); } - }, [onOntologySelect]); + }, [onOntologySelect, setOntologyData]); const popperProps = useMemo(() => ({ sx: { @@ -315,15 +321,18 @@ const OntologySearch = ({ placeholder, fullWidth = false, disabled, extra, userG ), - endAdornment: selectedValue?.selected && ( - - - + endAdornment: ( + + {selectedValue?.selected && ( + + )} + {params.InputProps.endAdornment} + ), }} sx={{ @@ -345,8 +354,9 @@ const OntologySearch = ({ placeholder, fullWidth = false, disabled, extra, userG
path, // keep full path + configure: (proxy) => { + proxy.on('error', (err, req) => { + console.log('Password change proxy error:', err); + console.log('Request URL:', req.url); + }); + proxy.on('proxyReq', (proxyReq, req) => { + console.log('Proxying password change request:', req.method, req.url); + // pass through auth/cookies if present + if (req.headers.authorization) proxyReq.setHeader('Authorization', req.headers.authorization); + if (req.headers.cookie) proxyReq.setHeader('Cookie', req.headers.cookie); + // Set appropriate content type for password change (likely form data) + if (req.method === 'POST') { + proxyReq.setHeader('Content-Type', 'application/x-www-form-urlencoded'); + } + }); + proxy.on('proxyRes', (proxyRes, req, res) => { + console.log('Password change response:', proxyRes.statusCode, req.url); + // handle redirects + const location = proxyRes.headers['location']; + if (proxyRes.statusCode === 303 && location) { + delete proxyRes.headers['location']; + res.setHeader('X-Redirect-Location', location); + } + + // CORS headers + const origin = req.headers.origin; + if (origin) res.setHeader('Access-Control-Allow-Origin', origin); + res.setHeader('Access-Control-Allow-Credentials', 'true'); + res.setHeader('Access-Control-Expose-Headers', 'X-Redirect-Location'); + }); + }, + }, '^/([^/]+)/priv/entity(.*)': { target: "https://uri.olympiangods.org", secure: false,