- Checkpoint, so so much
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -15,7 +15,6 @@ import ProductionAlert from "../production-list-columns/production-list-columns.
|
||||
import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component";
|
||||
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
|
||||
|
||||
import "./production-board-card.styles.scss";
|
||||
import dayjs from "../../utils/day";
|
||||
|
||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||
@@ -62,7 +61,7 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe
|
||||
return metadata?.labhrs && metadata?.larhrs
|
||||
? metadata.labhrs.aggregate.sum.mod_lb_hrs + metadata.larhrs.aggregate.sum.mod_lb_hrs
|
||||
: 0;
|
||||
}, [metadata]);
|
||||
}, [metadata?.labhrs, metadata?.larhrs]);
|
||||
|
||||
const bgColor = useMemo(() => cardColor(bodyshop.ssbuckets, totalHrs), [bodyshop.ssbuckets, totalHrs]);
|
||||
const contrastYIQ = useMemo(() => getContrastYIQ(bgColor), [bgColor]);
|
||||
@@ -77,7 +76,14 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe
|
||||
}}
|
||||
title={
|
||||
<Space>
|
||||
<ProductionAlert record={card} key="alert" />
|
||||
<ProductionAlert
|
||||
record={{
|
||||
id: card.id,
|
||||
production_vars: card?.metadata.production_vars,
|
||||
refetch: card?.refetch
|
||||
}}
|
||||
key="alert"
|
||||
/>
|
||||
{metadata?.suspended && <PauseCircleOutlined style={{ color: "orangered" }} />}
|
||||
{metadata?.iouparent && (
|
||||
<Tooltip title={t("jobs.labels.iou")}>
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
import { SyncOutlined, UnorderedListOutlined } from "@ant-design/icons";
|
||||
import { SyncOutlined } from "@ant-design/icons";
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import Board from "../../components/trello-board/index";
|
||||
import { Button, notification, Skeleton, Space, Statistic } from "antd";
|
||||
import { PageHeader } from "@ant-design/pro-layout";
|
||||
import React, { useEffect, useMemo, useState, useCallback } from "react";
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import { generate_UPDATE_JOB_KANBAN } from "../../graphql/jobs.queries";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component";
|
||||
import ProductionBoardFilters from "../production-board-filters/production-board-filters.component";
|
||||
import ProductionBoardCard from "../production-board-kanban-card/production-board-kanban-card.component";
|
||||
import ProductionListDetailComponent from "../production-list-detail/production-list-detail.component";
|
||||
import CardColorLegend from "../production-board-kanban-card/production-board-kanban-card-color-legend.component";
|
||||
import "./production-board-kanban.styles.scss";
|
||||
import { createBoardData, createFakeBoardData } from "./production-board-kanban.utils.js";
|
||||
import { createBoardData } from "./production-board-kanban.utils.js";
|
||||
import ProductionBoardKanbanSettings from "./production-board-kanban.settings.component.jsx";
|
||||
import cloneDeep from "lodash/cloneDeep";
|
||||
import isEqual from "lodash/isEqual";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
technician: selectTechnician
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
@@ -40,20 +37,16 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
)
|
||||
});
|
||||
|
||||
export function ProductionBoardKanbanComponent({
|
||||
data,
|
||||
bodyshop,
|
||||
refetch,
|
||||
technician,
|
||||
insertAuditTrail,
|
||||
associationSettings
|
||||
}) {
|
||||
export function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTrail, associationSettings }) {
|
||||
const [boardLanes, setBoardLanes] = useState({ lanes: [] });
|
||||
const [filter, setFilter] = useState({ search: "", employeeId: null });
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isMoving, setIsMoving] = useState(false);
|
||||
|
||||
const orientation = associationSettings?.kanban_settings?.orientation ? "vertical" : "horizontal";
|
||||
const orientation = useMemo(
|
||||
() => (associationSettings?.kanban_settings?.orientation ? "vertical" : "horizontal"),
|
||||
[associationSettings]
|
||||
);
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -63,7 +56,7 @@ export function ProductionBoardKanbanComponent({
|
||||
}, [associationSettings]);
|
||||
|
||||
useEffect(() => {
|
||||
const newBoardData = createFakeBoardData(
|
||||
const newBoardData = createBoardData(
|
||||
[...bodyshop.md_ro_statuses.production_statuses, ...(bodyshop.md_ro_statuses.additional_board_statuses || [])],
|
||||
data,
|
||||
filter
|
||||
@@ -202,15 +195,6 @@ export function ProductionBoardKanbanComponent({
|
||||
[data]
|
||||
);
|
||||
|
||||
const Header = useCallback(
|
||||
({ title }) => (
|
||||
<div className="react-trello-column-header" style={{ backgroundColor: "#e3e3e3" }}>
|
||||
<UnorderedListOutlined style={{ marginRight: "5px" }} /> {title.substring(0, 10)}
|
||||
</div>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
const cardSettings = useMemo(
|
||||
() =>
|
||||
associationSettings?.kanban_settings && Object.keys(associationSettings.kanban_settings).length > 0
|
||||
@@ -225,23 +209,12 @@ export function ProductionBoardKanbanComponent({
|
||||
production_note: true,
|
||||
employeeassignments: true,
|
||||
scheduled_completion: true,
|
||||
stickyheader: false,
|
||||
cardcolor: false,
|
||||
orientation: false
|
||||
},
|
||||
[associationSettings]
|
||||
);
|
||||
|
||||
const components = useMemo(
|
||||
() => ({
|
||||
Card: (cardProps) => (
|
||||
<ProductionBoardCard card={cardProps} technician={technician} bodyshop={bodyshop} cardSettings={cardSettings} />
|
||||
),
|
||||
LaneHeader: Header
|
||||
}),
|
||||
[Header, bodyshop, cardSettings, technician]
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return <Skeleton active />;
|
||||
}
|
||||
@@ -270,13 +243,7 @@ export function ProductionBoardKanbanComponent({
|
||||
/>
|
||||
{cardSettings.cardcolor && <CardColorLegend cardSettings={cardSettings} bodyshop={bodyshop} />}
|
||||
<ProductionListDetailComponent jobs={data} />
|
||||
<Board
|
||||
data={boardLanes}
|
||||
onDragEnd={onDragEnd}
|
||||
components={components}
|
||||
collapsibleLanes
|
||||
orientation={orientation}
|
||||
/>
|
||||
<Board data={boardLanes} onDragEnd={onDragEnd} orientation={orientation} cardSettings={cardSettings} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,147 +2,27 @@
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
//.react-trello-card {
|
||||
// border-radius: 3px;
|
||||
// background-color: #fff;
|
||||
// padding: 4px;
|
||||
// margin-bottom: 7px;
|
||||
//}
|
||||
|
||||
// .react-trello-card-skeleton,
|
||||
// .react-trello-card,
|
||||
// .react-trello-card-adder-form {
|
||||
// box-sizing: border-box;
|
||||
// max-width: 145px;
|
||||
// min-width: 145px;
|
||||
// }
|
||||
|
||||
.react-trello-card--dragging {
|
||||
.item .is-dragging {
|
||||
box-shadow: 2px 2px grey;
|
||||
rotate: 5deg;
|
||||
}
|
||||
|
||||
.react-trello-card__description {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.react-trello-card__title {
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 5px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
//.react-trello-column {
|
||||
// padding: 10px;
|
||||
// border-radius: 2px;
|
||||
// background-color: #eee;
|
||||
// margin: 5px;
|
||||
//}
|
||||
|
||||
.react-trello-column input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-form {
|
||||
border-radius: 3px;
|
||||
background-color: #fff;
|
||||
padding: 10px;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-form input {
|
||||
border: 0px;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-button {
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
border: 1px solid #ccc;
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 20px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-button:hover {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-form__title {
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 5px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
}
|
||||
.height-preserving-container:empty {
|
||||
min-height: calc(var(--child-height));
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-form__title:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-form__description {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-form__description:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-form__button {
|
||||
background-color: #eee;
|
||||
border: none;
|
||||
padding: 5px;
|
||||
width: 45%;
|
||||
margin-top: 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.react-trello-card-adder-form__button:hover {
|
||||
transition: 0.3s;
|
||||
cursor: pointer;
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.react-trello-column-header {
|
||||
font-weight: bold;
|
||||
background-color: #e3e3e3;
|
||||
.icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.react-trello-column-header input:focus {
|
||||
outline: none;
|
||||
.production-alert {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.react-trello-column-header__button {
|
||||
color: #333333;
|
||||
background-color: #ffffff;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
|
||||
.react-trello-column-header__button:hover,
|
||||
.react-trello-column-header__button:focus,
|
||||
.react-trello-column-header__button:active {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.react-trello-column-adder-button {
|
||||
border: 2px dashed #eee;
|
||||
height: 132px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.react-trello-column-adder-button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -43,18 +43,14 @@ const ProductionListColumnAlert = ({ record, insertAuditTrail }) => {
|
||||
jobid: record.id,
|
||||
operation: AuditTrailMapping.alertToggle(newAlertState),
|
||||
type: "alertToggle"
|
||||
}).then(() => {
|
||||
if (record.refetch) record.refetch();
|
||||
});
|
||||
|
||||
if (record.refetch) record.refetch();
|
||||
}, [updateAlert, insertAuditTrail, record]);
|
||||
|
||||
return (
|
||||
<div style={{ height: "19px" }}>
|
||||
{record.production_vars?.alert && (
|
||||
<Button className="production-alert" icon={<ExclamationCircleFilled />} onClick={handleAlertToggle} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
if (!record.production_vars?.alert) return null;
|
||||
|
||||
return <Button className="production-alert" icon={<ExclamationCircleFilled />} onClick={handleAlertToggle} />;
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ProductionListColumnAlert);
|
||||
|
||||
@@ -349,7 +349,7 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme
|
||||
key: "alert",
|
||||
sorter: (a, b) => Number(a.production_vars?.alert || false) - Number(b.production_vars?.alert || false),
|
||||
sortOrder: state.sortedInfo.columnKey === "alert" && state.sortedInfo.order,
|
||||
render: (text, record) => <ProductionListColumnAlert record={record} />
|
||||
render: (text, record) => <ProductionListColumnAlert record={{ record }} />
|
||||
},
|
||||
{
|
||||
title: i18n.t("production.labels.note"),
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import LaneFooter from "./Lane/LaneFooter";
|
||||
|
||||
import { BoardWrapper, StyleHorizontal, GlobalStyle, StyleVertical, ScrollableLane, Section } from "../styles/Base";
|
||||
import { BoardWrapper, StyleHorizontal, StyleVertical, ScrollableLane, Section } from "../styles/Base";
|
||||
|
||||
const exports = {
|
||||
StyleHorizontal,
|
||||
StyleVertical,
|
||||
GlobalStyle,
|
||||
BoardWrapper,
|
||||
ScrollableLane,
|
||||
LaneFooter,
|
||||
|
||||
@@ -1,27 +1,21 @@
|
||||
import { BoardContainer } from "../index";
|
||||
import { useMemo, useState } from "react";
|
||||
import { v1 } from "uuid";
|
||||
import { GlobalStyle } from "../styles/Base.js";
|
||||
import { useMemo } from "react";
|
||||
import { StyleHorizontal, StyleVertical } from "../styles/Base.js";
|
||||
|
||||
const Board = ({ id, className, components, orientation, ...additionalProps }) => {
|
||||
const [storeId] = useState(id || v1());
|
||||
|
||||
const allClassNames = useMemo(() => `react-trello-board ${className || ""}`.trim(), [className]);
|
||||
const Board = ({ id, className, orientation, cardSettings, ...additionalProps }) => {
|
||||
const OrientationStyle = useMemo(
|
||||
() => (orientation === "horizontal" ? components.StyleHorizontal : components.StyleVertical),
|
||||
[orientation, components.StyleHorizontal, components.StyleVertical]
|
||||
() => (orientation === "horizontal" ? StyleHorizontal : StyleVertical),
|
||||
[orientation]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<GlobalStyle />
|
||||
<OrientationStyle>
|
||||
<BoardContainer
|
||||
components={components}
|
||||
orientation={orientation}
|
||||
cardSettings={cardSettings}
|
||||
{...additionalProps}
|
||||
id={storeId}
|
||||
className={allClassNames}
|
||||
className="react-trello-board"
|
||||
/>
|
||||
</OrientationStyle>
|
||||
</>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React, { useCallback, useEffect, useState, useMemo } from "react";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { DragDropContext } from "../dnd/lib";
|
||||
import PropTypes from "prop-types";
|
||||
import pick from "lodash/pick";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import Lane from "./Lane";
|
||||
import { PopoverWrapper } from "react-popopo";
|
||||
@@ -15,26 +14,23 @@ import { BoardWrapper } from "../styles/Base.js";
|
||||
*
|
||||
* @component
|
||||
* @param {Object} props - Component props
|
||||
* @param {string} props.id - The unique identifier for the board
|
||||
* @param {Object} props.components - Custom components to use in the board
|
||||
* @param {Object} props.data - The initial data for the board
|
||||
* @param {Function} props.onDragEnd - Callback function when a drag ends
|
||||
* @param {Function} props.laneSortFunction - Callback function when a drag ends
|
||||
* @param {string} props.orientation - The orientation of the board ("horizontal" or "vertical")
|
||||
* @param {Function} props.eventBusHandle - Function to handle events from the event bus
|
||||
* @param {Object} props.reducerData - The initial data for the Redux reducer
|
||||
* @param {Object} props.otherProps - Any other props to pass to the board
|
||||
* @returns {JSX.Element} A Trello-like board
|
||||
*/
|
||||
const BoardContainer = ({
|
||||
id,
|
||||
components,
|
||||
data,
|
||||
onDataChange = () => {},
|
||||
onDragEnd = () => {},
|
||||
laneSortFunction = () => {},
|
||||
orientation = "horizontal",
|
||||
cardSettings = {},
|
||||
eventBusHandle,
|
||||
reducerData,
|
||||
...otherProps
|
||||
reducerData
|
||||
}) => {
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
@@ -42,8 +38,6 @@ const BoardContainer = ({
|
||||
const dispatch = useDispatch();
|
||||
const currentReducerData = useSelector((state) => (state.trello.lanes ? state.trello : {}));
|
||||
|
||||
const groupName = `TrelloBoard${id}`;
|
||||
|
||||
const wireEventBus = useCallback(() => {
|
||||
const eventBus = {
|
||||
publish: (event) => {
|
||||
@@ -98,24 +92,6 @@ const BoardContainer = ({
|
||||
setIsDragging(true);
|
||||
}, [setIsDragging]);
|
||||
|
||||
const passThroughProps = useMemo(
|
||||
() =>
|
||||
pick(
|
||||
{
|
||||
id,
|
||||
components,
|
||||
data,
|
||||
onDataChange,
|
||||
orientation,
|
||||
eventBusHandle,
|
||||
reducerData,
|
||||
...otherProps
|
||||
},
|
||||
["laneSortFunction", "collapsibleLanes", "orientation"]
|
||||
),
|
||||
[id, components, data, onDataChange, orientation, eventBusHandle, reducerData, otherProps]
|
||||
);
|
||||
|
||||
const onLaneDrag = useCallback(
|
||||
async ({ draggableId, type, source, reason, mode, destination, combine }) => {
|
||||
setIsDragging(false);
|
||||
@@ -143,44 +119,50 @@ const BoardContainer = ({
|
||||
},
|
||||
[dispatch, onDragEnd]
|
||||
);
|
||||
|
||||
// id: PropTypes.string.isRequired,
|
||||
// title: PropTypes.node,
|
||||
// index: PropTypes.number,
|
||||
// laneSortFunction: PropTypes.func,
|
||||
// cards: PropTypes.array,
|
||||
// orientation: PropTypes.string,
|
||||
// isProcessing: PropTypes.bool,
|
||||
// cardSettings: PropTypes.object,
|
||||
// technician: PropTypes.object,
|
||||
// bodyshop: PropTypes.object
|
||||
return (
|
||||
<BoardWrapper orientation={orientation}>
|
||||
<PopoverWrapper>
|
||||
<DragDropContext onDragEnd={onLaneDrag} onDragStart={onDragStart} contextId={groupName}>
|
||||
<PopoverWrapper>
|
||||
<BoardWrapper orientation={orientation}>
|
||||
<DragDropContext onDragEnd={onLaneDrag} onDragStart={onDragStart} contextId="production-board">
|
||||
{currentReducerData.lanes.map((lane, index) => {
|
||||
const { id, droppable, ...laneOtherProps } = lane;
|
||||
return (
|
||||
<Lane
|
||||
key={id}
|
||||
boardId={groupName}
|
||||
components={components}
|
||||
id={id}
|
||||
key={lane.id}
|
||||
id={lane.id}
|
||||
title={lane.title}
|
||||
index={index}
|
||||
{...laneOtherProps}
|
||||
{...passThroughProps}
|
||||
laneSortFunction={laneSortFunction}
|
||||
orientation={orientation}
|
||||
cards={lane.cards}
|
||||
isDragging={isDragging}
|
||||
isProcessing={isProcessing}
|
||||
cardSettings={cardSettings}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</DragDropContext>
|
||||
</PopoverWrapper>
|
||||
</BoardWrapper>
|
||||
</BoardWrapper>
|
||||
</PopoverWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
BoardContainer.propTypes = {
|
||||
id: PropTypes.string,
|
||||
components: PropTypes.object,
|
||||
actions: PropTypes.object,
|
||||
data: PropTypes.object.isRequired,
|
||||
reducerData: PropTypes.object,
|
||||
onDataChange: PropTypes.func,
|
||||
eventBusHandle: PropTypes.func,
|
||||
laneSortFunction: PropTypes.func,
|
||||
collapsibleLanes: PropTypes.bool,
|
||||
handleDragEnd: PropTypes.func,
|
||||
orientation: PropTypes.string
|
||||
};
|
||||
|
||||
@@ -2,31 +2,29 @@ import React, { forwardRef, useCallback, useEffect, useMemo, useState } from "re
|
||||
import PropTypes from "prop-types";
|
||||
import { bindActionCreators } from "redux";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import * as actions from "../../../redux/trello/trello.actions.js";
|
||||
import { Draggable, Droppable } from "../dnd/lib";
|
||||
import { Virtuoso, VirtuosoGrid } from "react-virtuoso";
|
||||
import HeightPreservingItem from "../components/Lane/HeightPreservingItem.jsx";
|
||||
import { Section } from "../styles/Base.js";
|
||||
import LaneFooter from "../components/Lane/LaneFooter.jsx";
|
||||
import { UnorderedListOutlined } from "@ant-design/icons";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../../redux/user/user.selectors.js";
|
||||
import { selectTechnician } from "../../../redux/tech/tech.selectors.js";
|
||||
import ProductionBoardCard from "../../production-board-kanban-card/production-board-kanban-card.component.jsx";
|
||||
|
||||
const Lane = ({
|
||||
actions,
|
||||
id,
|
||||
boardId,
|
||||
title,
|
||||
index,
|
||||
isProcessing,
|
||||
laneSortFunction,
|
||||
style = {},
|
||||
cardStyle = {},
|
||||
cards,
|
||||
collapsibleLanes = false,
|
||||
|
||||
components = {},
|
||||
cardSettings = {},
|
||||
orientation = "vertical",
|
||||
className,
|
||||
...otherProps
|
||||
technician,
|
||||
bodyshop
|
||||
}) => {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [isVisible, setIsVisible] = useState(true);
|
||||
@@ -37,187 +35,183 @@ const Lane = ({
|
||||
return () => clearTimeout(timer);
|
||||
}, [cards.length]);
|
||||
|
||||
const sortCards = useCallback((cards, sortFunction) => {
|
||||
const sortedCards = useMemo(() => {
|
||||
if (!cards) return [];
|
||||
if (!sortFunction) return cards;
|
||||
return cards.concat().sort((card1, card2) => sortFunction(card1, card2));
|
||||
}, []);
|
||||
if (!laneSortFunction) return cards;
|
||||
return [...cards].sort(laneSortFunction);
|
||||
}, [cards, laneSortFunction]);
|
||||
|
||||
const toggleLaneCollapsed = useCallback(() => {
|
||||
collapsibleLanes && setCollapsed(!collapsed);
|
||||
}, [collapsibleLanes, collapsed]);
|
||||
setCollapsed((prevCollapsed) => !prevCollapsed);
|
||||
}, []);
|
||||
|
||||
const Card = React.memo(({ provided, item: card, isDragging }) => {
|
||||
return (
|
||||
<div
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
ref={provided.innerRef}
|
||||
style={provided.draggableProps.style}
|
||||
className={`item ${isDragging ? "is-dragging" : ""}`}
|
||||
key={card.id}
|
||||
>
|
||||
<components.Card key={card.id} style={card.style || cardStyle} className="react-trello-card" {...card} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const renderDraggable = (index, item) => {
|
||||
if (!item) {
|
||||
console.log("null Item");
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Draggable draggableId={item.id} index={index} key={item.id} isDragDisabled={isProcessing}>
|
||||
{(provided, snapshot) => <Card provided={provided} item={item} isDragging={snapshot.isDragging} />}
|
||||
</Draggable>
|
||||
);
|
||||
};
|
||||
|
||||
const ItemWrapper = ({ children, ...props }) => (
|
||||
<div {...props} className="item-wrapper">
|
||||
{children}
|
||||
</div>
|
||||
const renderDraggable = useCallback(
|
||||
(index, card) => {
|
||||
if (!card) {
|
||||
console.log("null card");
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Draggable draggableId={card.id} index={index} key={card.id} isDragDisabled={isProcessing}>
|
||||
{(provided, snapshot) => (
|
||||
<div
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
ref={provided.innerRef}
|
||||
style={provided.draggableProps.style}
|
||||
className={`item ${snapshot.isDragging ? "is-dragging" : ""}`}
|
||||
key={card.id}
|
||||
>
|
||||
<ProductionBoardCard
|
||||
technician={technician}
|
||||
bodyshop={bodyshop}
|
||||
cardSettings={cardSettings}
|
||||
key={card.id}
|
||||
style={card.style}
|
||||
card={card}
|
||||
className="react-trello-card"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
},
|
||||
[isProcessing, technician, bodyshop, cardSettings]
|
||||
);
|
||||
|
||||
const renderDroppable = (provided, renderedCards) => {
|
||||
const Component = orientation === "vertical" ? VirtuosoGrid : Virtuoso;
|
||||
const FinalComponent = collapsed ? "div" : Component;
|
||||
|
||||
const commonProps = {
|
||||
useWindowScroll: true,
|
||||
data: renderedCards
|
||||
};
|
||||
|
||||
const verticalProps = {
|
||||
...commonProps,
|
||||
// we are using the useWindowScroll, so we don't need to pass the scrollerRef
|
||||
// scrollerRef: provided.innerRef,
|
||||
listClassName: "grid-container",
|
||||
itemClassName: "grid-item",
|
||||
components: {
|
||||
List: forwardRef(({ style, children, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
{...props}
|
||||
style={{
|
||||
...style
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)),
|
||||
Item: ({ children, ...props }) => <div {...props}>{children}</div>
|
||||
},
|
||||
itemContent: (index, item) => <ItemWrapper>{renderDraggable(index, item)}</ItemWrapper>,
|
||||
overscan: { main: 10, reverse: 10 }
|
||||
};
|
||||
|
||||
const horizontalProps = {
|
||||
...commonProps,
|
||||
components: { Item: HeightPreservingItem },
|
||||
overscan: { main: 1, reverse: 1 },
|
||||
itemContent: (index, item) => renderDraggable(index, item),
|
||||
scrollerRef: provided.innerRef
|
||||
};
|
||||
|
||||
const componentProps = orientation === "vertical" ? verticalProps : horizontalProps;
|
||||
|
||||
// A collapsed lane does not need to render the Virtuoso component
|
||||
const finalComponentProps = collapsed ? {} : componentProps;
|
||||
|
||||
return (
|
||||
<div style={{ height: "100%" }}>
|
||||
<div
|
||||
{...provided.droppableProps}
|
||||
ref={provided.innerRef}
|
||||
className={allClassNames}
|
||||
style={{ ...provided.droppableProps.style }}
|
||||
>
|
||||
{isVisible && <FinalComponent {...finalComponentProps} />}
|
||||
{(orientation === "horizontal" || renderedCards.length === 0 || collapsed) && provided.placeholder}
|
||||
</div>
|
||||
const ItemWrapper = useCallback(
|
||||
({ children, ...props }) => (
|
||||
<div {...props} className="item-wrapper">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
const renderDragContainer = () => {
|
||||
const renderedCards = sortCards(cards, laneSortFunction);
|
||||
const renderDroppable = useCallback(
|
||||
(provided, renderedCards) => {
|
||||
const Component = orientation === "vertical" ? VirtuosoGrid : Virtuoso;
|
||||
const FinalComponent = collapsed ? "div" : Component;
|
||||
|
||||
return (
|
||||
const commonProps = {
|
||||
useWindowScroll: true,
|
||||
data: renderedCards
|
||||
};
|
||||
|
||||
const verticalProps = {
|
||||
...commonProps,
|
||||
listClassName: "grid-container",
|
||||
itemClassName: "grid-item",
|
||||
components: {
|
||||
List: forwardRef(({ style, children, ...props }, ref) => (
|
||||
<div ref={ref} {...props} style={{ ...style }}>
|
||||
{children}
|
||||
</div>
|
||||
)),
|
||||
Item: ({ children, ...props }) => <div {...props}>{children}</div>
|
||||
},
|
||||
itemContent: (index, item) => <ItemWrapper>{renderDraggable(index, item)}</ItemWrapper>,
|
||||
overscan: { main: 10, reverse: 10 }
|
||||
};
|
||||
|
||||
const horizontalProps = {
|
||||
...commonProps,
|
||||
components: { Item: HeightPreservingItem },
|
||||
overscan: { main: 3, reverse: 3 },
|
||||
itemContent: (index, item) => renderDraggable(index, item),
|
||||
scrollerRef: provided.innerRef
|
||||
};
|
||||
|
||||
const componentProps = orientation === "vertical" ? verticalProps : horizontalProps;
|
||||
const finalComponentProps = collapsed ? {} : componentProps;
|
||||
|
||||
return (
|
||||
<div style={{ height: "100%" }}>
|
||||
<div
|
||||
{...provided.droppableProps}
|
||||
ref={provided.innerRef}
|
||||
className={`react-trello-lane ${collapsed ? "lane-collapsed" : ""}`}
|
||||
style={{ ...provided.droppableProps.style }}
|
||||
>
|
||||
{isVisible && <FinalComponent {...finalComponentProps} />}
|
||||
{(orientation === "horizontal" || renderedCards.length === 0 || collapsed) && provided.placeholder}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
[orientation, collapsed, isVisible, renderDraggable]
|
||||
);
|
||||
|
||||
const renderDragContainer = useCallback(
|
||||
() => (
|
||||
<Droppable
|
||||
droppableId={id}
|
||||
index={index}
|
||||
type="lane"
|
||||
direction={orientation === "horizontal" ? "vertical" : "grid"}
|
||||
mode="virtual"
|
||||
renderClone={(provided, snapshot, rubric) => (
|
||||
<Card
|
||||
clone={true}
|
||||
provided={provided}
|
||||
isDragging={snapshot.isDragging}
|
||||
item={renderedCards[rubric.source.index]}
|
||||
/>
|
||||
)}
|
||||
renderClone={(provided, snapshot, rubric) => {
|
||||
const card = sortedCards[rubric.source.index];
|
||||
return (
|
||||
<div
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
ref={provided.innerRef}
|
||||
style={provided.draggableProps.style}
|
||||
className={`item ${snapshot.isDragging ? "is-dragging" : ""}`}
|
||||
key={card.id}
|
||||
>
|
||||
<ProductionBoardCard
|
||||
technician={technician}
|
||||
bodyshop={bodyshop}
|
||||
cardSettings={cardSettings}
|
||||
key={card.id}
|
||||
style={card.style}
|
||||
className="react-trello-card"
|
||||
card={card}
|
||||
clone={false}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
>
|
||||
{(provided) => renderDroppable(provided, renderedCards)}
|
||||
{(provided) => renderDroppable(provided, sortedCards)}
|
||||
</Droppable>
|
||||
);
|
||||
};
|
||||
|
||||
const renderHeader = (pickedProps) => {
|
||||
return <components.LaneHeader {...pickedProps} onDoubleClick={toggleLaneCollapsed} />;
|
||||
};
|
||||
|
||||
const allClassNames = useMemo(
|
||||
() => `react-trello-lane ${collapsed ? "lane-collapsed" : ""} ${className || ""}`.trim(),
|
||||
[collapsed, className]
|
||||
),
|
||||
[id, index, orientation, renderDroppable, sortedCards, technician, bodyshop, cardSettings]
|
||||
);
|
||||
const passedProps = {
|
||||
actions,
|
||||
id,
|
||||
boardId,
|
||||
title,
|
||||
index,
|
||||
laneSortFunction,
|
||||
style,
|
||||
cardStyle,
|
||||
cards,
|
||||
collapsibleLanes,
|
||||
|
||||
components,
|
||||
orientation,
|
||||
className,
|
||||
...otherProps
|
||||
};
|
||||
return (
|
||||
<Section key={id} orientation={orientation} {...passedProps}>
|
||||
{renderHeader({ id, cards, ...passedProps })}
|
||||
<Section key={id} orientation={orientation}>
|
||||
<div onDoubleClick={toggleLaneCollapsed} className="react-trello-column-header">
|
||||
<UnorderedListOutlined className="icon" /> {title}
|
||||
</div>
|
||||
{renderDragContainer()}
|
||||
{collapsibleLanes && <LaneFooter onClick={toggleLaneCollapsed} collapsed={collapsed} />}
|
||||
<LaneFooter onClick={toggleLaneCollapsed} collapsed={collapsed} />
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
Lane.propTypes = {
|
||||
actions: PropTypes.object,
|
||||
id: PropTypes.string.isRequired,
|
||||
boardId: PropTypes.string,
|
||||
title: PropTypes.node,
|
||||
index: PropTypes.number,
|
||||
laneSortFunction: PropTypes.func,
|
||||
style: PropTypes.object,
|
||||
cardStyle: PropTypes.object,
|
||||
cards: PropTypes.array,
|
||||
label: PropTypes.string,
|
||||
collapsibleLanes: PropTypes.bool,
|
||||
components: PropTypes.object,
|
||||
orientation: PropTypes.string
|
||||
orientation: PropTypes.string,
|
||||
isProcessing: PropTypes.bool,
|
||||
cardSettings: PropTypes.object,
|
||||
technician: PropTypes.object,
|
||||
bodyshop: PropTypes.object
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
actions: bindActionCreators(actions, dispatch)
|
||||
});
|
||||
|
||||
export default connect(null, mapDispatchToProps)(Lane);
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
technician: selectTechnician
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Lane);
|
||||
|
||||
@@ -2,21 +2,17 @@ import React from "react";
|
||||
|
||||
import BoardContainer from "./controllers/BoardContainer.jsx";
|
||||
import Board from "./controllers/Board.jsx";
|
||||
import Lane from "./controllers/Lane.jsx";
|
||||
import DefaultComponents from "./components";
|
||||
|
||||
import { StyleSheetManager } from "styled-components";
|
||||
import isPropValid from "@emotion/is-prop-valid";
|
||||
|
||||
export { BoardContainer, Lane };
|
||||
|
||||
export { DefaultComponents as components };
|
||||
export { BoardContainer };
|
||||
|
||||
// Enhanced default export using arrow function for simplicity
|
||||
const TrelloBoard = ({ components, ...otherProps }) => {
|
||||
const TrelloBoard = ({ ...otherProps }) => {
|
||||
return (
|
||||
<StyleSheetManager shouldForwardProp={shouldForwardProp}>
|
||||
<Board components={{ ...DefaultComponents, ...components }} {...otherProps} />
|
||||
<Board {...otherProps} />
|
||||
</StyleSheetManager>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PopoverContainer, PopoverContent } from "react-popopo";
|
||||
import styled, { createGlobalStyle, css } from "styled-components";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
const getBoardWrapperStyles = (props) => {
|
||||
if (props.orientation === "vertical") {
|
||||
@@ -7,7 +7,6 @@ const getBoardWrapperStyles = (props) => {
|
||||
}
|
||||
if (props.orientation === "horizontal") {
|
||||
// TODO: The white-space: nowrap; would be a good place to offer further customization
|
||||
// This will be put in the lane settings and marked as 'Horizontal Wrapping'
|
||||
return `
|
||||
white-space: nowrap;
|
||||
`;
|
||||
@@ -21,13 +20,8 @@ const getSectionStyles = (props) => {
|
||||
return `
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
white-space: nowrap;
|
||||
// overflow-y: none;
|
||||
// overflow-y: none;
|
||||
min-width: 8.5%;
|
||||
flex-wrap: wrap;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
`;
|
||||
}
|
||||
return `
|
||||
@@ -47,52 +41,11 @@ const getLaneFooterStyles = (props) => {
|
||||
`;
|
||||
};
|
||||
|
||||
export const GlobalStyle = 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;
|
||||
}
|
||||
|
||||
.react-trello-column-header {
|
||||
border-radius: 5px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyleHorizontal = styled.div`
|
||||
.react-trello-lane {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 1px;
|
||||
overflow-y: visible;
|
||||
overflow-x: visible; // change this line
|
||||
}
|
||||
@@ -111,7 +64,14 @@ export const StyleHorizontal = styled.div`
|
||||
white-space: nowrap;
|
||||
min-width: 4%;
|
||||
}
|
||||
|
||||
.react-trello-column-header {
|
||||
border-radius: 5px;
|
||||
min-height: 15px;
|
||||
padding: 4px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.react-trello-card {
|
||||
height: auto;
|
||||
margin: 2px;
|
||||
@@ -120,9 +80,14 @@ export const StyleHorizontal = styled.div`
|
||||
|
||||
export const StyleVertical = styled.div`
|
||||
.react-trello-column-header {
|
||||
border-radius: 5px;
|
||||
min-height: 15px;
|
||||
padding: 5px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.react-trello-lane {
|
||||
min-height: 5px;
|
||||
height: 100%;
|
||||
@@ -144,15 +109,15 @@ export const StyleVertical = styled.div`
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
width: 8%; // TODO: THIS IS WHERE WE GET VERTICAL CARD CUSTOMIZATION
|
||||
display: flex;
|
||||
width: 250px; // TODO: (Note) This is where we will set the width of the cards in the vertical orientation
|
||||
align-content: stretch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.item {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
width: 250px; // TODO: (Note) This is where we will set the width of the cards in the vertical orientation
|
||||
}
|
||||
|
||||
.item-wrapper {
|
||||
@@ -172,52 +137,6 @@ export const StyleVertical = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export const CustomPopoverContainer = styled(PopoverContainer)`
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
flex-flow: column nowrap;
|
||||
`;
|
||||
|
||||
export const CustomPopoverContent = styled(PopoverContent)`
|
||||
visibility: hidden;
|
||||
margin-top: -5px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3);
|
||||
transition: all 0.3s ease 0ms;
|
||||
border-radius: 3px;
|
||||
min-width: 7em;
|
||||
flex-flow: column nowrap;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
padding: 5px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
${(props) =>
|
||||
props.active &&
|
||||
`
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition-delay: 100ms;
|
||||
`} &::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;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const BoardWrapper = styled.div`
|
||||
color: #393939;
|
||||
height: 100%;
|
||||
@@ -226,13 +145,6 @@ export const BoardWrapper = styled.div`
|
||||
${getBoardWrapperStyles};
|
||||
`;
|
||||
|
||||
export const Header = styled.header`
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
`;
|
||||
|
||||
export const Section = styled.section`
|
||||
background-color: #e3e3e3;
|
||||
border-radius: 3px;
|
||||
@@ -258,148 +170,8 @@ export const ScrollableLane = styled.div`
|
||||
justify-content: space-between;
|
||||
`;
|
||||
|
||||
export const Title = styled.span`
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
cursor: ${(props) => (props.draggable ? "grab" : `auto`)};
|
||||
width: 70%;
|
||||
`;
|
||||
|
||||
export const RightContent = styled.span`
|
||||
width: 38%;
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
font-size: 13px;
|
||||
`;
|
||||
|
||||
export const CardWrapper = styled.article`
|
||||
border-radius: 3px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
margin-bottom: 7px;
|
||||
max-width: 250px;
|
||||
min-width: 230px;
|
||||
`;
|
||||
|
||||
export const MovableCardWrapper = styled(CardWrapper)`
|
||||
&:hover {
|
||||
background-color: #f0f0f0;
|
||||
color: #000;
|
||||
}
|
||||
`;
|
||||
|
||||
export const CardHeader = styled(Header)`
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 6px;
|
||||
color: #000;
|
||||
`;
|
||||
|
||||
export const CardTitle = styled(Title)`
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
export const CardRightContent = styled(RightContent)`
|
||||
font-size: 10px;
|
||||
`;
|
||||
|
||||
export const Detail = styled.div`
|
||||
font-size: 12px;
|
||||
color: #4d4d4d;
|
||||
white-space: pre-wrap;
|
||||
`;
|
||||
|
||||
export const Footer = styled.div`
|
||||
border-top: 1px solid #eee;
|
||||
padding-top: 6px;
|
||||
text-align: right;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
`;
|
||||
|
||||
export const TagSpan = styled.span`
|
||||
padding: 2px 3px;
|
||||
border-radius: 3px;
|
||||
margin: 2px 5px;
|
||||
font-size: 70%;
|
||||
`;
|
||||
|
||||
export const AddCardLink = styled.a`
|
||||
border-radius: 0 0 3px 3px;
|
||||
color: #838c91;
|
||||
display: block;
|
||||
padding: 5px 2px;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
//background-color: #cdd2d4;
|
||||
color: #4d4d4d;
|
||||
text-decoration: underline;
|
||||
}
|
||||
`;
|
||||
|
||||
export const LaneTitle = styled.div`
|
||||
font-size: 15px;
|
||||
width: 268px;
|
||||
height: auto;
|
||||
`;
|
||||
|
||||
export const LaneSection = styled.section`
|
||||
background-color: #2b6aa3;
|
||||
border-radius: 3px;
|
||||
margin: 5px;
|
||||
position: relative;
|
||||
padding: 5px;
|
||||
display: inline-flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
export const NewLaneSection = styled(LaneSection)`
|
||||
width: 200px;
|
||||
`;
|
||||
|
||||
export const NewLaneButtons = styled.div`
|
||||
margin-top: 10px;
|
||||
`;
|
||||
|
||||
export const CardForm = styled.div`
|
||||
background-color: #e3e3e3;
|
||||
`;
|
||||
|
||||
export const InlineInput = styled.textarea`
|
||||
overflow-x: hidden; /* for Firefox (issue #5) */
|
||||
word-wrap: break-word;
|
||||
min-height: 18px;
|
||||
max-height: 112px; /* optional, but recommended */
|
||||
resize: none;
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: inherit;
|
||||
text-align: inherit;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
border-radius: 3px;
|
||||
border: 0;
|
||||
padding: 0 8px;
|
||||
outline: 0;
|
||||
|
||||
${(props) =>
|
||||
props.border &&
|
||||
css`
|
||||
&:focus {
|
||||
box-shadow: inset 0 0 0 2px #0079bf;
|
||||
}
|
||||
`} &:focus {
|
||||
background-color: white;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,154 +1,4 @@
|
||||
import styled from 'styled-components'
|
||||
import {CardWrapper, MovableCardWrapper} from './Base'
|
||||
|
||||
export const DeleteWrapper = styled.div`
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
right: 2px;
|
||||
cursor: pointer;
|
||||
`
|
||||
|
||||
export const GenDelButton = styled.button`
|
||||
transition: all 0.5s ease;
|
||||
display: inline-block;
|
||||
border: none;
|
||||
font-size: 15px;
|
||||
height: 15px;
|
||||
padding: 0;
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
width: 15px;
|
||||
background: inherit;
|
||||
cursor: pointer;
|
||||
`
|
||||
|
||||
export const DelButton = styled.button`
|
||||
transition: all 0.5s ease;
|
||||
display: inline-block;
|
||||
border: none;
|
||||
font-size: 8px;
|
||||
height: 15px;
|
||||
line-height: 1px;
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
width: 15px;
|
||||
background: inherit;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
|
||||
${MovableCardWrapper}:hover & {
|
||||
opacity: 1;
|
||||
}
|
||||
`
|
||||
|
||||
export const MenuButton = styled.button`
|
||||
transition: all 0.5s ease;
|
||||
display: inline-block;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
height: 15px;
|
||||
line-height: 1px;
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
width: 15px;
|
||||
background: inherit;
|
||||
cursor: pointer;
|
||||
`
|
||||
|
||||
export const LaneMenuHeader = styled.div`
|
||||
position: relative;
|
||||
margin-bottom: 4px;
|
||||
text-align: center;
|
||||
`
|
||||
|
||||
export const LaneMenuContent = styled.div`
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding: 0 12px 12px;
|
||||
`
|
||||
|
||||
export const LaneMenuItem = styled.div`
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
font-weight: 700;
|
||||
padding: 6px 12px;
|
||||
position: relative;
|
||||
margin: 0 -12px;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
background-color: #3179ba;
|
||||
color: #fff;
|
||||
}
|
||||
`
|
||||
|
||||
export const LaneMenuTitle = styled.span`
|
||||
box-sizing: border-box;
|
||||
color: #6b808c;
|
||||
display: block;
|
||||
line-height: 30px;
|
||||
border-bottom: 1px solid rgba(9, 45, 66, 0.13);
|
||||
margin: 0 6px;
|
||||
overflow: hidden;
|
||||
padding: 0 32px;
|
||||
position: relative;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
`
|
||||
|
||||
export const DeleteIcon = styled.span`
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
opacity: 1;
|
||||
overflow: hidden;
|
||||
border: 1px solid #83bd42;
|
||||
border-radius: 50%;
|
||||
padding: 4px;
|
||||
background-color: #83bd42;
|
||||
|
||||
${CardWrapper}:hover & {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:hover::before,
|
||||
&:hover::after {
|
||||
background: red;
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 2px;
|
||||
width: 60%;
|
||||
top: 45%;
|
||||
left: 20%;
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
&:before {
|
||||
-webkit-transform: rotate(45deg);
|
||||
-moz-transform: rotate(45deg);
|
||||
-o-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
&:after {
|
||||
-webkit-transform: rotate(-45deg);
|
||||
-moz-transform: rotate(-45deg);
|
||||
-o-transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
`
|
||||
import styled from "styled-components";
|
||||
|
||||
export const ExpandCollapseBase = styled.span`
|
||||
width: 36px;
|
||||
@@ -156,11 +6,11 @@ export const ExpandCollapseBase = styled.span`
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
`
|
||||
`;
|
||||
|
||||
export const CollapseBtn = styled(ExpandCollapseBase)`
|
||||
&:before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -171,7 +21,7 @@ export const CollapseBtn = styled(ExpandCollapseBase)`
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 4px;
|
||||
@@ -179,11 +29,11 @@ export const CollapseBtn = styled(ExpandCollapseBase)`
|
||||
border-left: 3px solid transparent;
|
||||
border-right: 3px solid transparent;
|
||||
}
|
||||
`
|
||||
`;
|
||||
|
||||
export const ExpandBtn = styled(ExpandCollapseBase)`
|
||||
&:before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -194,7 +44,7 @@ export const ExpandBtn = styled(ExpandCollapseBase)`
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 0px;
|
||||
@@ -202,50 +52,4 @@ export const ExpandBtn = styled(ExpandCollapseBase)`
|
||||
border-left: 3px solid transparent;
|
||||
border-right: 3px solid transparent;
|
||||
}
|
||||
`
|
||||
|
||||
export const AddButton = styled.button`
|
||||
background: #5aac44;
|
||||
color: #fff;
|
||||
transition: background 0.3s ease;
|
||||
min-height: 32px;
|
||||
padding: 4px 16px;
|
||||
vertical-align: top;
|
||||
margin-top: 0;
|
||||
margin-right: 8px;
|
||||
font-weight: bold;
|
||||
border-radius: 3px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0;
|
||||
`
|
||||
|
||||
export const CancelButton = styled.button`
|
||||
background: #999999;
|
||||
color: #fff;
|
||||
transition: background 0.3s ease;
|
||||
min-height: 32px;
|
||||
padding: 4px 16px;
|
||||
vertical-align: top;
|
||||
margin-top: 0;
|
||||
font-weight: bold;
|
||||
border-radius: 3px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0;
|
||||
`
|
||||
export const AddLaneLink = styled.button`
|
||||
background: #2b6aa3;
|
||||
border: none;
|
||||
color: #fff;
|
||||
transition: background 0.3s ease;
|
||||
min-height: 32px;
|
||||
padding: 4px 16px;
|
||||
vertical-align: top;
|
||||
margin-top: 0;
|
||||
margin-right: 0px;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0;
|
||||
`
|
||||
`;
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import styled, {keyframes} from 'styled-components'
|
||||
|
||||
const keyframeAnimation = keyframes`
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
20% {
|
||||
transform: scale(1, 2.2);
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
}
|
||||
`
|
||||
export const LoaderDiv = styled.div`
|
||||
text-align: center;
|
||||
margin: 15px 0;
|
||||
`
|
||||
|
||||
export const LoadingBar = styled.div`
|
||||
display: inline-block;
|
||||
margin: 0 2px;
|
||||
width: 4px;
|
||||
height: 18px;
|
||||
border-radius: 4px;
|
||||
animation: ${keyframeAnimation} 1s ease-in-out infinite;
|
||||
background-color: #777;
|
||||
|
||||
&:nth-child(1) {
|
||||
animation-delay: 0.0001s;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
animation-delay: 0.09s;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
animation-delay: 0.18s;
|
||||
}
|
||||
|
||||
&:nth-child(4) {
|
||||
animation-delay: 0.27s;
|
||||
}
|
||||
`
|
||||
Reference in New Issue
Block a user