Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 8ef39e74 authored by Simon Ebel's avatar Simon Ebel
Browse files

feat: add custom EditableCell and ExpandableCell to prevent infinite lazy...

feat: add custom EditableCell and ExpandableCell to prevent infinite lazy height computing. Ref #167
parent b20eb4d0
No related branches found
No related tags found
No related merge requests found
......@@ -21,6 +21,7 @@ import {
ToggleButton,
Typography,
} from "@mui/material";
import Link from "@mui/material/Link";
import { grey } from "@mui/material/colors";
import {
DataGrid,
......@@ -32,12 +33,12 @@ import {
GridToolbarColumnsButton,
GridToolbarDensitySelector,
GridToolbarFilterButton,
useGridApiContext,
} from "@mui/x-data-grid";
import { ContainedButton, HelpButton } from "../components/button";
import DropDown from "../components/dropdown";
import { useLang } from "../context/Lang";
import { fetcherGet } from "../fetch/fetcher";
import { useDataSources } from "../fetch/sources";
import {
useContexts,
......@@ -45,7 +46,7 @@ import {
useMixedQuery,
useUpdateValues,
} from "../fetch/view";
import {isDefined, prettifyValue} from "../utils/utils";
import { isDefined, prettifyValue } from "../utils/utils";
import {
getStartEndVariables,
parseError,
......@@ -167,6 +168,10 @@ const trans = {
</Typography>
),
},
sliceText: {
more: { fr: "voir plus", en: "view more" },
less: { fr: "voir moins", en: "view less" },
},
};
function CustomToolbar() {
......@@ -208,7 +213,6 @@ function ContextsList({
const pos = parseInt(event.target.getAttribute("pos"));
const variable = event.target.value;
variablesValue[idx][pos] = variable;
console.log(variablesValue);
setVariablesValue([...variablesValue]);
setShouldExecuteQuery(false);
};
......@@ -312,6 +316,82 @@ function ContextsList({
);
}
function ExpandableCell({ value, lang, ...params }) {
const [expanded, setExpanded] = React.useState(false);
const handOnChange = () => {
setExpanded(!expanded);
params.row[`${params.field}_expand`] =
!params.row[`${params.field}_expand`];
};
React.useEffect(() => {
const expand_state = params.row[`${params.field}_expand`];
setExpanded(expand_state);
}, [params.row, params.field]);
function renderValue(value) {
if (value) {
return expanded ? value : value.slice(0, 200);
}
}
function renderLink() {
if (value) {
return (
value.length > 200 && (
<Link
type="button"
component="button"
sx={{ fontSize: "inherit" }}
onClick={handOnChange}
>
{expanded ? trans.sliceText.less[lang] : trans.sliceText.more[lang]}
</Link>
)
);
}
}
return (
<div>
{renderValue(value)}&nbsp;
{renderLink()}
</div>
);
}
function EditCell(props) {
const { id, value, field, hasFocus } = props;
const apiRef = useGridApiContext();
const ref = React.useRef();
React.useLayoutEffect(() => {
if (hasFocus) {
ref.current.focus();
}
}, [hasFocus]);
const handleValueChange = (event) => {
const newValue = event.target.value; // The new value entered by the user
apiRef.current.setEditCellValue({ id, field, value: newValue });
};
return (
<TextField
multiline
sx={{ border: "none", width: "100%", height: "100%" }}
ref={ref}
id="outlined-basic"
variant="standard"
value={value}
onChange={handleValueChange}
InputProps={{
disableUnderline: true,
}}
/>
);
}
function DataView({
database,
contexts,
......@@ -374,25 +454,28 @@ function DataView({
// setDataError(null);
}
const { columns, rows, statement } = parseData;
const { columns, rows } = parseData;
var newColumnData = [];
var IdToField = {};
for (let column of columns) {
console.log(column);
var frontColumn = {
...column,
headerName: "",
width: "",
editable: "",
headerName: column.field,
width: 150,
editable: column.editable === "false" ? false : true,
flex: 1,
renderCell: (params) => (
<ExpandableCell {...params} lang={activeLang} />
),
renderEditCell: (params) => <EditCell {...params} />,
};
frontColumn.headerName = frontColumn.field;
frontColumn.width = 150;
frontColumn.editable = column.editable === "false" ? false : true;
newColumnData.push(frontColumn);
newColumnData.push(frontColumn);
IdToField[frontColumn.id] = frontColumn.field;
}
setColumnData(newColumnData);
setActiveRows(rows);
setIdToField(IdToField);
......@@ -404,7 +487,7 @@ function DataView({
setNoResutFound(false);
}
}
}, [dataRows]);
}, [dataRows, setDataError, activeLang]);
React.useEffect(() => {
const fieldToId = Object.fromEntries(
......@@ -421,6 +504,12 @@ function DataView({
for (let field of Object.keys(fieldToId)) {
const value = row[field];
const fieldExpandState = `${field}_expand`;
if (!(fieldExpandState in row)) {
row[`${field}_expand`] = false;
}
const fieldId = fieldToId[field];
if (!(fieldId in fieldIdToValueIdToRowId)) {
fieldIdToValueIdToRowId[fieldId] = {};
......@@ -458,11 +547,11 @@ function DataView({
var error = parseError(isDataRowsError);
setDataError(error);
}
}, [isDataRowsError]);
}, [isDataRowsError, setDataError]);
const [valuesToUpdate, setValuesToUpdate] = React.useState({});
const { updated, isUpdateError, isUpdateLoading } = useUpdateValues(
const { updated } = useUpdateValues(
shouldUpdateValues,
database,
contexts,
......@@ -470,12 +559,35 @@ function DataView({
activeSource.type
);
// FIXME:
// Will be used to set a message to the user to tell him if update is successfull or not
React.useEffect(() => {
if (updated) {
}
});
return (
<Box>
{Object.keys(activeRows).length > 0 ? (
<DataGrid
sx={{
overflow: "hidden",
"&.MuiDataGrid-root--densityCompact .MuiDataGrid-cell": {
py: "8px",
},
"&.MuiDataGrid-root--densityStandard .MuiDataGrid-cell": {
py: "15px",
},
"&.MuiDataGrid-root--densityComfortable .MuiDataGrid-cell": {
py: "22px",
},
mt: 2,
}}
// rowsHeight={100}
getRowHeight={() => "auto"}
getEstimatedRowHeight={() => 200}
rows={displayRows}
autoHeight={true}
slots={{
toolbar: CustomToolbar,
}}
......@@ -494,32 +606,30 @@ function DataView({
}
pageSizeOptions={[10, 20, 50]}
disableRowSelectionOnClick
sx={{
"&.MuiDataGrid-root--densityCompact .MuiDataGrid-cell": {
py: "8px",
},
"&.MuiDataGrid-root--densityStandard .MuiDataGrid-cell": {
py: "15px",
},
"&.MuiDataGrid-root--densityComfortable .MuiDataGrid-cell": {
py: "22px",
},
mt: 2,
}}
onCellEditStop={(params, event) => {
const fieldId = params.colDef.id;
const valueId = params.row.fieldToValue[fieldId];
const rowsToUpdate = fieldIdToValueIdToRowId[fieldId][valueId];
if (event.target) {
const updatedValue = event.target.value;
var updatedRows = { ...activeRows };
var updatedRows = { ...activeRows };
if (event.target) {
rowsToUpdate.forEach((id) => {
var updatedRow = { ...activeRows[id] };
updatedRow[IdToField[fieldId]] = updatedValue;
// Keep the cell expanded after stopping edit it
const editedField = IdToField[fieldId];
updatedRows[id] = updatedRow;
let oldValue = activeRows[id][IdToField[fieldId]];
// Update the new value of the cell
const updatedValue = event.target.value;
updatedRow[editedField] = updatedValue;
console.log(updatedRow);
updatedRow[`${editedField}_expand`] = true;
let oldValue = activeRows[id][editedField];
if (!(id in valuesToUpdate)) {
valuesToUpdate[id] = {};
}
......@@ -562,11 +672,9 @@ export default function View() {
const [shouldFetchContexts, setShouldFetchContexts] = React.useState(false);
const [paths, setPaths] = React.useState([]);
const { extractedContexts, isContextsError, isContextsLoading } = useContexts(
shouldFetchContexts,
database,
[activeSource.id]
);
const { extractedContexts } = useContexts(shouldFetchContexts, database, [
activeSource.id,
]);
React.useEffect(() => {
if (isDefined(extractedContexts)) {
......@@ -575,7 +683,7 @@ export default function View() {
}, [extractedContexts]);
const [sources, setSources] = React.useState([]);
const { dataSources, isDataSourcesLoading } = useDataSources(true, database);
const { dataSources } = useDataSources(true, database);
React.useEffect(() => {
const getSourceName = (source) => {
......@@ -697,15 +805,13 @@ export default function View() {
}
}, [activePaths, radioValue, variablesValue]);
const { inStatement, isStatementError, isStatementLoading } = useMixedQuery(
const { inStatement, isStatementError } = useMixedQuery(
database,
contexts,
activeSource,
shouldFetchStatement
);
// console.log(inStatement, shouldFetchStatement);
React.useEffect(() => {
if (isDefined(inStatement) && inStatement) {
setStatement(prettyPrintStatement(inStatement["statement"]));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment