Skip to content

Commit

Permalink
Merge pull request #560 from Sienci-Labs/MI-1525-features-job-progress
Browse files Browse the repository at this point in the history
Features: Job Progress
  • Loading branch information
sophiabeluli authored Oct 10, 2024
2 parents 4b5b534 + 0b3955e commit eaa8caa
Show file tree
Hide file tree
Showing 16 changed files with 1,104 additions and 602 deletions.
289 changes: 181 additions & 108 deletions src/app/src/application.css

Large diffs are not rendered by default.

80 changes: 58 additions & 22 deletions src/app/src/components/shadcn/Progress.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,66 @@
// https://ui.shadcn.com/docs/components/progress

"use client"
'use client';

import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress"
import * as React from 'react';
import * as ProgressPrimitive from '@radix-ui/react-progress';

import cx from "classnames"
import cx from 'classnames';

interface Props {
Bit?: string;
className?: string;
value: number;
style?: React.CSSProperties;
}

const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
>(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root
ref={ref}
className={cx(
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
className
)}
{...props}
React.ElementRef<
typeof ProgressPrimitive.Root & React.ForwardRefExoticComponent<Props>
>,
React.ComponentPropsWithoutRef<
typeof ProgressPrimitive.Root & React.ForwardRefExoticComponent<Props>
>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-primary transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
))
Progress.displayName = ProgressPrimitive.Root.displayName
>(({ className, value, style, Bit, ...props }, ref) => (
<div className="overflow-visible relative h-4 w-full rounded-full">
<ProgressPrimitive.Root
ref={ref}
className={cx('relative h-4 w-full rounded-full', className)}
{...props}
>
<div className="overflow-hidden h-full w-full">
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 transition-all bg-black"
style={{
transform: `translateX(-${100 - (value || 0)}%)`,
}}
/>
</div>
{Bit && (
<div
className="h-full w-full flex-1 transition-all absolute bottom-0"
style={{
transform: `translateX(-${100 - (value || 0)}%)`,
}}
>
<img
src={Bit}
className="absolute bottom-0 right-[-5px] h-14"
/>
</div>
)}
</ProgressPrimitive.Root>
{/* <div className="absolute bottom-0 left-0 transition-all flex-1 h-full w-full">
<img
src={Bit}
style={{
transform: `translateX(-${100 - (value || 0)}%)`,
}}
className="h-14"
/>
</div> */}
</div>
));
Progress.displayName = ProgressPrimitive.Root.displayName;

export { Progress }
export { Progress };
48 changes: 23 additions & 25 deletions src/app/src/definitions/general.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { GRBL_ACTIVE_STATES, GRBL_HAL_ACTIVE_STATES } from "../constants";

import { GRBL_ACTIVE_STATES, GRBL_HAL_ACTIVE_STATES } from '../constants';

// Types

Expand All @@ -12,39 +11,38 @@ export type GRBL_ACTIVE_STATES_T =
export type GRBL_HAL_ACTIVE_STATES_T =
(typeof GRBL_HAL_ACTIVE_STATES)[keyof typeof GRBL_HAL_ACTIVE_STATES];


// Inerfaces

export interface BasicObject {
[key: string]: string | number | boolean | Array<any> | BasicObject,
};
[key: string]: string | number | boolean | Array<any> | BasicObject;
}

export interface BasicPosition {
x: number,
y: number,
z: number,
a?: number,
x: number;
y: number;
z: number;
a?: number;
b?: number;
c?: number;
};
}

export interface BBox {
min: {
x: number,
y: number,
z: number,
},
x: number;
y: number;
z: number;
};
max: {
x: number,
y: number,
z: number,
},
delta: {
x: number,
y: number,
z: number,
}
};
x: number;
y: number;
z: number;
};
delta?: {
x: number;
y: number;
z: number;
};
}

export interface Shuttle {
feedrateMin: number;
Expand All @@ -55,4 +53,4 @@ export interface Shuttle {

export interface MDI {
disabled: boolean;
}
}
116 changes: 69 additions & 47 deletions src/app/src/features/JobControl/ControlButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,67 @@ import {
START,
STOP,
WORKFLOW_STATE_IDLE,
WORKFLOW_STATE_PAUSED
} from "../../constants";
import controller from "app/lib/controller";
import cx from "classnames";
import { includes } from "lodash";
import { GRBL_ACTIVE_STATES_T } from "app/definitions/general";
import { WORKFLOW_STATES_T } from "app/store/definitions";
import { PiPause } from "react-icons/pi";
import { FiOctagon } from "react-icons/fi";
import { IoPlayOutline } from "react-icons/io5";
import { useEffect, useState } from "react";

type MACHINE_CONTROL_BUTTONS_T = (typeof MACHINE_CONTROL_BUTTONS)[keyof typeof MACHINE_CONTROL_BUTTONS];
WORKFLOW_STATE_PAUSED,
} from '../../constants';
import controller from 'app/lib/controller';
import cx from 'classnames';
import { includes } from 'lodash';
import { GRBL_ACTIVE_STATES_T } from 'app/definitions/general';
import { WORKFLOW_STATES_T } from 'app/store/definitions';
import { PiPause } from 'react-icons/pi';
import { FiOctagon } from 'react-icons/fi';
import { IoPlayOutline } from 'react-icons/io5';
import { useEffect, useState } from 'react';

type MACHINE_CONTROL_BUTTONS_T =
(typeof MACHINE_CONTROL_BUTTONS)[keyof typeof MACHINE_CONTROL_BUTTONS];

interface ControlButtonProps {
type: MACHINE_CONTROL_BUTTONS_T,
workflow: { state: WORKFLOW_STATES_T },
activeState: GRBL_ACTIVE_STATES_T,
isConnected: boolean,
fileLoaded: boolean
};
type: MACHINE_CONTROL_BUTTONS_T;
workflow: { state: WORKFLOW_STATES_T };
activeState: GRBL_ACTIVE_STATES_T;
isConnected: boolean;
fileLoaded: boolean;
}

interface Message {
[key: MACHINE_CONTROL_BUTTONS_T]: string
};
[key: MACHINE_CONTROL_BUTTONS_T]: string;
}

interface Icons {
[key: MACHINE_CONTROL_BUTTONS_T]: JSX.Element
};
[key: MACHINE_CONTROL_BUTTONS_T]: JSX.Element;
}

interface OnClick {
[key: MACHINE_CONTROL_BUTTONS_T]: () => void
};
[key: MACHINE_CONTROL_BUTTONS_T]: () => void;
}

const ControlButton: React.FC<ControlButtonProps> = ({ type, workflow, activeState, isConnected, fileLoaded }) => {
const ControlButton: React.FC<ControlButtonProps> = ({
type,
workflow,
activeState,
isConnected,
fileLoaded,
}) => {
const isDisabled = (): boolean => {
if (!isConnected || !fileLoaded) {
return true;
} else if (
(type === START && (activeState === GRBL_ACTIVE_STATE_IDLE)) ||
(type === PAUSE && (activeState === GRBL_ACTIVE_STATE_RUN || activeState === GRBL_ACTIVE_STATE_HOLD)) ||
(type === STOP && (activeState === GRBL_ACTIVE_STATE_RUN || activeState === GRBL_ACTIVE_STATE_HOLD || activeState === GRBL_ACTIVE_STATE_ALARM))
(type === START &&
(activeState === GRBL_ACTIVE_STATE_IDLE ||
activeState === GRBL_ACTIVE_STATE_HOLD)) ||
(type === PAUSE &&
(activeState === GRBL_ACTIVE_STATE_RUN ||
activeState === GRBL_ACTIVE_STATE_HOLD)) ||
(type === STOP &&
(activeState === GRBL_ACTIVE_STATE_RUN ||
activeState === GRBL_ACTIVE_STATE_HOLD ||
activeState === GRBL_ACTIVE_STATE_ALARM))
) {
return false;
}
return true;
}
};

const [disabled, setDisabled] = useState(isDisabled());

Expand All @@ -63,14 +77,22 @@ const ControlButton: React.FC<ControlButtonProps> = ({ type, workflow, activeSta
});

const handleRun = (): void => {
console.assert(includes([WORKFLOW_STATE_IDLE, WORKFLOW_STATE_PAUSED], workflow.state) || activeState === GRBL_ACTIVE_STATE_HOLD);
console.assert(
includes(
[WORKFLOW_STATE_IDLE, WORKFLOW_STATE_PAUSED],
workflow.state,
) || activeState === GRBL_ACTIVE_STATE_HOLD,
);

if (workflow.state === WORKFLOW_STATE_IDLE) {
controller.command('gcode:start');
return;
}

if (workflow.state === WORKFLOW_STATE_PAUSED || activeState === GRBL_ACTIVE_STATE_HOLD) {
if (
workflow.state === WORKFLOW_STATE_PAUSED ||
activeState === GRBL_ACTIVE_STATE_HOLD
) {
controller.command('gcode:resume');
}
};
Expand All @@ -82,36 +104,36 @@ const ControlButton: React.FC<ControlButtonProps> = ({ type, workflow, activeSta
};

const message: Message = {
START: "Start",
PAUSE: "Pause",
STOP: "Stop"
}
START: 'Start',
PAUSE: 'Pause',
STOP: 'Stop',
};

const icons: Icons = {
START: <IoPlayOutline className="text-4xl" />,
PAUSE: <PiPause className="text-3xl" />,
STOP: <FiOctagon className="text-3xl" />
STOP: <FiOctagon className="text-3xl" />,
};

const onClick: OnClick = {
START: handleRun,
PAUSE: handlePause,
STOP: handleStop
STOP: handleStop,
};

return (
<div className="flex justify-center items-center">
<button
type="button"
className={cx(
"grid grid-cols-[1fr_2fr] gap-[1px] items-center h-12 w-24 px-2 rounded border-solid border-gray-600 duration-150 ease-in-out",
"[box-shadow:_0.4px_0.4px_2px_2px_var(--tw-shadow-color)] shadow-gray-500",
'grid grid-cols-[1fr_2fr] gap-[1px] items-center h-12 w-24 px-2 rounded border-solid border-gray-600 duration-150 ease-in-out',
'[box-shadow:_0.4px_0.4px_2px_2px_var(--tw-shadow-color)] shadow-gray-500',
{
"bg-gray-300 text-gray-600": disabled,
"bg-green-600 text-white": !disabled && type === START,
"bg-orange-400 text-white": !disabled && type === PAUSE,
"bg-red-500 text-white": !disabled && type === STOP
}
'bg-gray-300 text-gray-600': disabled,
'bg-green-600 text-white': !disabled && type === START,
'bg-orange-400 text-white': !disabled && type === PAUSE,
'bg-red-500 text-white': !disabled && type === STOP,
},
)}
title={type}
onClick={onClick[type]}
Expand All @@ -122,6 +144,6 @@ const ControlButton: React.FC<ControlButtonProps> = ({ type, workflow, activeSta
</button>
</div>
);
}
};

export default ControlButton;
export default ControlButton;
Loading

0 comments on commit eaa8caa

Please sign in to comment.