Skip to content

Commit

Permalink
[PUI] Fix for hovering in parameteric part table (#7933)
Browse files Browse the repository at this point in the history
* Fix for hovering in parameteric part table

- Visual glitches are now gone

* Prevent editing of template field
  • Loading branch information
SchrodingersGat authored Aug 20, 2024
1 parent 7cbaeb1 commit dbe12c2
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 55 deletions.
9 changes: 7 additions & 2 deletions src/frontend/src/forms/PartForms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,11 @@ export function partCategoryFields(): ApiFormFieldSet {
return fields;
}

export function usePartParameterFields(): ApiFormFieldSet {
export function usePartParameterFields({
editTemplate
}: {
editTemplate?: boolean;
}): ApiFormFieldSet {
// Valid field choices
const [choices, setChoices] = useState<any[]>([]);

Expand All @@ -156,6 +160,7 @@ export function usePartParameterFields(): ApiFormFieldSet {
disabled: true
},
template: {
disabled: editTemplate == false,
onValueChange: (value: any, record: any) => {
// Adjust the type of the "data" field based on the selected template
if (record?.checkbox) {
Expand Down Expand Up @@ -195,5 +200,5 @@ export function usePartParameterFields(): ApiFormFieldSet {
}
}
};
}, [fieldType, choices]);
}, [editTemplate, fieldType, choices]);
}
2 changes: 2 additions & 0 deletions src/frontend/src/functions/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
IconCornerUpRightDouble,
IconCurrencyDollar,
IconDots,
IconEdit,
IconExclamationCircle,
IconExternalLink,
IconFileUpload,
Expand Down Expand Up @@ -109,6 +110,7 @@ const icons = {
units: IconRulerMeasure,
keywords: IconTag,
status: IconInfoCircle,
edit: IconEdit,
info: IconInfoCircle,
exclamation: IconExclamationCircle,
details: IconInfoCircle,
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/tables/InvenTreeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const defaultPageSize: number = 25;
* @param dataFormatter : (data: any) => any - Callback function to reformat data returned by server (if not in default format)
* @param rowActions : (record: any) => RowAction[] - Callback function to generate row actions
* @param onRowClick : (record: any, index: number, event: any) => void - Callback function when a row is clicked
* @param onCellClick : (event: any, record: any, recordIndex: number, column: any, columnIndex: number) => void - Callback function when a cell is clicked
* @param onCellClick : (event: any, record: any, index: number, column: any, columnIndex: number) => void - Callback function when a cell is clicked
* @param modelType: ModelType - The model type for the table
*/
export type InvenTreeTableProps<T = any> = {
Expand Down
28 changes: 21 additions & 7 deletions src/frontend/src/tables/TableHoverCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { t } from '@lingui/macro';
import { Divider, Group, HoverCard, Stack, Text } from '@mantine/core';
import { IconInfoCircle } from '@tabler/icons-react';
import { ReactNode } from 'react';
import { ReactNode, useMemo } from 'react';

import { InvenTreeIcon, InvenTreeIconType } from '../functions/icons';

Expand All @@ -23,12 +23,26 @@ export function TableHoverCard({
icon?: InvenTreeIconType;
iconColor?: string;
}) {
// If no extra information presented, just return the raw value
if (!extra) {
return value;
}
const extraItems: ReactNode = useMemo(() => {
if (Array.isArray(extra)) {
if (extra.length == 0) {
return null;
}

if (Array.isArray(extra) && extra.length == 0) {
return (
<Stack gap="xs">
{extra.map((item, idx) => (
<div key={t`item-${idx}`}>{item}</div>
))}
</Stack>
);
} else {
return extra;
}
}, [extra]);

// If no extra information presented, just return the raw value
if (!extraItems) {
return value;
}

Expand All @@ -50,7 +64,7 @@ export function TableHoverCard({
<Text fw="bold">{title}</Text>
</Group>
<Divider />
{extra}
{extraItems}
</Stack>
</HoverCard.Dropdown>
</HoverCard>
Expand Down
101 changes: 57 additions & 44 deletions src/frontend/src/tables/part/ParametricPartTable.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { t } from '@lingui/macro';
import { ActionIcon, Group, Tooltip } from '@mantine/core';
import { Group } from '@mantine/core';
import { useHover } from '@mantine/hooks';
import { IconEdit } from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query';
import { useCallback, useMemo, useState } from 'react';
import { ReactNode, useCallback, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';

import { api } from '../../App';
import { YesNoButton } from '../../components/buttons/YesNoButton';
Expand All @@ -13,6 +13,8 @@ import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { usePartParameterFields } from '../../forms/PartForms';
import { cancelEvent } from '../../functions/events';
import { navigateToLink } from '../../functions/navigation';
import { getDetailUrl } from '../../functions/urls';
import {
useCreateApiFormModal,
useEditApiFormModal
Expand All @@ -30,28 +32,32 @@ import { TableHoverCard } from '../TableHoverCard';
function ParameterCell({
record,
template,
canEdit,
onEdit
canEdit
}: {
record: any;
template: any;
canEdit: boolean;
onEdit: () => void;
}) {
const { hovered, ref } = useHover();

// Find matching template parameter
let parameter = record.parameters?.find(
(p: any) => p.template == template.pk
);
const parameter = useMemo(() => {
return record.parameters?.find((p: any) => p.template == template.pk);
}, [record.parameters, template]);

let extra: any[] = [];

let value: any = parameter?.data;
// Format the value for display
const value: ReactNode = useMemo(() => {
let v: any = parameter?.data;

if (template?.checkbox && value != undefined) {
value = <YesNoButton value={parameter.data} />;
}
// Handle boolean values
if (template?.checkbox && v != undefined) {
v = <YesNoButton value={parameter.data} />;
}

return v;
}, [parameter, template]);

if (
template.units &&
Expand All @@ -62,30 +68,21 @@ function ParameterCell({
extra.push(`${parameter.data_numeric} [${template.units}]`);
}

const handleClick = useCallback((event: any) => {
cancelEvent(event);
onEdit();
}, []);
if (hovered && canEdit) {
extra.push(t`Click to edit`);
}

return (
<div>
<Group grow ref={ref} justify="space-between">
<Group grow style={{ flex: 1 }}>
<Group grow>
<TableHoverCard
value={value ?? '-'}
extra={extra}
icon={hovered && canEdit ? 'edit' : 'info'}
title={t`Internal Units`}
/>
</Group>
{hovered && canEdit && (
<div style={{ flex: 0 }}>
<Tooltip label={t`Edit parameter`}>
<ActionIcon size="xs" onClick={handleClick} variant="transparent">
<IconEdit />
</ActionIcon>
</Tooltip>
</div>
)}
</Group>
</div>
);
Expand All @@ -98,6 +95,7 @@ export default function ParametricPartTable({
}) {
const table = useTable('parametric-parts');
const user = useUserState();
const navigate = useNavigate();

const categoryParmeters = useQuery({
queryKey: ['category-parameters', categoryId],
Expand All @@ -118,7 +116,9 @@ export default function ParametricPartTable({
const [selectedTemplate, setSelectedTemplate] = useState<number>(0);
const [selectedParameter, setSelectedParameter] = useState<number>(0);

const partParameterFields: ApiFormFieldSet = usePartParameterFields();
const partParameterFields: ApiFormFieldSet = usePartParameterFields({
editTemplate: false
});

const addParameter = useCreateApiFormModal({
url: ApiEndpoints.part_parameter_list,
Expand Down Expand Up @@ -195,26 +195,25 @@ export default function ParametricPartTable({
record={record}
template={template}
canEdit={user.hasChangeRole(UserRoles.part)}
onEdit={() => {
setSelectedTemplate(template.pk);
setSelectedPart(record.pk);
let parameter = record.parameters?.find(
(p: any) => p.template == template.pk
);

if (parameter) {
setSelectedParameter(parameter.pk);
editParameter.open();
} else {
addParameter.open();
}
}}
/>
)
};
});
}, [user, categoryParmeters.data]);

const onParameterClick = useCallback((template: number, part: any) => {
setSelectedTemplate(template);
setSelectedPart(part.pk);
let parameter = part.parameters?.find((p: any) => p.template == template);

if (parameter) {
setSelectedParameter(parameter.pk);
editParameter.open();
} else {
addParameter.open();
}
}, []);

const tableFilters: TableFilter[] = useMemo(() => {
return [
{
Expand Down Expand Up @@ -268,14 +267,28 @@ export default function ParametricPartTable({
columns={tableColumns}
props={{
enableDownload: false,
tableFilters: tableFilters,
params: {
category: categoryId,
cascade: true,
category_detail: true,
parameters: true
},
modelType: ModelType.part,
tableFilters: tableFilters
onCellClick: ({ event, record, index, column, columnIndex }) => {
cancelEvent(event);

// Is this a "parameter" cell?
if (column?.accessor?.toString()?.startsWith('parameter_')) {
const col = column as any;
onParameterClick(col.extra.template, record);
} else {
// Navigate through to the part detail page
if (record?.pk) {
const url = getDetailUrl(ModelType.part, record.pk);
navigateToLink(url, navigate, event);
}
}
}
}}
/>
</>
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/tables/part/PartParameterTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export function PartParameterTable({
];
}, [partId]);

const partParameterFields: ApiFormFieldSet = usePartParameterFields();
const partParameterFields: ApiFormFieldSet = usePartParameterFields({});

const newParameter = useCreateApiFormModal({
url: ApiEndpoints.part_parameter_list,
Expand Down

0 comments on commit dbe12c2

Please sign in to comment.