Compare commits

...

10 Commits

Author SHA1 Message Date
6413ce0b9b Goodbye extraneous console logging...
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 20:05:59 -05:00
ffda5c6a61 ...
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 18:53:19 -05:00
37ada2d8f5 ...
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 18:47:48 -05:00
ff04bb36de Take that, Traefik!
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 18:39:23 -05:00
16f044d308 Motherfu...
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 18:06:46 -05:00
b6949a7673 Update CI/CD pipeline
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 17:37:36 -05:00
44932cf3e2 How was it working and then broken? I really hate Traefik somethimes...
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 17:28:22 -05:00
ef2846f626 Fixes for a few oddities and the Traefik issues
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 17:18:42 -05:00
4a0fe47000 What is up with traefik?
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 16:04:07 -05:00
fc013c9fa8 Goodbye, package-lock.json. We like node_modules. 2024-01-24 15:45:21 -05:00
10 changed files with 89 additions and 4120 deletions

View File

@@ -3,20 +3,21 @@ type: docker
name: Demo Deploy Pipeline name: Demo Deploy Pipeline
workspace: workspace:
path: /drone/bopeep path: /drone/walden
steps: steps:
- name: Deploy Container - name: Deploy Container
image: docker image: docker
privileged: true privileged: true
commands: commands:
- docker compose -f docker-compose.prod.yml build --pull --no-cache - docker compose -f docker-compose.prod.yml build
# - docker compose -f docker-compose.prod.yml build --pull --no-cache
- docker compose -f docker-compose.prod.yml up --remove-orphans --force-recreate --wait - docker compose -f docker-compose.prod.yml up --remove-orphans --force-recreate --wait
volumes: volumes:
- name: dockersock - name: dockersock
path: /var/run/docker.sock path: /var/run/docker.sock
- name: dockerconfig - name: dockerconfig
path: /drone/bopeep/.docker/config.json path: /drone/walden/.docker/config.json
- name: Send Status Notifications - name: Send Status Notifications
image: plugins/webhook image: plugins/webhook
privileged: true privileged: true

View File

@@ -12,8 +12,8 @@ services:
networks: networks:
- walden-backend - walden-backend
volumes: volumes:
- 'db:/data/db' - 'walden-db:/data/db'
- 'db:/data/configdb' - 'walden-db:/data/configdb'
restart: unless-stopped restart: unless-stopped
frontend: frontend:
@@ -26,16 +26,16 @@ services:
- NODE_ENV=production - NODE_ENV=production
- MONGO_URL=mongodb://mongo:27017/bopeep - MONGO_URL=mongodb://mongo:27017/bopeep
ports: ports:
- 3000:3000 - 3003:3000
labels: labels:
- 'traefik.enable=true' - 'traefik.enable=true'
- 'traefik.docker.network=docknet' - 'traefik.docker.network=docknet'
- 'traefik.http.routers.labs-bopeep.rule=Host(`area51.mifi.dev`) && PathPrefix(`/bopeep`)' - 'traefik.http.routers.labs-walden.rule=Host(`area51.mifi.dev`)'
- 'traefik.http.routers.labs-bopeep.entrypoints=websecure' - 'traefik.http.routers.labs-walden.entrypoints=websecure'
- 'traefik.http.routers.labs-bopeep.tls=true' - 'traefik.http.routers.labs-walden.tls=true'
- 'traefik.http.routers.labs-bopeep.tls.certresolver=letsencrypt' - 'traefik.http.routers.labs-walden.tls.certresolver=letsencrypt'
- 'traefik.http.routers.labs-bopeep.service=labs-bopeep-service' - 'traefik.http.routers.labs-walden.service=labs-walden-service'
- 'traefik.http.services.labs-bopeep-service.loadbalancer.server.port=3000' - 'traefik.http.services.labs-walden-service.loadbalancer.server.port=3000'
networks: networks:
- walden-backend - walden-backend
- docknet - docknet
@@ -49,5 +49,5 @@ networks:
external: true external: true
volumes: volumes:
db: walden-db:
external: false external: true

4058
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -18,29 +18,29 @@ export function Bins() {
switch (event.key) { switch (event.key) {
case 'ArrowDown': case 'ArrowDown':
event.preventDefault(); event.preventDefault();
setBin(Bin.LOSS); !!item && setBin(Bin.LOSS);
break; break;
case 'ArrowLeft': case 'ArrowLeft':
event.preventDefault(); event.preventDefault();
setBin(Bin.PROCESS); !!item && setBin(Bin.PROCESS);
break; break;
case 'ArrowRight': case 'ArrowRight':
event.preventDefault(); event.preventDefault();
setBin(Bin.SHOULDER_TAP); !!item && setBin(Bin.SHOULDER_TAP);
break; break;
case 'ArrowUp': case 'ArrowUp':
event.preventDefault(); event.preventDefault();
setBin(Bin.DONATE); !!item && setBin(Bin.DONATE);
break; break;
} }
}, [bin, item, setBin, setItem]); }, [item, setBin]);
useEffect(() => { useEffect(() => {
window.addEventListener('keydown', handleKeydown); window.addEventListener('keydown', handleKeydown);
return () => { return () => {
window.removeEventListener('keydown', handleKeydown); window.removeEventListener('keydown', handleKeydown);
}; };
}, []); }, [handleKeydown]);
return ( return (
<div className={styles.bins}> <div className={styles.bins}>

View File

@@ -15,7 +15,6 @@ export function ProductInfo() {
const { item, setItem } = useContext(BinnerContext); const { item, setItem } = useContext(BinnerContext);
const { processors } = useContext(SupplyChainContext); const { processors } = useContext(SupplyChainContext);
const [inputItem, setInputItem] = useState<Partial<ParsedBarcode> | null>(null); const [inputItem, setInputItem] = useState<Partial<ParsedBarcode> | null>(null);
const dateRef = useRef<HTMLInputElement>(null);
const weightRef = useRef<HTMLInputElement>(null); const weightRef = useRef<HTMLInputElement>(null);
const getProcessorByBarcodeId = useGetProcessorByBarcodeId(); const getProcessorByBarcodeId = useGetProcessorByBarcodeId();
@@ -32,8 +31,22 @@ export function ProductInfo() {
setItem(barcodeToProduct(`${inputItem?.product}${inputItem?.date}${inputItem?.processor}${inputItem?.weight}`)); setItem(barcodeToProduct(`${inputItem?.product}${inputItem?.date}${inputItem?.processor}${inputItem?.weight}`));
setInputItem(null); setInputItem(null);
} }
setIsEntryMode(!isCompleteItem(inputItem)); }, [inputItem]);
}, [inputItem])
const getDateString = (date: Date) => {
const yyyy = date.getFullYear();
let mm: number | string = date.getMonth() + 1;
let dd: number | string = date.getDate();
if (dd < 10) {
dd = '0' + dd;
}
if (mm < 10) {
mm = '0' + mm;
}
return `${yyyy}-${mm}-${dd}`;
}
return ( return (
<div className={styles.productInfo}> <div className={styles.productInfo}>
@@ -58,13 +71,13 @@ export function ProductInfo() {
<div className={styles.card}> <div className={styles.card}>
<label htmlFor="date">Packaged Date</label> <label htmlFor="date">Packaged Date</label>
<input <input
id="date" value={!!item ? ordinalToDate(item.date).toDateString() : ''} id="date"
type="date"
value={!!item ? getDateString(ordinalToDate(item.date)) : undefined}
contentEditable={isEntryMode} contentEditable={isEntryMode}
ref={dateRef} onChange={isEntryMode ? (e) => {
onChange={(e) => { setInputItem({ ...inputItem || {}, date: `${dateToOrdinal(new Date(e.currentTarget.valueAsNumber))}` })
dateRef.current.value = e.currentTarget.value; } : undefined}
setInputItem({ ...inputItem || {}, date: dateToOrdinal(new Date(e.currentTarget.value)) })
}}
/> />
</div> </div>
<div className={styles.card}> <div className={styles.card}>
@@ -86,26 +99,36 @@ export function ProductInfo() {
</div> </div>
<div className={styles.card}> <div className={styles.card}>
<label htmlFor="weight">Weight</label> <label htmlFor="weight">Weight</label>
{isEntryMode ? (
<div className={styles.inputWithButton}> <div className={styles.inputWithButton}>
<input <input
id="weight" id="weight"
value={!!item ? `${item.weight} lbs.` : ''}
contentEditable={false} contentEditable={false}
tabIndex={-1} tabIndex={-1}
ref={weightRef} ref={weightRef}
/> />
{isEntryMode && (
<button <button
onClick={(e) => { onClick={(e) => {
const weight = faker.number.int({ min: 1000, max: 1999 }); const weight = faker.number.int({ min: 1000, max: 1999 });
weightRef.current.value = `${weight / 100} lbs`; setInputItem({ ...inputItem || {}, weight }) if (weightRef.current) {
weightRef.current.value = `${weight / 100} lbs`;
}
setInputItem({ ...inputItem || {}, weight })
}} }}
tabIndex={0} tabIndex={0}
> >
Weight from Scale Weight from Scale
</button> </button>
)}
</div> </div>
) : (
<input
id="weight"
value={!!item ? `${item?.weight} lbs.` : ''}
contentEditable={false}
tabIndex={-1}
readOnly
/>
)}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -22,17 +22,21 @@ export default function Page() {
break; break;
case 'Escape': case 'Escape':
event.preventDefault(); event.preventDefault();
if (bin !== null) {
setBin(null); setBin(null);
} else {
setItem(null);
}
break; break;
} }
}, [bin, item, setBin, setItem]); }, [bin, setBin, setItem]);
useEffect(() => { useEffect(() => {
window.addEventListener('keydown', handleKeydown); window.addEventListener('keydown', handleKeydown);
return () => { return () => {
window.removeEventListener('keydown', handleKeydown); window.removeEventListener('keydown', handleKeydown);
}; };
}, []); }, [handleKeydown]);
return ( return (
<main className={styles.page}> <main className={styles.page}>

View File

@@ -2,6 +2,7 @@
.page { .page {
padding: 1rem; padding: 1rem;
min-height: 100vh;
h1 { h1 {
margin-bottom: 1em; margin-bottom: 1em;

View File

@@ -48,11 +48,9 @@ export default function Page() {
onDrop={handleDrop} onDrop={handleDrop}
> >
<h2>{binToLabel(parseInt(k))}</h2> <h2>{binToLabel(parseInt(k))}</h2>
{v.length > 0 && (
<ul onDrop={handleDrop}> <ul onDrop={handleDrop}>
{v.map((item) => (<li key={(item as BinnedDocument)._id} onDragStart={() => setDragging(item)} draggable>{`${item.product} - ${item.weight}lbs`}</li>))} {v.length > 0 && v.map((item) => (<li key={(item as BinnedDocument)._id} onDragStart={() => setDragging(item)} draggable>{`${item.product} - ${item.weight}lbs`}</li>))}
</ul> </ul>
)}
</div> </div>
))} ))}
</div> </div>

View File

@@ -2,7 +2,6 @@ import { faker } from '@faker-js/faker';
import { Product } from "./product.enum"; import { Product } from "./product.enum";
import { dateToOrdinal } from './ordinalDate'; import { dateToOrdinal } from './ordinalDate';
import { ValueOf } from 'next/dist/shared/lib/constants';
export type Barcode = string; export type Barcode = string;

View File

@@ -16,14 +16,15 @@ export async function addToBin(bin: number, item: Omit<BinItem, 'bin'>) {
export async function getBinsContents(): Promise<BinsContents> { export async function getBinsContents(): Promise<BinsContents> {
await db(); await db();
const bins = {} as BinsContents;
const createdAt = new Date(); const createdAt = new Date();
createdAt.setUTCHours(0,0,0,0); createdAt.setDate(createdAt.getDate() - 1);
createdAt.setHours(0,0,0,0);
// Should be today, but lets do yesterday so there is more to see for demo purposes // Should be today, but lets do yesterday so there is more to see for demo purposes
const binned = await Binned.find({ createdAt: { $gte: createdAt }}); const binned = await Binned.find({ createdAt: { $gte: createdAt }});
binned.forEach((item: BinItem) => bins[item.bin] = [...(bins[item.bin] ?? []), item]); return JSON.parse(JSON.stringify(binned.reduce((bins: { [key in Bin]: BinItem[] }, cur: BinItem) => {
return JSON.parse(JSON.stringify(bins)); bins[cur.bin] = [...bins[cur.bin], cur];
return bins;
}, { [Bin.LOSS]: [], [Bin.PROCESS]: [], [Bin.DONATE]: [], [Bin.SHOULDER_TAP]: [] })));
} }
export async function switchBin(bin: number, id: StringSchemaDefinition) { export async function switchBin(bin: number, id: StringSchemaDefinition) {