diff --git a/client/src/components/production-board-kanban/production-board-kanban.settings.component.jsx b/client/src/components/production-board-kanban/production-board-kanban.settings.component.jsx index b5bb92d90..73192590b 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.settings.component.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.settings.component.jsx @@ -4,23 +4,26 @@ import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { UPDATE_KANBAN_SETTINGS } from "../../graphql/user.queries"; -export default function ProductionBoardKanbanSettings({ associationSettings, parentLoading, onSettingsChange }) { +export default function ProductionBoardKanbanSettings({ associationSettings, parentLoading }) { const [form] = Form.useForm(); const [open, setOpen] = useState(false); const [loading, setLoading] = useState(false); const [hasChanges, setHasChanges] = useState(false); - const [orientation, setOrientation] = useState(true); // Default to vertical - + const [orientation, setOrientation] = useState(true); + const [compact, setCompact] = useState(false); + const [colored, setColored] = useState(false); const [updateKbSettings] = useMutation(UPDATE_KANBAN_SETTINGS); + const { t } = useTranslation(); useEffect(() => { if (associationSettings?.kanban_settings) { + const { orientation = true, compact = true, cardcolor = true } = associationSettings.kanban_settings; form.setFieldsValue(associationSettings.kanban_settings); - setOrientation(associationSettings.kanban_settings?.orientation ?? true); + setOrientation(orientation); + setCompact(compact); + setColored(cardcolor); } - }, [form, associationSettings, open]); - - const { t } = useTranslation(); + }, [form, associationSettings]); const handleFinish = async (values) => { setLoading(true); @@ -29,9 +32,10 @@ export default function ProductionBoardKanbanSettings({ associationSettings, par const result = await updateKbSettings({ variables: { id: associationSettings?.id, - ks: { ...values, orientation } + ks: { ...values, orientation, compact, cardcolor: colored } } }); + if (result.errors) { notification.open({ type: "error", @@ -40,40 +44,56 @@ export default function ProductionBoardKanbanSettings({ associationSettings, par }) }); } + setOpen(false); setLoading(false); parentLoading(false); setHasChanges(false); }; - const handleValuesChange = () => { - setHasChanges(true); - }; + const handleValuesChange = () => setHasChanges(true); - const handleOrientationChange = (checked) => { - setOrientation(checked); + const handleCheckedChanges = (checked, callback) => { + callback(checked); setHasChanges(true); }; const cardStyle = { minWidth: "50vw", marginTop: 10 }; + const renderSwitchItem = (name, checked, callback, labelKey, checkedChildrenKey, unCheckedChildrenKey) => ( + + + handleCheckedChanges(checked, callback)} + /> + + + ); + + const renderCheckboxItem = (name, labelKey) => ( + + + {t(labelKey)} + + + ); + const renderCardSettings = () => ( <> + {renderSwitchItem( + "orientation", + orientation, + setOrientation, + "production.labels.orientation", + "production.labels.vertical", + "production.labels.horizontal" + )} - - - - - - - {t("production.options.small")} @@ -82,77 +102,39 @@ export default function ProductionBoardKanbanSettings({ associationSettings, par - - - - - {t("production.labels.compact")} - - - - - {t("production.labels.cardcolor")} - - + {renderSwitchItem( + "compact", + compact, + setCompact, + "production.labels.compact", + "production.labels.tall", + "production.labels.wide" + )} + {renderSwitchItem( + "cardcolor", + colored, + setColored, + "production.labels.cardcolor", + "production.labels.on", + "production.labels.off" + )} - - - {t("production.labels.model_info")} - - - - - {t("production.labels.ownr_nm")} - - - - - {t("production.labels.clm_no")} - - - - - {t("production.labels.ins_co_nm")} - - - - - {t("production.labels.employeeassignments")} - - - - - {t("production.labels.actual_in")} - - - - - {t("production.labels.scheduled_completion")} - - - - - {t("production.labels.ats")} - - - - - {t("production.labels.production_note")} - - - - - {t("production.labels.sublets")} - - - - - {t("production.labels.partsstatus")} - - + {[ + "model_info", + "ownr_nm", + "clm_no", + "ins_co_nm", + "employeeassignments", + "actual_in", + "scheduled_completion", + "ats", + "production_note", + "sublets", + "partsstatus" + ].map((item) => renderCheckboxItem(item, `production.labels.${item}`))} @@ -172,7 +154,7 @@ export default function ProductionBoardKanbanSettings({ associationSettings, par - diff --git a/client/src/components/production-board-kanban/trello-board/components/Lane/ItemComponent.jsx b/client/src/components/production-board-kanban/trello-board/components/Lane/ItemComponent.jsx new file mode 100644 index 000000000..885fadc02 --- /dev/null +++ b/client/src/components/production-board-kanban/trello-board/components/Lane/ItemComponent.jsx @@ -0,0 +1,9 @@ +import React from "react"; + +const ItemComponent = ({ children, maxCardHeight, maxCardWidth, ...props }) => ( +
+ {children} +
+); + +export default ItemComponent; diff --git a/client/src/components/production-board-kanban/trello-board/components/Lane/ItemWrapper.jsx b/client/src/components/production-board-kanban/trello-board/components/Lane/ItemWrapper.jsx new file mode 100644 index 000000000..2af6453d8 --- /dev/null +++ b/client/src/components/production-board-kanban/trello-board/components/Lane/ItemWrapper.jsx @@ -0,0 +1,9 @@ +import React from "react"; + +const ItemWrapper = React.memo(({ children, ...props }) => ( +
+ {children} +
+)); + +export default ItemWrapper; diff --git a/client/src/components/production-board-kanban/trello-board/components/Lane/ListComponent.jsx b/client/src/components/production-board-kanban/trello-board/components/Lane/ListComponent.jsx new file mode 100644 index 000000000..794578df1 --- /dev/null +++ b/client/src/components/production-board-kanban/trello-board/components/Lane/ListComponent.jsx @@ -0,0 +1,9 @@ +import React, { forwardRef } from "react"; + +const ListComponent = forwardRef(({ style, children, ...props }, ref) => ( +
+ {children} +
+)); + +export default ListComponent; diff --git a/client/src/components/production-board-kanban/trello-board/controllers/Lane.jsx b/client/src/components/production-board-kanban/trello-board/controllers/Lane.jsx index 08f178a96..c90000d28 100644 --- a/client/src/components/production-board-kanban/trello-board/controllers/Lane.jsx +++ b/client/src/components/production-board-kanban/trello-board/controllers/Lane.jsx @@ -1,4 +1,4 @@ -import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; import PropTypes from "prop-types"; import { bindActionCreators } from "redux"; import { connect } from "react-redux"; @@ -15,24 +15,9 @@ import { selectTechnician } from "../../../../redux/tech/tech.selectors.js"; import ProductionBoardCard from "../../../production-board-kanban-card/production-board-kanban-card.component.jsx"; import HeightMemoryWrapper from "../components/Lane/HeightMemoryWrapper.jsx"; import SizeMemoryWrapper from "../components/Lane/SizeMemoryWrapper.jsx"; - -const ListComponent = forwardRef(({ style, children, ...props }, ref) => ( -
- {children} -
-)); - -const ItemComponent = ({ children, maxCardHeight, maxCardWidth, ...props }) => ( -
- {children} -
-); - -const ItemWrapper = React.memo(({ children, ...props }) => ( -
- {children} -
-)); +import ListComponent from "../components/Lane/ListComponent.jsx"; +import ItemComponent from "../components/Lane/ItemComponent.jsx"; +import ItemWrapper from "../components/Lane/ItemWrapper.jsx"; /** * Lane is a React component that represents a lane in a Trello-like board. @@ -170,6 +155,8 @@ const Lane = ({ const componentProps = orientation === "vertical" ? verticalProps : horizontalProps; + // If the lane is collapsed, we want to render a div instead of the virtualized list, and we want to set the height to the max height of the lane so that + // the lane doesn't shrink when collapsed (in horizontal mode) const finalComponentProps = collapsed ? orientation === "horizontal" ? { @@ -180,19 +167,19 @@ const Lane = ({ : {} : componentProps; + // If the lane is horizontal and collapsed, we want to override the minHeight style so that the lane doesn't shrink to 0 height const shouldOverride = orientation !== "horizontal" && (collapsed || !renderedCards.length); + + // If the lane is horizontal and collapsed, we want to render a placeholder so that the lane doesn't shrink to 0 height and grows when + // a card is dragged over it const shouldRenderPlaceholder = orientation !== "horizontal" && (collapsed || renderedCards.length === 0); - const hasKey = - orientation === "vertical" - ? { - key: id - } - : {}; + // Super magic key to maintain max height on the lane when cards are added / removed / resized / etc + const itemKey = `${id}-${orientation}-${cardSettings?.compact}-${renderedCards.length}-${cardSettings?.cardSize}`; return ( ); }, - [orientation, collapsed, isVisible, renderDraggable, maxLaneHeight, setMaxLaneHeight, maxCardWidth, id] + [ + orientation, + collapsed, + isVisible, + renderDraggable, + maxLaneHeight, + setMaxLaneHeight, + maxCardWidth, + id, + cardSettings + ] ); const renderDragContainer = useCallback( diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 43ac55662..85689a62b 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -2759,7 +2759,13 @@ "settings": "Error saving board settings: {{error}}" }, "labels": { - "orientation": "Orientation", + "on": "On", + "off": "Off", + "wide": "Wide", + "tall": "Tall", + "vertical": "Vertical", + "horizontal": "Horizontal", + "orientation": "Board Orientation", "card_size": "Card Size", "model_info": "Model Info", "actual_in": "Actual In", @@ -2775,11 +2781,11 @@ "qbo_usa": "QBO USA" } }, - "cardcolor": "Card Colors", + "cardcolor": "Colored Cards", "cardsettings": "Card Settings", "clm_no": "Claim Number", "comment": "Comment", - "compact": "Compact", + "compact": "Compact Cards", "detailpriority": "D/P", "employeeassignments": "Employee Assignments", "employeesearch": "Employee Search", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index d65e54245..2785c962a 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -2742,6 +2742,14 @@ "settings": "" }, "labels": { + "on": "", + "off": "", + "wide": "", + "tall": "", + "vertical": "", + "horizontal": "", + "orientation": "", + "card_size": "", "model_info": "", "actual_in": "", "alert": "",