Skip to content

Commit

Permalink
Merge branch 'dev' into feature/2547-normalize-study-path
Browse files Browse the repository at this point in the history
  • Loading branch information
Anis SMAIL committed Jan 30, 2025
2 parents e987d24 + 1263f5a commit d14030e
Show file tree
Hide file tree
Showing 18 changed files with 504 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ def _apply(self, study_data: FileStudy, listener: t.Optional[ICommandListener] =
if binding_constraints[key].get("id") in self.ids:
deleted_binding_constraints.append(binding_constraints.pop(key))

# BC dict should start at index 0
new_binding_constraints = {str(i): value for i, value in enumerate(binding_constraints.values())}

study_data.tree.save(
binding_constraints,
new_binding_constraints,
["input", "bindingconstraints", "bindingconstraints"],
)

Expand Down
10 changes: 8 additions & 2 deletions commitlint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ const RuleConfigSeverity = {
Disabled: 0,
Warning: 1,
Error: 2,
}
};

module.exports = {
extends: ["@commitlint/config-conventional"],
// Rules: https://commitlint.js.org/reference/rules.html
rules: {
"header-max-length": [RuleConfigSeverity.Error, "always", 150],
"scope-case": [
RuleConfigSeverity.Error,
"always",
["lower-case", "kebab-case"],
],
"scope-empty": [RuleConfigSeverity.Error, "never"],
"header-max-length": [RuleConfigSeverity.Error, "always", 150],
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -987,10 +987,15 @@ def test_for_version_870(self, client: TestClient, user_access_token: str, study
assert res.status_code == 200, res.json()

# Asserts that the deletion worked
binding_constraints_list = preparer.get_binding_constraints(study_id)
binding_constraints_list = client.get(
f"/v1/studies/{study_id}/raw",
params={"path": f"input/bindingconstraints/bindingconstraints"}, # type: ignore
).json()
assert len(binding_constraints_list) == 2
actual_ids = [constraint["id"] for constraint in binding_constraints_list]
actual_ids = [constraint["id"] for constraint in binding_constraints_list.values()]
assert actual_ids == ["binding_constraint_1", "binding_constraint_3"]
keys = sorted(int(k) for k in binding_constraints_list.keys())
assert keys == list(range(len(keys)))

# =============================
# CONSTRAINT DUPLICATION
Expand Down
3 changes: 2 additions & 1 deletion webapp/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export default [
rules: {
...reactHookPlugin.configs.recommended.rules,
"@typescript-eslint/array-type": ["error", { default: "array-simple" }],
"@typescript-eslint/no-non-null-assertion": "error",
"@typescript-eslint/no-restricted-imports": [
"error",
{
Expand Down Expand Up @@ -129,7 +130,7 @@ export default [
{
// Includes hooks from 'react-use'
additionalHooks:
"(useSafeMemo|useUpdateEffectOnce|useDeepCompareEffect|useShallowCompareEffect|useCustomCompareEffect)",
"(useSafeMemo|useUpdateEffect|useUpdateEffectOnce|useDeepCompareEffect|useShallowCompareEffect|useCustomCompareEffect)",
},
],
"require-await": "warn", // TODO: switch to "error" when the quantity of warning will be low
Expand Down
11 changes: 8 additions & 3 deletions webapp/src/components/App/Singlestudy/FreezeStudy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function FreezeStudy({ studyId }: FreezeStudyProps) {
setBlockingTasks(
tasks.map((task) => ({
id: task.id,
type: task.type!,
type: task.type,
})),
);

Expand Down Expand Up @@ -143,10 +143,15 @@ function FreezeStudy({ studyId }: FreezeStudyProps) {

function forceUpdate(taskId: BlockingTask["id"]) {
getTask({ id: taskId }).then((task) => {
// Normally all blocking tasks have a type
if (!task.type) {
return;
}

const payload = {
id: task.id,
message: task.result?.message || "",
type: task.type!,
type: task.type,
};
if (task.status === TaskStatus.Running) {
if (typeof task.progress === "number") {
Expand Down Expand Up @@ -179,7 +184,7 @@ function FreezeStudy({ studyId }: FreezeStudyProps) {
unsubscribeWsChannels();
window.clearInterval(intervalId);
};
}, [studyId]);
}, [blockingTasksRef, studyId]);

return (
<Backdrop open={blockingTasks.length > 0} sx={{ position: "absolute" }}>
Expand Down
27 changes: 12 additions & 15 deletions webapp/src/components/App/Singlestudy/explore/Debug/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function Debug() {
// Allow to keep expanded items when the tree is reloaded with `reloadTreeData`
const [expandedItems, setExpandedItems] = useState<string[]>([]);
const [searchParams, setSearchParams] = useSearchParams();
const pathInUrl = searchParams.get("path");
const path = searchParams.get("path");

const res = usePromiseWithSnackbarError(
async () => {
Expand All @@ -60,17 +60,18 @@ function Debug() {
const firstChildName = Object.keys(res.data ?? {})[0];
const firstChildTreeData = R.path<TreeData>([firstChildName], res.data);

const pathInUrlParts = pathInUrl?.split("/");
const urlPathTreeData = pathInUrlParts ? R.path<TreeData>(pathInUrlParts, res.data) : null;
const pathSegments = path?.split("/");
const filename = pathSegments ? R.last(pathSegments) : null;
const treeData = pathSegments ? R.path<TreeData>(pathSegments, res.data) : null;

let fileInfo: FileInfo | null = null;

if (urlPathTreeData) {
if (path && filename && treeData) {
fileInfo = {
fileType: getFileType(urlPathTreeData),
treeData: urlPathTreeData,
filename: R.last(pathInUrlParts!)!,
filePath: pathInUrl!,
fileType: getFileType(treeData),
treeData,
filename,
filePath: path,
};
} else if (firstChildTreeData) {
fileInfo = {
Expand All @@ -81,15 +82,11 @@ function Debug() {
};
}

if (fileInfo) {
setSelectedFile(fileInfo);
} else {
setSelectedFile(null);
}
}, [res.data, pathInUrl]);
setSelectedFile(fileInfo);
}, [res.data, path]);

useUpdateEffect(() => {
if (selectedFile?.filePath !== pathInUrl) {
if (selectedFile?.filePath !== path) {
setSearchParams({ path: selectedFile?.filePath || "" });
}
}, [selectedFile?.filePath]);
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/components/App/Singlestudy/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ function SingleStudy(props: Props) {
) : (
<HomeView study={study} tree={tree} />
)}
<FreezeStudy studyId={studyId!} />
{studyId && <FreezeStudy studyId={studyId} />}
</Box>
{openCommands && studyId && (
<CommandDrawer
Expand Down
114 changes: 57 additions & 57 deletions webapp/src/components/common/DataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,83 +19,91 @@ import {
type EditListItem,
type GridSelection,
type DataEditorProps,
type GridCell,
} from "@glideapps/glide-data-grid";
import "@glideapps/glide-data-grid/dist/index.css";
import { useCallback, useEffect, useState } from "react";
import { useCallback, useState } from "react";
import { voidFn } from "@/utils/fnUtils";
import { darkTheme } from "./Matrix/styles";
import { useUpdateEffect } from "react-use";

interface StringRowMarkerOptions {
kind: "string" | "clickable-string";
getTitle?: (rowIndex: number) => string;
width?: number;
}

type RowMarkers =
export type RowMarkers =
| NonNullable<DataEditorProps["rowMarkers"]>
| StringRowMarkerOptions["kind"]
| StringRowMarkerOptions;

type RowMarkersOptions = Exclude<RowMarkers, string>;

export interface DataGridProps
extends Omit<DataEditorProps, "rowMarkers" | "onGridSelectionChange" | "gridSelection"> {
export interface DataGridProps extends Omit<DataEditorProps, "rowMarkers" | "gridSelection"> {
rowMarkers?: RowMarkers;
enableColumnResize?: boolean;
}

const ROW_HEIGHT = 30;

function isStringRowMarkerOptions(
rowMarkerOptions: RowMarkersOptions,
): rowMarkerOptions is StringRowMarkerOptions {
return rowMarkerOptions.kind === "string" || rowMarkerOptions.kind === "clickable-string";
}

function DataGrid(props: DataGridProps) {
const {
rowMarkers = { kind: "none" },
getCellContent,
columns: columnsFromProps,
onCellEdited,
onCellsEdited,
onColumnResize,
onColumnResizeStart,
onColumnResizeEnd,
enableColumnResize = true,
freezeColumns,
...rest
} = props;

function DataGrid({
rowMarkers = { kind: "none" },
getCellContent,
columns: columnsFromProps,
onCellEdited,
onCellsEdited,
onColumnResize,
onColumnResizeStart,
onColumnResizeEnd,
onGridSelectionChange,
enableColumnResize = true,
freezeColumns,
rows,
...rest
}: DataGridProps) {
const rowMarkersOptions: RowMarkersOptions =
typeof rowMarkers === "string" ? { kind: rowMarkers } : rowMarkers;

const isStringRowMarkers = isStringRowMarkerOptions(rowMarkersOptions);
const adjustedFreezeColumns = isStringRowMarkers ? (freezeColumns || 0) + 1 : freezeColumns;

const [columns, setColumns] = useState(columnsFromProps);
const [selection, setSelection] = useState<GridSelection>({
columns: CompactSelection.empty(),
const [columns, setColumns] = useState(initColumns);
const [gridSelection, setGridSelection] = useState<GridSelection>({
rows: CompactSelection.empty(),
columns: CompactSelection.empty(),
});

// Add a column for the "string" row markers if needed
useEffect(() => {
setColumns(
isStringRowMarkers ? [{ id: "", title: "" }, ...columnsFromProps] : columnsFromProps,
);
useUpdateEffect(() => {
setColumns(initColumns());
}, [columnsFromProps, isStringRowMarkers]);

////////////////////////////////////////////////////////////////
// Utils
////////////////////////////////////////////////////////////////

function initColumns() {
return isStringRowMarkers
? [{ id: "", title: "", width: rowMarkersOptions.width }, ...columnsFromProps]
: columnsFromProps;
}

const ifElseStringRowMarkers = <R1, R2>(
colIndex: number,
onTrue: () => R1,
onTrue: (options: StringRowMarkerOptions) => R1,
onFalse: (colIndex: number) => R2,
) => {
let adjustedColIndex = colIndex;

if (isStringRowMarkers) {
if (colIndex === 0) {
return onTrue();
return onTrue(rowMarkersOptions);
}

adjustedColIndex = colIndex - 1;
Expand All @@ -118,11 +126,8 @@ function DataGrid(props: DataGridProps) {

return ifElseStringRowMarkers(
colIndex,
() => {
const title =
isStringRowMarkers && rowMarkersOptions.getTitle
? rowMarkersOptions.getTitle(rowIndex)
: `Row ${rowIndex + 1}`;
({ getTitle }) => {
const title = getTitle ? getTitle(rowIndex) : `Row ${rowIndex + 1}`;

return {
kind: GridCellKind.Text,
Expand All @@ -133,7 +138,7 @@ function DataGrid(props: DataGridProps) {
themeOverride: {
bgCell: darkTheme.bgHeader,
},
};
} satisfies GridCell;
},
(adjustedColIndex) => {
return getCellContent([adjustedColIndex, rowIndex]);
Expand Down Expand Up @@ -223,7 +228,7 @@ function DataGrid(props: DataGridProps) {
if (newSelection.current) {
// Select the whole row when clicking on a row marker cell
if (rowMarkersOptions.kind === "clickable-string" && newSelection.current.cell[0] === 0) {
setSelection({
setGridSelection({
...newSelection,
current: undefined,
rows: CompactSelection.fromSingleSelection(newSelection.current.cell[1]),
Expand All @@ -238,28 +243,24 @@ function DataGrid(props: DataGridProps) {
}
}

// Prevent selecting the row marker column
// Select/Deselect all the rows like others row markers when selecting the column
if (newSelection.columns.hasIndex(0)) {
// TODO find a way to have the rows length to select all the rows like other row markers
// setSelection({
// ...newSelection,
// columns: CompactSelection.empty(),
// rows: CompactSelection.fromSingleSelection([
// 0,
// // rowsLength
// ]),
// });

setSelection({
const isSelectedAll = gridSelection.rows.length === rows;

setGridSelection({
...newSelection,
columns: newSelection.columns.remove(0),
columns: CompactSelection.empty(),
rows: isSelectedAll
? CompactSelection.empty()
: CompactSelection.fromSingleSelection([0, rows]),
});

return;
}
}

setSelection(newSelection);
setGridSelection(newSelection);
onGridSelectionChange?.(newSelection);
}
};

Expand All @@ -269,16 +270,14 @@ function DataGrid(props: DataGridProps) {

return (
<DataEditor
groupHeaderHeight={30}
headerHeight={30}
rowHeight={30}
groupHeaderHeight={ROW_HEIGHT}
headerHeight={ROW_HEIGHT}
rowHeight={ROW_HEIGHT}
smoothScrollX
smoothScrollY
overscrollX={2}
overscrollY={2}
width="100%"
theme={darkTheme}
{...rest}
rows={rows}
columns={columns}
rowMarkers={isStringRowMarkers ? "none" : rowMarkersOptions}
getCellContent={getCellContentWrapper}
Expand All @@ -287,9 +286,10 @@ function DataGrid(props: DataGridProps) {
onColumnResize={handleColumnResize}
onColumnResizeStart={handleColumnResizeStart}
onColumnResizeEnd={handleColumnResizeEnd}
gridSelection={selection}
gridSelection={gridSelection}
onGridSelectionChange={handleGridSelectionChange}
freezeColumns={adjustedFreezeColumns}
{...rest}
/>
);
}
Expand Down
Loading

0 comments on commit d14030e

Please sign in to comment.