Progress Commit

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-05-16 16:41:39 -04:00
parent 095e1e9789
commit d47ae64bd6
11 changed files with 5174 additions and 24727 deletions

29610
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -17,10 +17,10 @@
"@reduxjs/toolkit": "^2.2.4",
"@sentry/cli": "^2.31.2",
"@sentry/react": "^7.114.0",
"@splitsoftware/splitio-react": "^1.11.1",
"@splitsoftware/splitio-react": "^1.12.0",
"@tanem/react-nprogress": "^5.0.51",
"@vitejs/plugin-react": "^4.2.1",
"antd": "^5.17.0",
"antd": "^5.17.2",
"apollo-link-logger": "^2.0.1",
"apollo-link-sentry": "^3.3.0",
"autosize": "^6.0.1",
@@ -32,9 +32,9 @@
"dotenv": "^16.4.5",
"env-cmd": "^10.1.0",
"exifr": "^7.1.3",
"firebase": "^10.11.1",
"firebase": "^10.12.0",
"graphql": "^16.6.0",
"i18next": "^23.11.3",
"i18next": "^23.11.4",
"i18next-browser-languagedetector": "^7.2.1",
"immutability-helper": "^3.1.1",
"kuika-smooth-dnd": "^1.0.0",
@@ -62,7 +62,7 @@
"react-product-fruits": "^2.2.6",
"react-redux": "^9.1.2",
"react-resizable": "^3.0.5",
"react-router-dom": "^6.23.0",
"react-router-dom": "^6.23.1",
"react-scripts": "^5.0.1",
"react-sticky": "^6.0.3",
"react-virtualized": "^9.22.5",
@@ -73,7 +73,7 @@
"redux-saga": "^1.3.0",
"redux-state-sync": "^3.1.4",
"reselect": "^5.1.0",
"sass": "^1.77.0",
"sass": "^1.77.1",
"socket.io-client": "^4.7.5",
"styled-components": "^6.1.11",
"subscriptions-transport-ws": "^0.11.0",

View File

@@ -22,7 +22,7 @@ const CardColorLegend = ({ bodyshop }) => {
});
return (
<Col>
<Col style={{ marginLeft: "15px" }}>
<Typography>{t("production.labels.legend")}</Typography>
<List
grid={{

View File

@@ -1,4 +1,4 @@
import { SyncOutlined } from "@ant-design/icons";
import { SyncOutlined, UnorderedListOutlined } from "@ant-design/icons";
import { useApolloClient } from "@apollo/client";
import Board from "../../components/trello-board/index";
import { Button, Grid, notification, Space, Statistic } from "antd";
@@ -54,7 +54,10 @@ export function ProductionBoardKanbanComponent({
const [isMoving, setIsMoving] = useState(false);
const [orientation, setOrientation] = useState("vertical");
const { t } = useTranslation();
useEffect(() => {
const boardData = createBoardData(
[...bodyshop.md_ro_statuses.production_statuses, ...(bodyshop.md_ro_statuses.additional_board_statuses || [])],
@@ -71,6 +74,11 @@ export function ProductionBoardKanbanComponent({
const client = useApolloClient();
// Create a function that toggles the orientation when the button is clicked
const toggleOrientation = () => {
setOrientation((prevOrientation) => (prevOrientation === "horizontal" ? "vertical" : "horizontal"));
};
const handleDragEnd = async (cardId, sourceLaneId, targetLaneId, position, cardDetails) => {
logImEXEvent("kanban_drag_end");
@@ -106,33 +114,41 @@ export function ProductionBoardKanbanComponent({
}
const newChildCardNewParent = newChildCard ? cardId : null;
const update = await client.mutate({
mutation: generate_UPDATE_JOB_KANBAN(
oldChildCard ? oldChildCard.id : null,
oldChildCardNewParent,
cardId,
movedCardNewKanbanParent,
targetLaneId,
newChildCard ? newChildCard.id : null,
newChildCardNewParent
)
});
try {
const update = await client.mutate({
mutation: generate_UPDATE_JOB_KANBAN(
oldChildCard ? oldChildCard.id : null,
oldChildCardNewParent,
cardId,
movedCardNewKanbanParent,
targetLaneId,
newChildCard ? newChildCard.id : null,
newChildCardNewParent
)
});
insertAuditTrail({
jobid: cardId,
operation: AuditTrailMapping.jobstatuschange(targetLaneId),
type: "jobstatuschange"
});
insertAuditTrail({
jobid: cardId,
operation: AuditTrailMapping.jobstatuschange(targetLaneId),
type: "jobstatuschange"
});
if (update.errors) {
if (update.errors) {
notification["error"]({
message: t("production.errors.boardupdate", {
message: JSON.stringify(update.errors)
})
});
}
} catch (error) {
notification["error"]({
message: t("production.errors.boardupdate", {
message: JSON.stringify(update.errors)
message: error.message
})
});
} finally {
setIsMoving(false);
}
setIsMoving(false);
};
const totalHrs = data
@@ -174,7 +190,7 @@ export function ProductionBoardKanbanComponent({
<Sticky>
{({ style }) => (
<div className="react-trello-column-header" style={{ ...style, zIndex: "99", backgroundColor: "#e3e3e3" }}>
{title}
<UnorderedListOutlined style={{ marginRight: "5px" }} /> {title}
</div>
)}
</Sticky>
@@ -182,7 +198,7 @@ export function ProductionBoardKanbanComponent({
const NormalHeader = ({ title }) => (
<div className="react-trello-column-header" style={{ backgroundColor: "#e3e3e3" }}>
{title}
<UnorderedListOutlined style={{ marginRight: "5px" }} /> {title}
</div>
);
@@ -229,6 +245,7 @@ export function ProductionBoardKanbanComponent({
</Button>
<ProductionBoardFilters filter={filter} setFilter={setFilter} loading={isMoving} />
<ProductionBoardKanbanCardSettings associationSettings={associationSettings} />
<Button onClick={toggleOrientation}>Toggle Orientation</Button>
</Space>
}
/>
@@ -242,6 +259,8 @@ export function ProductionBoardKanbanComponent({
handleDragEnd={handleDragEnd}
style={{ height: "100%", backgroundColor: "transparent" }}
components={components}
orientation={orientation}
collapsibleLanes
/>
</StickyContainer>
) : (
@@ -252,6 +271,8 @@ export function ProductionBoardKanbanComponent({
handleDragEnd={handleDragEnd}
style={{ backgroundColor: "transparent" }}
components={components}
collapsibleLanes
orientation={orientation}
/>
</div>
)}

View File

@@ -6,10 +6,11 @@ import NewLaneForm from "./NewLaneForm.jsx";
import NewCardForm from "./NewCardForm.jsx";
import AddCardLink from "./AddCardLink";
import NewLaneSection from "./NewLaneSection.jsx";
import { BoardWrapper, GlobalStyle, ScrollableLane, Section } from "../styles/Base";
import { BoardWrapper, GlobalStyleHorizontal, GlobalStyleVertical, ScrollableLane, Section } from "../styles/Base";
const exports = {
GlobalStyle,
GlobalStyleHorizontal,
GlobalStyleVertical,
BoardWrapper,
Loader,
ScrollableLane,

View File

@@ -3,15 +3,22 @@ import classNames from "classnames";
import { useState } from "react";
import { v1 } from "uuid";
const Board = ({ id, className, components, ...additionalProps }) => {
const Board = ({ id, className, components, orientation, ...additionalProps }) => {
const [storeId] = useState(id || v1());
const allClassNames = classNames("react-trello-board", className || "");
const Styles = orientation === "horizontal" ? components.GlobalStyleHorizontal : components.GlobalStyleVertical;
return (
<>
<components.GlobalStyle />
<BoardContainer components={components} {...additionalProps} id={storeId} className={allClassNames} />
<Styles />
<BoardContainer
components={components}
orientation={orientation}
{...additionalProps}
id={storeId}
className={allClassNames}
/>
</>
);
};

View File

@@ -141,12 +141,13 @@ class BoardContainer extends Component {
laneStyle,
onCardMoveAcrossLanes,
t,
orientation,
...otherProps
} = this.props;
const { addLaneMode } = this.state;
// Stick to whitelisting attributes to segregate board and lane props
const passthroughProps = pick(this.props, [
const passThroughProps = pick(this.props, [
"onCardMoveAcrossLanes",
"onLaneScroll",
"onLaneDelete",
@@ -169,19 +170,19 @@ class BoardContainer extends Component {
"handleDragEnd",
"cardDragClass",
"editLaneTitle",
"t"
"orientation"
]);
return (
<components.BoardWrapper style={style} {...otherProps} draggable={false}>
<components.BoardWrapper style={style} orientation={orientation} {...otherProps} draggable={false}>
<PopoverWrapper>
<Container
orientation="horizontal"
orientation={orientation === "vertical" ? "vertical" : "horizontal"}
onDragStart={this.onDragStart}
dragClass={laneDragClass}
dropClass={laneDropClass}
onDrop={this.onLaneDrop}
lockAxis="x"
lockAxis={orientation === "vertical" ? "y" : "x"}
getChildPayload={(index) => this.getLaneDetails(index)}
groupName={this.groupName}
>
@@ -201,7 +202,7 @@ class BoardContainer extends Component {
cardStyle={this.props.cardStyle || lane.cardStyle}
editable={editable && !lane.disallowAddingCard}
{...otherProps}
{...passthroughProps}
{...passThroughProps}
/>
);
return draggable && laneDraggable ? <Draggable key={lane.id}>{laneToRender}</Draggable> : laneToRender;
@@ -209,9 +210,9 @@ class BoardContainer extends Component {
</Container>
</PopoverWrapper>
{canAddLanes && (
<Container orientation="horizontal">
<Container orientation={orientation === "vertical" ? "vertical" : "horizontal"}>
{editable && !addLaneMode ? (
<components.NewLaneSection t={t} onClick={this.showEditableLane} />
<components.NewLaneSection onClick={this.showEditableLane} />
) : (
addLaneMode && <components.NewLaneForm onCancel={this.hideEditableLane} onAdd={this.addNewLane} t={t} />
)}
@@ -257,7 +258,9 @@ BoardContainer.propTypes = {
cardDragClass: PropTypes.string,
laneDragClass: PropTypes.string,
laneDropClass: PropTypes.string,
onCardMoveAcrossLanes: PropTypes.func.isRequired
onCardMoveAcrossLanes: PropTypes.func.isRequired,
t: PropTypes.func,
orientation: PropTypes.string
};
BoardContainer.defaultProps = {
@@ -281,7 +284,8 @@ BoardContainer.defaultProps = {
cardDraggable: true,
cardDragClass: "react_trello_dragClass",
laneDragClass: "react_trello_dragLaneClass",
laneDropClass: ""
laneDropClass: "",
orientation: "horizontal"
};
const mapStateToProps = (state) => {

View File

@@ -157,7 +157,8 @@ class Lane extends Component {
cardDropClass,
tagStyle,
cardStyle,
components
components,
orientation
} = this.props;
const { addCardMode, collapsed } = this.state;
@@ -191,7 +192,7 @@ class Lane extends Component {
return (
<components.ScrollableLane ref={this.laneDidMount} isDraggingOver={isDraggingOver}>
<Container
orientation="vertical" // TODO This is where we would switch the card orientation.
// orientation={orientation === "horizontal" ? "vertical" : "horizontal"}
groupName={this.groupName}
dragClass={cardDragClass}
dropClass={cardDropClass}
@@ -254,6 +255,7 @@ class Lane extends Component {
onLaneUpdate,
onCardUpdate,
onCardMoveAcrossLanes,
orientation,
...otherProps
} = this.props;
const allClassNames = classNames("react-trello-lane", this.props.className || "");
@@ -265,6 +267,7 @@ class Lane extends Component {
onClick={() => onLaneClick && onLaneClick(id)}
draggable={false}
className={allClassNames}
orientation={orientation}
>
{this.renderHeader({ id, cards, ...otherProps })}
{this.renderDragContainer(isDraggingOver)}
@@ -308,7 +311,13 @@ Lane.propTypes = {
cardDraggable: PropTypes.bool,
cardDragClass: PropTypes.string,
cardDropClass: PropTypes.string,
canAddLanes: PropTypes.bool
canAddLanes: PropTypes.bool,
hideCardDeleteIcon: PropTypes.bool,
components: PropTypes.object,
getCardDetails: PropTypes.func,
handleDragStart: PropTypes.func,
handleDragEnd: PropTypes.func,
orientation: PropTypes.string
};
Lane.defaultProps = {
@@ -319,7 +328,25 @@ Lane.defaultProps = {
editable: false,
onLaneUpdate: () => {},
onCardAdd: () => {},
onCardUpdate: () => {}
onCardUpdate: () => {},
onCardDelete: () => {},
onBeforeCardDelete: () => {},
onLaneDelete: () => {},
onLaneClick: () => {},
onLaneScroll: () => {},
onCardClick: () => {},
onCardMoveAcrossLanes: () => {},
draggable: false,
laneDraggable: false,
cardDraggable: true,
collapsibleLanes: false,
droppable: true,
canAddLanes: false,
hideCardDeleteIcon: false,
components: {},
handleDragStart: () => {},
handleDragEnd: () => {},
orientation: "vertical"
};
const mapDispatchToProps = (dispatch) => ({

View File

@@ -1,26 +0,0 @@
const REPLACE_TABLE = {
customLaneHeader: "components.LaneHeader",
newLaneTemplate: "components.NewLaneSection",
newCardTemplate: "components.NewCardForm",
children: "components.Card",
customCardLayout: "components.Card",
addLaneTitle: '`t` function with key "Add another lane"',
addCardLink: '`t` function with key "Click to add card"'
};
const warn = (prop) => {
const use = REPLACE_TABLE[prop];
console.warn(
`react-trello property '${prop}' is removed. Use '${use}' instead. More - https://github.com/rcdexta/react-trello/blob/master/UPGRADE.md`
);
};
const deprecationWarning = (props) => {
Object.keys(REPLACE_TABLE).forEach((key) => {
if (props.hasOwnProperty(key)) {
warn(key);
}
});
};
export default deprecationWarning;

View File

@@ -5,7 +5,6 @@ import Container from "./dnd/Container.jsx";
import BoardContainer from "./controllers/BoardContainer.jsx";
import Board from "./controllers/Board.jsx";
import Lane from "./controllers/Lane.jsx";
import deprecationWarnings from "./helpers/deprecationWarnings";
import DefaultComponents from "./components";
import widgets from "./widgets/index";
@@ -19,8 +18,6 @@ export { DefaultComponents as components };
// Enhanced default export using arrow function for simplicity
const TrelloBoard = ({ components, ...otherProps }) => {
deprecationWarnings(otherProps);
return (
<StyleSheetManager shouldForwardProp={shouldForwardProp}>
<Board components={{ ...DefaultComponents, ...components }} {...otherProps} />

View File

@@ -1,7 +1,30 @@
import { PopoverContainer, PopoverContent } from "react-popopo";
import styled, { createGlobalStyle, css } from "styled-components";
export const GlobalStyle = createGlobalStyle`
const getBoardWrapperStyles = (props) => {
if (props.orientation === "vertical") {
return ` `;
}
if (props.orientation === "horizontal") {
return `
display: flex;
flex-direction: row;
align-items: flex-start;
`;
}
return "";
};
const getSectionStyles = (props) => {
if (props.orientation === "horizontal") {
return `
display: inline-flex;
`;
}
return "";
};
export const GlobalStyleHorizontal = createGlobalStyle`
.comPlainTextContentEditable {
-webkit-user-modify: read-write-plaintext-only;
cursor: text;
@@ -25,9 +48,11 @@ export const GlobalStyle = createGlobalStyle`
.icon-overflow-menu-horizontal:before {
content: "\\E91F";
}
.icon-lg, .icon-sm {
color: #798d99;
}
.icon-lg {
height: 32px;
font-size: 16px;
@@ -36,6 +61,69 @@ export const GlobalStyle = createGlobalStyle`
}
`;
export const GlobalStyleVertical = createGlobalStyle`
.comPlainTextContentEditable {
-webkit-user-modify: read-write-plaintext-only;
cursor: text;
}
.comPlainTextContentEditable--has-placeholder::before {
content: attr(placeholder);
opacity: 0.5;
color: inherit;
cursor: text;
}
.react_trello_dragClass {
transform: rotate(3deg);
}
.react_trello_dragLaneClass {
transform: rotate(3deg);
}
.icon-overflow-menu-horizontal:before {
content: "\\E91F";
}
.icon-lg, .icon-sm {
color: #798d99;
}
.icon-lg {
height: 32px;
font-size: 16px;
line-height: 32px;
width: 32px;
}
.smooth-dnd-container {
//min-height: 100px; // Not needed, just for extra landing space
}
.smooth-dnd-container.horizontal {
white-space: break-spaces;
flex-direction: column;
}
.react-trello-lane {
border: 1px solid #ccc;
border-radius: 5px;
}
.react-trello-column-header {
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
text-align: left;
}
.react-trello-board {
overflow-y: hidden !important;
}
`;
export const CustomPopoverContainer = styled(PopoverContainer)`
position: absolute;
right: 10px;
@@ -58,6 +146,7 @@ export const CustomPopoverContent = styled(PopoverContent)`
padding: 5px;
left: 50%;
transform: translateX(-50%);
${(props) =>
props.active &&
`
@@ -67,11 +156,13 @@ export const CustomPopoverContent = styled(PopoverContent)`
`} &::before {
visibility: hidden;
}
a {
color: rgba(255, 255, 255, 0.56);
padding: 0.5em 1em;
margin: 0;
text-decoration: none;
&:hover {
background-color: #00bcd4 !important;
color: #37474f;
@@ -85,11 +176,7 @@ export const BoardWrapper = styled.div`
overflow-y: scroll;
padding: 5px;
color: #393939;
display: flex;
flex-direction: row;
align-items: flex-start;
// TODO: This was commented out to match existing board style
//height: 100vh;
${getBoardWrapperStyles};
`;
export const Header = styled.header`
@@ -105,9 +192,7 @@ export const Section = styled.section`
margin: 5px 5px;
position: relative;
padding: 10px;
display: inline-flex;
// TODO: This was commented out to match existing board style
//max-height: 90%;
${getSectionStyles};
flex-direction: column;
`;
@@ -282,6 +367,7 @@ export const InlineInput = styled.textarea`
border: 0;
padding: 0 8px;
outline: 0;
${(props) =>
props.border &&
css`