Compare commits
7 Commits
f635415b75
...
7671172d97
| Author | SHA1 | Date | |
|---|---|---|---|
| 7671172d97 | |||
| 6dd1a5b332 | |||
| 865f280cfa | |||
| a717260b8d | |||
| 4464cea022 | |||
| 55418e2f09 | |||
| 5281118596 |
23
backend/db/schema/dockdoor.scans.schema.ts
Normal file
23
backend/db/schema/dockdoor.scans.schema.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
||||||
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
|
import type { z } from "zod";
|
||||||
|
|
||||||
|
export const dockDoorScans = pgTable("dock_door_scans", {
|
||||||
|
id: uuid("id").defaultRandom().primaryKey(),
|
||||||
|
dockId: text("dock_id").notNull(),
|
||||||
|
loadingOrder: text("loading_order").notNull(),
|
||||||
|
loadingUnit: text("loading_Unit").unique(), // can be running number or sscc depending on where it came from
|
||||||
|
loadingUnitStatus: text("loading_unit_status").default("loaded"), // TODO: add enums on the status of each load.
|
||||||
|
message: text("message"), // the response it gave when scanning
|
||||||
|
status: text("status").default("active"), // TODO: add in enums for this
|
||||||
|
add_date: timestamp("add_date", { withTimezone: true }).defaultNow(),
|
||||||
|
add_user: text("add_user").default("lst-system"),
|
||||||
|
upd_date: timestamp("upd_date", { withTimezone: true }).defaultNow(),
|
||||||
|
upd_user: text("upd_user").default("lst-system"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const dockDoorScansSchema = createSelectSchema(dockDoorScans);
|
||||||
|
export const newDockDoorScansSchema = createInsertSchema(dockDoorScans);
|
||||||
|
|
||||||
|
export type DockDoorScans = z.infer<typeof dockDoorScansSchema>;
|
||||||
|
export type NewDockDoorScans = z.infer<typeof newDockDoorScansSchema>;
|
||||||
@@ -2,7 +2,9 @@ import { eq, sql } from "drizzle-orm";
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
import { db } from "../db/db.controller.js";
|
import { db } from "../db/db.controller.js";
|
||||||
|
import { dockDoorScans } from "../db/schema/dockdoor.scans.schema.js";
|
||||||
import { dockDoorScanners } from "../db/schema/dockdoor.schema.js";
|
import { dockDoorScanners } from "../db/schema/dockdoor.schema.js";
|
||||||
|
import { runProdApi } from "../utils/prodEndpoint.utils.js";
|
||||||
import { apiReturn } from "../utils/returnHelper.utils.js";
|
import { apiReturn } from "../utils/returnHelper.utils.js";
|
||||||
import { tryCatch } from "../utils/trycatch.utils.js";
|
import { tryCatch } from "../utils/trycatch.utils.js";
|
||||||
|
|
||||||
@@ -14,20 +16,52 @@ const endLoading = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
r.post("/", async (req, res) => {
|
r.post("/", async (req, res) => {
|
||||||
// close the loading order
|
// TODO: setup the emitter to just emit the data when we post to the db
|
||||||
|
|
||||||
// clear the loading order off the dock
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const validated = endLoading.parse(req.body);
|
const validated = endLoading.parse(req.body);
|
||||||
|
|
||||||
|
const orders = (await runProdApi({
|
||||||
|
method: "post",
|
||||||
|
endpoint: `/public/v1.0/OutboundDeliveries/LoadingOrders/${req.body.loadingOrder}/Finish`,
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
printDeliveryDocuments: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})) as any;
|
||||||
|
|
||||||
|
if (orders?.data.errors) {
|
||||||
|
console.log(orders.data.errors);
|
||||||
|
return apiReturn(res, {
|
||||||
|
success: false,
|
||||||
|
level: "error",
|
||||||
|
module: "dockdoor",
|
||||||
|
subModule: "loadingOrder",
|
||||||
|
message: `Failed to finish the order.`,
|
||||||
|
data: (orders.data.errors as any) ?? [],
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await tryCatch(
|
||||||
|
db
|
||||||
|
.update(dockDoorScans)
|
||||||
|
.set({
|
||||||
|
upd_date: sql`NOW()`,
|
||||||
|
upd_user: req.user?.username ?? "lst-dock-system",
|
||||||
|
})
|
||||||
|
.where(eq(dockDoorScanners.currentLoadingOrder, validated.loadingOrder))
|
||||||
|
.returning(),
|
||||||
|
);
|
||||||
|
|
||||||
const { data, error } = await tryCatch(
|
const { data, error } = await tryCatch(
|
||||||
db
|
db
|
||||||
.update(dockDoorScanners)
|
.update(dockDoorScanners)
|
||||||
.set({
|
.set({
|
||||||
currentLoadingOrder: "",
|
currentLoadingOrder: "",
|
||||||
upd_date: sql`NOW()`,
|
upd_date: sql`NOW()`,
|
||||||
upd_user: req.user?.username,
|
upd_user: req.user?.username ?? "lst-dock-system",
|
||||||
})
|
})
|
||||||
.where(eq(dockDoorScanners.dockId, validated.dockId))
|
.where(eq(dockDoorScanners.dockId, validated.dockId))
|
||||||
.returning(),
|
.returning(),
|
||||||
@@ -46,13 +80,15 @@ r.post("/", async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return apiReturn(res, {
|
return apiReturn(res, {
|
||||||
success: true,
|
success: orders.data.errors ? false : true,
|
||||||
level: "info",
|
level: orders.data.errors ? "error" : "info",
|
||||||
module: "dockdoor",
|
module: "dockdoor",
|
||||||
subModule: "loadingOrder",
|
subModule: "loadingOrder",
|
||||||
message: `Loading order ${validated.loadingOrder} was just closed.`,
|
message: orders.data.errors
|
||||||
|
? `Loading order was cleared but encountered an error: \n${orders.data.errors[0].message} \nPossible reason for this is the loading order was completed via scanner or other means.`
|
||||||
|
: `Loading order ${validated.loadingOrder} was just closed.`,
|
||||||
data: data ?? [],
|
data: data ?? [],
|
||||||
status: 200,
|
status: orders.data.errors ? 400 : 200,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return apiReturn(res, {
|
return apiReturn(res, {
|
||||||
@@ -60,7 +96,7 @@ r.post("/", async (req, res) => {
|
|||||||
level: "error",
|
level: "error",
|
||||||
module: "dockdoor",
|
module: "dockdoor",
|
||||||
subModule: "loadingOrder",
|
subModule: "loadingOrder",
|
||||||
message: `Failed to start loading order.`,
|
message: `Failed to Close loading order.`,
|
||||||
data: (error as any) ?? [],
|
data: (error as any) ?? [],
|
||||||
status: 400,
|
status: 400,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "../db/db.controller.js";
|
import { db } from "../db/db.controller.js";
|
||||||
|
import { dockDoorScans } from "../db/schema/dockdoor.scans.schema.js";
|
||||||
import { dockDoorScanners } from "../db/schema/dockdoor.schema.js";
|
import { dockDoorScanners } from "../db/schema/dockdoor.schema.js";
|
||||||
import { emitToRoom } from "../socket.io/roomEmitter.socket.js";
|
import { emitToRoom } from "../socket.io/roomEmitter.socket.js";
|
||||||
import { runProdApi } from "../utils/prodEndpoint.utils.js";
|
import { runProdApi } from "../utils/prodEndpoint.utils.js";
|
||||||
@@ -15,12 +16,35 @@ type Data = {
|
|||||||
runningNo?: string;
|
runningNo?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const postScan = async (data: any) => {
|
||||||
|
try {
|
||||||
|
await db.insert(dockDoorScans).values({
|
||||||
|
dockId: data.dockId,
|
||||||
|
loadingOrder: data.loadingOrder,
|
||||||
|
loadingUnit: data.unit, // can be running number or sscc depending on where it came from
|
||||||
|
loadingUnitStatus: data.unitStatus, // TODO: add enums on the status of each load.
|
||||||
|
message: data.message, // the response it gave when scanning
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error: ", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const loadUnit = async (data: Data) => {
|
const loadUnit = async (data: Data) => {
|
||||||
// are we even active at this time?
|
// are we even active at this time?
|
||||||
const dockDoorActive = await db.query.settings.findFirst({
|
const dockDoorActive = await db.query.settings.findFirst({
|
||||||
where: (u, { eq }) => eq(u.name, "dockDoorScanning"),
|
where: (u, { eq }) => eq(u.name, "dockDoorScanning"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const unitToScan = data.sscc
|
||||||
|
? { sscc: data.sscc?.slice(2) }
|
||||||
|
: { runningNo: Number(data.runningNo) };
|
||||||
|
|
||||||
|
const dock = await db
|
||||||
|
.select()
|
||||||
|
.from(dockDoorScanners)
|
||||||
|
.where(eq(dockDoorScanners.dockId, data.dockId as string));
|
||||||
|
|
||||||
if (!dockDoorActive?.active) {
|
if (!dockDoorActive?.active) {
|
||||||
return returnFunc({
|
return returnFunc({
|
||||||
success: false,
|
success: false,
|
||||||
@@ -33,29 +57,18 @@ const loadUnit = async (data: Data) => {
|
|||||||
room: "",
|
room: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// check if its a valids an sscc
|
|
||||||
|
|
||||||
if (data.sscc === "noread") {
|
|
||||||
return returnFunc({
|
|
||||||
success: false,
|
|
||||||
level: "error",
|
|
||||||
module: "dockdoor",
|
|
||||||
subModule: "loadUnit",
|
|
||||||
message:
|
|
||||||
"Failed to load the unit to the truck, there was no pallet read.",
|
|
||||||
data: [],
|
|
||||||
notify: false,
|
|
||||||
room: `dockDoorLoading:${data.dockId}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we currently have a loading order attached to the dock door.
|
// check if we currently have a loading order attached to the dock door.
|
||||||
const dock = await db
|
|
||||||
.select()
|
|
||||||
.from(dockDoorScanners)
|
|
||||||
.where(eq(dockDoorScanners.dockId, data.dockId as string));
|
|
||||||
|
|
||||||
if (dock[0]?.currentLoadingOrder === "") {
|
if (dock[0]?.currentLoadingOrder === "") {
|
||||||
|
postScan({
|
||||||
|
dockId: data.dockId,
|
||||||
|
loadingOrder: dock[0]?.currentLoadingOrder,
|
||||||
|
loadingUnit: unitToScan,
|
||||||
|
loadingUnitStatus: "notLoaded",
|
||||||
|
message:
|
||||||
|
"There are know current active loading orders please start one and try again.",
|
||||||
|
});
|
||||||
return returnFunc({
|
return returnFunc({
|
||||||
success: true,
|
success: true,
|
||||||
level: "error",
|
level: "error",
|
||||||
@@ -68,6 +81,30 @@ const loadUnit = async (data: Data) => {
|
|||||||
room: `dockDoorLoading:${data.dockId}`,
|
room: `dockDoorLoading:${data.dockId}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// check if its a valids an sscc
|
||||||
|
|
||||||
|
if (data.sscc === "noread") {
|
||||||
|
postScan({
|
||||||
|
dockId: data.dockId,
|
||||||
|
loadingOrder: dock[0]?.currentLoadingOrder,
|
||||||
|
loadingUnit: unitToScan,
|
||||||
|
loadingUnitStatus: "noread",
|
||||||
|
message:
|
||||||
|
"Failed to load the unit to the truck, there was no pallet read.",
|
||||||
|
});
|
||||||
|
|
||||||
|
return returnFunc({
|
||||||
|
success: false,
|
||||||
|
level: "error",
|
||||||
|
module: "dockdoor",
|
||||||
|
subModule: "loadUnit",
|
||||||
|
message:
|
||||||
|
"Failed to load the unit to the truck, there was no pallet read.",
|
||||||
|
data: [],
|
||||||
|
notify: false,
|
||||||
|
room: `dockDoorLoading:${data.dockId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: pallet validation, check if we are on hold, then check if we have been in the staging warehouse for more than x time.
|
// TODO: pallet validation, check if we are on hold, then check if we have been in the staging warehouse for more than x time.
|
||||||
|
|
||||||
@@ -77,10 +114,6 @@ const loadUnit = async (data: Data) => {
|
|||||||
|
|
||||||
// add the loading units
|
// add the loading units
|
||||||
try {
|
try {
|
||||||
const unitToScan = data.sscc
|
|
||||||
? { sscc: data.sscc?.slice(2) }
|
|
||||||
: { runningNo: Number(data.runningNo) };
|
|
||||||
|
|
||||||
const prod = (await runProdApi({
|
const prod = (await runProdApi({
|
||||||
method: "post",
|
method: "post",
|
||||||
endpoint: `/public/v1.0/OutboundDeliveries/LoadingOrders/${dock[0]?.currentLoadingOrder}/LoadUnit`,
|
endpoint: `/public/v1.0/OutboundDeliveries/LoadingOrders/${dock[0]?.currentLoadingOrder}/LoadUnit`,
|
||||||
@@ -90,6 +123,13 @@ const loadUnit = async (data: Data) => {
|
|||||||
//emitToRoom(`dockDoorLoading:${data.dockId}`, prod?.data ?? []);
|
//emitToRoom(`dockDoorLoading:${data.dockId}`, prod?.data ?? []);
|
||||||
|
|
||||||
if (!prod?.success) {
|
if (!prod?.success) {
|
||||||
|
postScan({
|
||||||
|
dockId: data.dockId,
|
||||||
|
loadingOrder: dock[0]?.currentLoadingOrder,
|
||||||
|
loadingUnit: unitToScan,
|
||||||
|
loadingUnitStatus: "notLoaded",
|
||||||
|
message: prod?.data.errors[0].message,
|
||||||
|
});
|
||||||
emitToRoom(`dockDoorLoading:${data.dockId}`, prod?.data.errors[0]);
|
emitToRoom(`dockDoorLoading:${data.dockId}`, prod?.data.errors[0]);
|
||||||
return returnFunc({
|
return returnFunc({
|
||||||
success: false,
|
success: false,
|
||||||
@@ -107,6 +147,14 @@ const loadUnit = async (data: Data) => {
|
|||||||
data: prod.data,
|
data: prod.data,
|
||||||
code: 0,
|
code: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
postScan({
|
||||||
|
dockId: data.dockId,
|
||||||
|
loadingOrder: dock[0]?.currentLoadingOrder,
|
||||||
|
loadingUnit: unitToScan,
|
||||||
|
loadingUnitStatus: "loaded",
|
||||||
|
message: emitData.message,
|
||||||
|
});
|
||||||
emitToRoom(`dockDoorLoading:${data.dockId}`, emitData as any);
|
emitToRoom(`dockDoorLoading:${data.dockId}`, emitData as any);
|
||||||
return returnFunc({
|
return returnFunc({
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ r.patch(
|
|||||||
requirePermission({ notifications: ["update"] }),
|
requirePermission({ notifications: ["update"] }),
|
||||||
async (req, res: Response) => {
|
async (req, res: Response) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const validated = updateNote.parse(req.body);
|
const validated = updateNote.parse(req.body);
|
||||||
|
|
||||||
@@ -37,6 +36,7 @@ r.patch(
|
|||||||
await modifiedNotification(id as string);
|
await modifiedNotification(id as string);
|
||||||
|
|
||||||
if (nError) {
|
if (nError) {
|
||||||
|
|
||||||
return apiReturn(res, {
|
return apiReturn(res, {
|
||||||
success: false,
|
success: false,
|
||||||
level: "error",
|
level: "error",
|
||||||
@@ -58,6 +58,7 @@ r.patch(
|
|||||||
status: 200,
|
status: 200,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
||||||
if (err instanceof z.ZodError) {
|
if (err instanceof z.ZodError) {
|
||||||
const flattened = z.flattenError(err);
|
const flattened = z.flattenError(err);
|
||||||
// return res.status(400).json({
|
// return res.status(400).json({
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ r.delete("/:id", async (req, res) => {
|
|||||||
.where(eq(opendockArticleSetup.id, id))
|
.where(eq(opendockArticleSetup.id, id))
|
||||||
.returning();
|
.returning();
|
||||||
return apiReturn(res, {
|
return apiReturn(res, {
|
||||||
success: false,
|
success: true,
|
||||||
level: "info", //connect.success ? "info" : "error",
|
level: "info", //connect.success ? "info" : "error",
|
||||||
module: "opendock",
|
module: "opendock",
|
||||||
subModule: "articleCheck",
|
subModule: "articleCheck",
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { desc } from "drizzle-orm";
|
import { desc, eq } from "drizzle-orm";
|
||||||
import { db } from "../db/db.controller.js";
|
import { db } from "../db/db.controller.js";
|
||||||
import { logs } from "../db/schema/logs.schema.js";
|
import { logs } from "../db/schema/logs.schema.js";
|
||||||
import { ppoRun } from "../warehousing/warehousing.ppooMonitor.js";
|
import { ppoRun } from "../warehousing/warehousing.ppooMonitor.js";
|
||||||
|
import { dockDoorScans } from "../db/schema/dockdoor.scans.schema.js";
|
||||||
|
|
||||||
type RoomDefinition<T = unknown> = {
|
type RoomDefinition<T = unknown> = {
|
||||||
seed: (limit: number) => Promise<T[]>;
|
seed: (limit: number) => Promise<T[]>;
|
||||||
@@ -103,7 +104,18 @@ export const roomDefinition: Record<RoomId, RoomDefinition> = {
|
|||||||
"dockDoorLoading:2": {
|
"dockDoorLoading:2": {
|
||||||
seed: async (limit) => {
|
seed: async (limit) => {
|
||||||
console.log(limit);
|
console.log(limit);
|
||||||
|
try {
|
||||||
|
const rows = await db
|
||||||
|
.select()
|
||||||
|
.from(dockDoorScans).where(eq(dockDoorScans.status, "active"))
|
||||||
|
.orderBy(desc(dockDoorScans.upd_date))
|
||||||
|
.limit(limit);
|
||||||
|
|
||||||
|
return rows; //.reverse();
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to seed logs:", e);
|
||||||
return [];
|
return [];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const statement = {
|
|||||||
logistics: ["read", "create", "update", "delete", "readAll"],
|
logistics: ["read", "create", "update", "delete", "readAll"],
|
||||||
mobile: ["read", "create", "update", "delete", "readAll"],
|
mobile: ["read", "create", "update", "delete", "readAll"],
|
||||||
openDock: ["read", "create", "update", "delete"],
|
openDock: ["read", "create", "update", "delete"],
|
||||||
|
warehouse: ["read", "create", "update", "delete"],
|
||||||
notifications: ["read", "create", "update", "delete", "readAll"],
|
notifications: ["read", "create", "update", "delete", "readAll"],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@@ -17,17 +18,20 @@ export const user = ac.newRole({
|
|||||||
app: ["read", "create"],
|
app: ["read", "create"],
|
||||||
notifications: ["read", "create"],
|
notifications: ["read", "create"],
|
||||||
openDock: ["read"],
|
openDock: ["read"],
|
||||||
|
warehouse: ["read"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const manager = ac.newRole({
|
export const manager = ac.newRole({
|
||||||
app: ["read", "create", "update"],
|
app: ["read", "create", "update"],
|
||||||
mobile: ["read", "create", "update"],
|
mobile: ["read", "create", "update"],
|
||||||
openDock: ["read", "create", "update"],
|
openDock: ["read", "create", "update"],
|
||||||
|
warehouse: ["read", "create"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const transport = ac.newRole({
|
export const transport = ac.newRole({
|
||||||
app: ["read", "create", "update"],
|
app: ["read", "create", "update"],
|
||||||
openDock: ["read", "create", "update"],
|
openDock: ["read", "create", "update"],
|
||||||
|
warehouse: ["read", "create"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const admin = ac.newRole({
|
export const admin = ac.newRole({
|
||||||
@@ -35,6 +39,7 @@ export const admin = ac.newRole({
|
|||||||
mobile: ["read", "create", "update"],
|
mobile: ["read", "create", "update"],
|
||||||
user: ["create", "update", "ban"],
|
user: ["create", "update", "ban"],
|
||||||
openDock: ["read", "create", "update"],
|
openDock: ["read", "create", "update"],
|
||||||
|
warehouse: ["read", "create", "update"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const systemAdmin = ac.newRole({
|
export const systemAdmin = ac.newRole({
|
||||||
@@ -44,6 +49,7 @@ export const systemAdmin = ac.newRole({
|
|||||||
mobile: ["read", "create", "update", "delete", "readAll"],
|
mobile: ["read", "create", "update", "delete", "readAll"],
|
||||||
logistics: ["read", "create", "update", "delete", "readAll"],
|
logistics: ["read", "create", "update", "delete", "readAll"],
|
||||||
notifications: ["read", "create", "update", "delete", "readAll"],
|
notifications: ["read", "create", "update", "delete", "readAll"],
|
||||||
|
warehouse: ["read", "create", "update", "delete"],
|
||||||
openDock: ["read", "create", "update", "delete"],
|
openDock: ["read", "create", "update", "delete"],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
94
frontend/src/components/Sidebar/Warhouse.tsx
Normal file
94
frontend/src/components/Sidebar/Warhouse.tsx
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { Link } from "@tanstack/react-router";
|
||||||
|
import { ChevronRight, Link as link } from "lucide-react";
|
||||||
|
import { permissionQuery } from "../../lib/queries/permsCheck";
|
||||||
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger,
|
||||||
|
} from "../ui/collapsible";
|
||||||
|
import {
|
||||||
|
SidebarGroup,
|
||||||
|
SidebarGroupContent,
|
||||||
|
SidebarGroupLabel,
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
SidebarMenuSub,
|
||||||
|
SidebarMenuSubButton,
|
||||||
|
SidebarMenuSubItem,
|
||||||
|
useSidebar,
|
||||||
|
} from "../ui/sidebar";
|
||||||
|
|
||||||
|
export default function WarehouseBar() {
|
||||||
|
const { data: canCreate = false } = useQuery(
|
||||||
|
permissionQuery({
|
||||||
|
warehouse: ["read"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const { setOpen } = useSidebar();
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
title: "Dock Door Scanning",
|
||||||
|
url: "/warehouse",
|
||||||
|
//icon,
|
||||||
|
isActive: canCreate,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
title: "DockDoorScanning",
|
||||||
|
icon: link,
|
||||||
|
url: "/warehouse/dockdoorscanning",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SidebarGroup>
|
||||||
|
<SidebarGroupLabel>Warehouse</SidebarGroupLabel>
|
||||||
|
<SidebarGroupContent>
|
||||||
|
<SidebarMenu>
|
||||||
|
{items.map((item) => (
|
||||||
|
<div key={item.title}>
|
||||||
|
{item.isActive && (
|
||||||
|
<Collapsible
|
||||||
|
asChild
|
||||||
|
//defaultOpen={isNotifications}
|
||||||
|
className="group/collapsible"
|
||||||
|
>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<CollapsibleTrigger asChild>
|
||||||
|
<SidebarMenuButton tooltip={item.title}>
|
||||||
|
{item.title}
|
||||||
|
|
||||||
|
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<CollapsibleContent>
|
||||||
|
<SidebarMenuSub>
|
||||||
|
{item.items?.map((subItem) => (
|
||||||
|
<SidebarMenuSubItem key={subItem.title}>
|
||||||
|
<SidebarMenuSubButton asChild>
|
||||||
|
<Link
|
||||||
|
to={subItem.url}
|
||||||
|
onClick={() => setOpen(false)}
|
||||||
|
>
|
||||||
|
<subItem.icon />
|
||||||
|
<span>{subItem.title}</span>
|
||||||
|
</Link>
|
||||||
|
</SidebarMenuSubButton>
|
||||||
|
</SidebarMenuSubItem>
|
||||||
|
))}
|
||||||
|
</SidebarMenuSub>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</Collapsible>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</SidebarMenu>
|
||||||
|
</SidebarGroupContent>
|
||||||
|
</SidebarGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -13,16 +13,23 @@ import AdminSidebar from "./AdminBar";
|
|||||||
import DocBar from "./DocBar";
|
import DocBar from "./DocBar";
|
||||||
import MobileBar from "./MobileBar";
|
import MobileBar from "./MobileBar";
|
||||||
import TransportationBar from "./TransportationBar";
|
import TransportationBar from "./TransportationBar";
|
||||||
|
import WarehouseBar from "./Warhouse";
|
||||||
|
|
||||||
export function AppSidebar() {
|
export function AppSidebar() {
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
const { data: settings, isLoading } = useSuspenseQuery(getSettings());
|
const { data: settings, isLoading } = useSuspenseQuery(getSettings());
|
||||||
const { data: canRead = false } = useQuery(
|
const { data: canReadOpenDock = false } = useQuery(
|
||||||
permissionQuery({
|
permissionQuery({
|
||||||
openDock: ["read"],
|
openDock: ["read"],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { data: canReadWarehouse = false } = useQuery(
|
||||||
|
permissionQuery({
|
||||||
|
warehouse: ["read"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar
|
<Sidebar
|
||||||
variant="sidebar"
|
variant="sidebar"
|
||||||
@@ -42,7 +49,12 @@ export function AppSidebar() {
|
|||||||
{!isLoading &&
|
{!isLoading &&
|
||||||
settings.filter((n: any) => n.name === "opendock_sync")[0]
|
settings.filter((n: any) => n.name === "opendock_sync")[0]
|
||||||
?.active &&
|
?.active &&
|
||||||
canRead && <TransportationBar />}
|
canReadOpenDock && <TransportationBar />}
|
||||||
|
|
||||||
|
{!isLoading &&
|
||||||
|
settings.filter((n: any) => n.name === "dockDoorScanning")[0]
|
||||||
|
?.active &&
|
||||||
|
canReadWarehouse && <WarehouseBar />}
|
||||||
|
|
||||||
{session &&
|
{session &&
|
||||||
(session.user.role === "admin" ||
|
(session.user.role === "admin" ||
|
||||||
|
|||||||
@@ -6,7 +6,14 @@ import {
|
|||||||
} from "better-auth/client/plugins";
|
} from "better-auth/client/plugins";
|
||||||
|
|
||||||
import { createAuthClient } from "better-auth/react";
|
import { createAuthClient } from "better-auth/react";
|
||||||
import { ac, admin, manager, systemAdmin, user } from "./auth-permissions";
|
import {
|
||||||
|
ac,
|
||||||
|
admin,
|
||||||
|
manager,
|
||||||
|
systemAdmin,
|
||||||
|
transport,
|
||||||
|
user,
|
||||||
|
} from "./auth-permissions";
|
||||||
|
|
||||||
export const authClient = createAuthClient({
|
export const authClient = createAuthClient({
|
||||||
baseURL: `${window.location.origin}/lst/api/auth`,
|
baseURL: `${window.location.origin}/lst/api/auth`,
|
||||||
@@ -17,6 +24,7 @@ export const authClient = createAuthClient({
|
|||||||
admin,
|
admin,
|
||||||
user,
|
user,
|
||||||
manager,
|
manager,
|
||||||
|
transport,
|
||||||
systemAdmin,
|
systemAdmin,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export const selectableRoles: SelectableRole[] = [
|
|||||||
{ label: "User", value: "user" },
|
{ label: "User", value: "user" },
|
||||||
{ label: "Manager", value: "manager" },
|
{ label: "Manager", value: "manager" },
|
||||||
{ label: "Transport", value: "transport" },
|
{ label: "Transport", value: "transport" },
|
||||||
|
{ label: "Warehouse", value: "warehouse" },
|
||||||
{ label: "Admin", value: "admin" },
|
{ label: "Admin", value: "admin" },
|
||||||
{ label: "System Admin", value: "systemAdmin" },
|
{ label: "System Admin", value: "systemAdmin" },
|
||||||
];
|
];
|
||||||
@@ -25,6 +26,7 @@ export const statement = {
|
|||||||
logistics: ["read", "create", "update", "delete", "readAll"],
|
logistics: ["read", "create", "update", "delete", "readAll"],
|
||||||
mobile: ["read", "create", "update", "delete", "readAll"],
|
mobile: ["read", "create", "update", "delete", "readAll"],
|
||||||
openDock: ["read", "create", "update", "delete"],
|
openDock: ["read", "create", "update", "delete"],
|
||||||
|
warehouse: ["read", "create", "update", "delete"],
|
||||||
notifications: ["read", "create", "update", "delete", "readAll"],
|
notifications: ["read", "create", "update", "delete", "readAll"],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@@ -34,17 +36,20 @@ export const user = ac.newRole({
|
|||||||
app: ["read", "create"],
|
app: ["read", "create"],
|
||||||
notifications: ["read", "create"],
|
notifications: ["read", "create"],
|
||||||
openDock: ["read"],
|
openDock: ["read"],
|
||||||
|
warehouse: ["read"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const manager = ac.newRole({
|
export const manager = ac.newRole({
|
||||||
app: ["read", "create", "update"],
|
app: ["read", "create", "update"],
|
||||||
mobile: ["read", "create", "update"],
|
mobile: ["read", "create", "update"],
|
||||||
openDock: ["read", "create", "update"],
|
openDock: ["read", "create", "update"],
|
||||||
|
warehouse: ["read", "create"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const transport = ac.newRole({
|
export const transport = ac.newRole({
|
||||||
app: ["read", "create", "update"],
|
app: ["read", "create", "update"],
|
||||||
openDock: ["read", "create", "update"],
|
openDock: ["read", "create", "update"],
|
||||||
|
warehouse: ["read", "create"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const admin = ac.newRole({
|
export const admin = ac.newRole({
|
||||||
@@ -52,6 +57,7 @@ export const admin = ac.newRole({
|
|||||||
mobile: ["read", "create", "update"],
|
mobile: ["read", "create", "update"],
|
||||||
user: ["create", "update", "ban"],
|
user: ["create", "update", "ban"],
|
||||||
openDock: ["read", "create", "update"],
|
openDock: ["read", "create", "update"],
|
||||||
|
warehouse: ["read", "create", "update"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const systemAdmin = ac.newRole({
|
export const systemAdmin = ac.newRole({
|
||||||
@@ -61,6 +67,7 @@ export const systemAdmin = ac.newRole({
|
|||||||
mobile: ["read", "create", "update", "delete", "readAll"],
|
mobile: ["read", "create", "update", "delete", "readAll"],
|
||||||
logistics: ["read", "create", "update", "delete", "readAll"],
|
logistics: ["read", "create", "update", "delete", "readAll"],
|
||||||
notifications: ["read", "create", "update", "delete", "readAll"],
|
notifications: ["read", "create", "update", "delete", "readAll"],
|
||||||
|
warehouse: ["read", "create", "update", "delete"],
|
||||||
openDock: ["read", "create", "update", "delete"],
|
openDock: ["read", "create", "update", "delete"],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
21
frontend/src/lib/queries/getActiveDockScanners.ts
Normal file
21
frontend/src/lib/queries/getActiveDockScanners.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { keepPreviousData, queryOptions } from "@tanstack/react-query";
|
||||||
|
import { api } from "../apiHelper";
|
||||||
|
|
||||||
|
export function getActiveLoadingOrders() {
|
||||||
|
return queryOptions({
|
||||||
|
queryKey: ["getActiveLoadingOrders"],
|
||||||
|
queryFn: () => dataFetch(),
|
||||||
|
staleTime: 5000,
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
|
placeholderData: keepPreviousData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataFetch = async () => {
|
||||||
|
const { data } = await api.get("/dockDoor/activeLoadingOrders");
|
||||||
|
if (!data.success) {
|
||||||
|
throw new Error(data.message ?? "Failed to load articles");
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.data ?? [];
|
||||||
|
};
|
||||||
25
frontend/src/lib/queries/getActiveLoadingOrders.ts
Normal file
25
frontend/src/lib/queries/getActiveLoadingOrders.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { keepPreviousData, queryOptions } from "@tanstack/react-query";
|
||||||
|
import { api } from "../apiHelper";
|
||||||
|
|
||||||
|
export function getActiveDockScanners() {
|
||||||
|
return queryOptions({
|
||||||
|
queryKey: ["getActiveDockScanners"],
|
||||||
|
queryFn: () => dataFetch(),
|
||||||
|
staleTime: 5000,
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
|
placeholderData: keepPreviousData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataFetch = async () => {
|
||||||
|
if (window.location.hostname === "localhost") {
|
||||||
|
await new Promise((res) => setTimeout(res, 1500));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await api.get("/dockDoor/scanners");
|
||||||
|
if (!data.success) {
|
||||||
|
throw new Error(data.message ?? "Failed to load articles");
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.data ?? [];
|
||||||
|
};
|
||||||
@@ -22,7 +22,10 @@ import { Route as AdminScanUsersRouteImport } from './routes/admin/scanUsers'
|
|||||||
import { Route as AdminNotificationsRouteImport } from './routes/admin/notifications'
|
import { Route as AdminNotificationsRouteImport } from './routes/admin/notifications'
|
||||||
import { Route as AdminLogsRouteImport } from './routes/admin/logs'
|
import { Route as AdminLogsRouteImport } from './routes/admin/logs'
|
||||||
import { Route as authLoginRouteImport } from './routes/(auth)/login'
|
import { Route as authLoginRouteImport } from './routes/(auth)/login'
|
||||||
|
import { Route as WarehouseDockdoorscanningIndexRouteImport } from './routes/warehouse/dockdoorscanning/index'
|
||||||
import { Route as TransportationOpendockIndexRouteImport } from './routes/transportation/opendock/index'
|
import { Route as TransportationOpendockIndexRouteImport } from './routes/transportation/opendock/index'
|
||||||
|
import { Route as WarehouseDockdoorscanningDockScansRouteImport } from './routes/warehouse/dockdoorscanning/$dockScans'
|
||||||
|
import { Route as WarehouseDockdoorscanningDockRouteImport } from './routes/warehouse/dockdoorscanning/$dock'
|
||||||
import { Route as authUserSignupRouteImport } from './routes/(auth)/user.signup'
|
import { Route as authUserSignupRouteImport } from './routes/(auth)/user.signup'
|
||||||
import { Route as authUserResetpasswordRouteImport } from './routes/(auth)/user.resetpassword'
|
import { Route as authUserResetpasswordRouteImport } from './routes/(auth)/user.resetpassword'
|
||||||
import { Route as authUserProfileRouteImport } from './routes/(auth)/user.profile'
|
import { Route as authUserProfileRouteImport } from './routes/(auth)/user.profile'
|
||||||
@@ -92,12 +95,30 @@ const authLoginRoute = authLoginRouteImport.update({
|
|||||||
path: '/login',
|
path: '/login',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const WarehouseDockdoorscanningIndexRoute =
|
||||||
|
WarehouseDockdoorscanningIndexRouteImport.update({
|
||||||
|
id: '/warehouse/dockdoorscanning/',
|
||||||
|
path: '/warehouse/dockdoorscanning/',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const TransportationOpendockIndexRoute =
|
const TransportationOpendockIndexRoute =
|
||||||
TransportationOpendockIndexRouteImport.update({
|
TransportationOpendockIndexRouteImport.update({
|
||||||
id: '/transportation/opendock/',
|
id: '/transportation/opendock/',
|
||||||
path: '/transportation/opendock/',
|
path: '/transportation/opendock/',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const WarehouseDockdoorscanningDockScansRoute =
|
||||||
|
WarehouseDockdoorscanningDockScansRouteImport.update({
|
||||||
|
id: '/warehouse/dockdoorscanning/$dockScans',
|
||||||
|
path: '/warehouse/dockdoorscanning/$dockScans',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
|
const WarehouseDockdoorscanningDockRoute =
|
||||||
|
WarehouseDockdoorscanningDockRouteImport.update({
|
||||||
|
id: '/warehouse/dockdoorscanning/$dock',
|
||||||
|
path: '/warehouse/dockdoorscanning/$dock',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const authUserSignupRoute = authUserSignupRouteImport.update({
|
const authUserSignupRoute = authUserSignupRouteImport.update({
|
||||||
id: '/(auth)/user/signup',
|
id: '/(auth)/user/signup',
|
||||||
path: '/user/signup',
|
path: '/user/signup',
|
||||||
@@ -131,7 +152,10 @@ export interface FileRoutesByFullPath {
|
|||||||
'/user/profile': typeof authUserProfileRoute
|
'/user/profile': typeof authUserProfileRoute
|
||||||
'/user/resetpassword': typeof authUserResetpasswordRoute
|
'/user/resetpassword': typeof authUserResetpasswordRoute
|
||||||
'/user/signup': typeof authUserSignupRoute
|
'/user/signup': typeof authUserSignupRoute
|
||||||
|
'/warehouse/dockdoorscanning/$dock': typeof WarehouseDockdoorscanningDockRoute
|
||||||
|
'/warehouse/dockdoorscanning/$dockScans': typeof WarehouseDockdoorscanningDockScansRoute
|
||||||
'/transportation/opendock/': typeof TransportationOpendockIndexRoute
|
'/transportation/opendock/': typeof TransportationOpendockIndexRoute
|
||||||
|
'/warehouse/dockdoorscanning/': typeof WarehouseDockdoorscanningIndexRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
@@ -150,7 +174,10 @@ export interface FileRoutesByTo {
|
|||||||
'/user/profile': typeof authUserProfileRoute
|
'/user/profile': typeof authUserProfileRoute
|
||||||
'/user/resetpassword': typeof authUserResetpasswordRoute
|
'/user/resetpassword': typeof authUserResetpasswordRoute
|
||||||
'/user/signup': typeof authUserSignupRoute
|
'/user/signup': typeof authUserSignupRoute
|
||||||
|
'/warehouse/dockdoorscanning/$dock': typeof WarehouseDockdoorscanningDockRoute
|
||||||
|
'/warehouse/dockdoorscanning/$dockScans': typeof WarehouseDockdoorscanningDockScansRoute
|
||||||
'/transportation/opendock': typeof TransportationOpendockIndexRoute
|
'/transportation/opendock': typeof TransportationOpendockIndexRoute
|
||||||
|
'/warehouse/dockdoorscanning': typeof WarehouseDockdoorscanningIndexRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesById {
|
export interface FileRoutesById {
|
||||||
__root__: typeof rootRouteImport
|
__root__: typeof rootRouteImport
|
||||||
@@ -170,7 +197,10 @@ export interface FileRoutesById {
|
|||||||
'/(auth)/user/profile': typeof authUserProfileRoute
|
'/(auth)/user/profile': typeof authUserProfileRoute
|
||||||
'/(auth)/user/resetpassword': typeof authUserResetpasswordRoute
|
'/(auth)/user/resetpassword': typeof authUserResetpasswordRoute
|
||||||
'/(auth)/user/signup': typeof authUserSignupRoute
|
'/(auth)/user/signup': typeof authUserSignupRoute
|
||||||
|
'/warehouse/dockdoorscanning/$dock': typeof WarehouseDockdoorscanningDockRoute
|
||||||
|
'/warehouse/dockdoorscanning/$dockScans': typeof WarehouseDockdoorscanningDockScansRoute
|
||||||
'/transportation/opendock/': typeof TransportationOpendockIndexRoute
|
'/transportation/opendock/': typeof TransportationOpendockIndexRoute
|
||||||
|
'/warehouse/dockdoorscanning/': typeof WarehouseDockdoorscanningIndexRoute
|
||||||
}
|
}
|
||||||
export interface FileRouteTypes {
|
export interface FileRouteTypes {
|
||||||
fileRoutesByFullPath: FileRoutesByFullPath
|
fileRoutesByFullPath: FileRoutesByFullPath
|
||||||
@@ -191,7 +221,10 @@ export interface FileRouteTypes {
|
|||||||
| '/user/profile'
|
| '/user/profile'
|
||||||
| '/user/resetpassword'
|
| '/user/resetpassword'
|
||||||
| '/user/signup'
|
| '/user/signup'
|
||||||
|
| '/warehouse/dockdoorscanning/$dock'
|
||||||
|
| '/warehouse/dockdoorscanning/$dockScans'
|
||||||
| '/transportation/opendock/'
|
| '/transportation/opendock/'
|
||||||
|
| '/warehouse/dockdoorscanning/'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to:
|
to:
|
||||||
| '/'
|
| '/'
|
||||||
@@ -210,7 +243,10 @@ export interface FileRouteTypes {
|
|||||||
| '/user/profile'
|
| '/user/profile'
|
||||||
| '/user/resetpassword'
|
| '/user/resetpassword'
|
||||||
| '/user/signup'
|
| '/user/signup'
|
||||||
|
| '/warehouse/dockdoorscanning/$dock'
|
||||||
|
| '/warehouse/dockdoorscanning/$dockScans'
|
||||||
| '/transportation/opendock'
|
| '/transportation/opendock'
|
||||||
|
| '/warehouse/dockdoorscanning'
|
||||||
id:
|
id:
|
||||||
| '__root__'
|
| '__root__'
|
||||||
| '/'
|
| '/'
|
||||||
@@ -229,7 +265,10 @@ export interface FileRouteTypes {
|
|||||||
| '/(auth)/user/profile'
|
| '/(auth)/user/profile'
|
||||||
| '/(auth)/user/resetpassword'
|
| '/(auth)/user/resetpassword'
|
||||||
| '/(auth)/user/signup'
|
| '/(auth)/user/signup'
|
||||||
|
| '/warehouse/dockdoorscanning/$dock'
|
||||||
|
| '/warehouse/dockdoorscanning/$dockScans'
|
||||||
| '/transportation/opendock/'
|
| '/transportation/opendock/'
|
||||||
|
| '/warehouse/dockdoorscanning/'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
}
|
}
|
||||||
export interface RootRouteChildren {
|
export interface RootRouteChildren {
|
||||||
@@ -249,7 +288,10 @@ export interface RootRouteChildren {
|
|||||||
authUserProfileRoute: typeof authUserProfileRoute
|
authUserProfileRoute: typeof authUserProfileRoute
|
||||||
authUserResetpasswordRoute: typeof authUserResetpasswordRoute
|
authUserResetpasswordRoute: typeof authUserResetpasswordRoute
|
||||||
authUserSignupRoute: typeof authUserSignupRoute
|
authUserSignupRoute: typeof authUserSignupRoute
|
||||||
|
WarehouseDockdoorscanningDockRoute: typeof WarehouseDockdoorscanningDockRoute
|
||||||
|
WarehouseDockdoorscanningDockScansRoute: typeof WarehouseDockdoorscanningDockScansRoute
|
||||||
TransportationOpendockIndexRoute: typeof TransportationOpendockIndexRoute
|
TransportationOpendockIndexRoute: typeof TransportationOpendockIndexRoute
|
||||||
|
WarehouseDockdoorscanningIndexRoute: typeof WarehouseDockdoorscanningIndexRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@tanstack/react-router' {
|
declare module '@tanstack/react-router' {
|
||||||
@@ -345,6 +387,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof authLoginRouteImport
|
preLoaderRoute: typeof authLoginRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/warehouse/dockdoorscanning/': {
|
||||||
|
id: '/warehouse/dockdoorscanning/'
|
||||||
|
path: '/warehouse/dockdoorscanning'
|
||||||
|
fullPath: '/warehouse/dockdoorscanning/'
|
||||||
|
preLoaderRoute: typeof WarehouseDockdoorscanningIndexRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/transportation/opendock/': {
|
'/transportation/opendock/': {
|
||||||
id: '/transportation/opendock/'
|
id: '/transportation/opendock/'
|
||||||
path: '/transportation/opendock'
|
path: '/transportation/opendock'
|
||||||
@@ -352,6 +401,20 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof TransportationOpendockIndexRouteImport
|
preLoaderRoute: typeof TransportationOpendockIndexRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/warehouse/dockdoorscanning/$dockScans': {
|
||||||
|
id: '/warehouse/dockdoorscanning/$dockScans'
|
||||||
|
path: '/warehouse/dockdoorscanning/$dockScans'
|
||||||
|
fullPath: '/warehouse/dockdoorscanning/$dockScans'
|
||||||
|
preLoaderRoute: typeof WarehouseDockdoorscanningDockScansRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
|
'/warehouse/dockdoorscanning/$dock': {
|
||||||
|
id: '/warehouse/dockdoorscanning/$dock'
|
||||||
|
path: '/warehouse/dockdoorscanning/$dock'
|
||||||
|
fullPath: '/warehouse/dockdoorscanning/$dock'
|
||||||
|
preLoaderRoute: typeof WarehouseDockdoorscanningDockRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/(auth)/user/signup': {
|
'/(auth)/user/signup': {
|
||||||
id: '/(auth)/user/signup'
|
id: '/(auth)/user/signup'
|
||||||
path: '/user/signup'
|
path: '/user/signup'
|
||||||
@@ -393,7 +456,11 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
authUserProfileRoute: authUserProfileRoute,
|
authUserProfileRoute: authUserProfileRoute,
|
||||||
authUserResetpasswordRoute: authUserResetpasswordRoute,
|
authUserResetpasswordRoute: authUserResetpasswordRoute,
|
||||||
authUserSignupRoute: authUserSignupRoute,
|
authUserSignupRoute: authUserSignupRoute,
|
||||||
|
WarehouseDockdoorscanningDockRoute: WarehouseDockdoorscanningDockRoute,
|
||||||
|
WarehouseDockdoorscanningDockScansRoute:
|
||||||
|
WarehouseDockdoorscanningDockScansRoute,
|
||||||
TransportationOpendockIndexRoute: TransportationOpendockIndexRoute,
|
TransportationOpendockIndexRoute: TransportationOpendockIndexRoute,
|
||||||
|
WarehouseDockdoorscanningIndexRoute: WarehouseDockdoorscanningIndexRoute,
|
||||||
}
|
}
|
||||||
export const routeTree = rootRouteImport
|
export const routeTree = rootRouteImport
|
||||||
._addFileChildren(rootRouteChildren)
|
._addFileChildren(rootRouteChildren)
|
||||||
|
|||||||
@@ -170,11 +170,11 @@ const NotificationTable = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await api.patch(
|
const res = await api.patch(
|
||||||
`/lst/api/notification/${i.row.original.id}`,
|
`/notification/${i.row.original.id}`,
|
||||||
{
|
{
|
||||||
active: !activeToggle,
|
active: !activeToggle,
|
||||||
},
|
},
|
||||||
{ withCredentials: true },
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.data.success) {
|
if (res.data.success) {
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ const ScanUserTable = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await api.delete(
|
const res = await api.delete(
|
||||||
`/lst/api/mobile/auth/user/${i.row.original.id}`,
|
`/mobile/auth/user/${i.row.original.id}`,
|
||||||
|
|
||||||
{
|
{
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import { useSuspenseQuery } from "@tanstack/react-query";
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
||||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||||
import { createColumnHelper } from "@tanstack/react-table";
|
import { createColumnHelper } from "@tanstack/react-table";
|
||||||
import { Suspense } from "react";
|
import { Suspense, useState } from "react";
|
||||||
import { authClient } from "../../../lib/auth-client";
|
import { authClient } from "../../../lib/auth-client";
|
||||||
import { getArticleLinks } from "../../../lib/queries/getArticleLinks";
|
import { getArticleLinks } from "../../../lib/queries/getArticleLinks";
|
||||||
import LstTable from "../../../lib/tableStuff/LstTable";
|
import LstTable from "../../../lib/tableStuff/LstTable";
|
||||||
import SearchableHeader from "../../../lib/tableStuff/SearchableHeader";
|
import SearchableHeader from "../../../lib/tableStuff/SearchableHeader";
|
||||||
import SkellyTable from "../../../lib/tableStuff/SkellyTable";
|
import SkellyTable from "../../../lib/tableStuff/SkellyTable";
|
||||||
import NewArticleLink from "./-components/NewArticleLink";
|
import NewArticleLink from "./-components/NewArticleLink";
|
||||||
|
import { api } from "../../../lib/apiHelper";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { Button } from "../../../components/ui/button";
|
||||||
|
import { Spinner } from "../../../components/ui/spinner";
|
||||||
|
import { Trash } from "lucide-react";
|
||||||
|
|
||||||
export const Route = createFileRoute("/transportation/opendock/")({
|
export const Route = createFileRoute("/transportation/opendock/")({
|
||||||
beforeLoad: async ({ location }) => {
|
beforeLoad: async ({ location }) => {
|
||||||
@@ -91,6 +96,75 @@ const ArticleLinkTable = () => {
|
|||||||
filterFn: "includesString",
|
filterFn: "includesString",
|
||||||
cell: (i) => i.getValue(),
|
cell: (i) => i.getValue(),
|
||||||
}),
|
}),
|
||||||
|
columnHelper.accessor("deleteUser", {
|
||||||
|
header: ({ column }) => (
|
||||||
|
<SearchableHeader
|
||||||
|
column={column}
|
||||||
|
title="Delete Link"
|
||||||
|
searchable={false}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
filterFn: "includesString",
|
||||||
|
cell: (i) => {
|
||||||
|
// biome-ignore lint: just removing the lint for now to get this going will maybe fix later
|
||||||
|
const [activeToggle, setActiveToggle] = useState(false);
|
||||||
|
|
||||||
|
const onTrigger = async () => {
|
||||||
|
setActiveToggle(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await api.delete(
|
||||||
|
`/opendock/articleCheck/${i.row.original.id}`,
|
||||||
|
|
||||||
|
{
|
||||||
|
withCredentials: true,
|
||||||
|
timeout: 5000,
|
||||||
|
validateStatus: () => true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.data.success) {
|
||||||
|
toast.success(`AV: ${i.row.original.av} was deleted.`);
|
||||||
|
refetch();
|
||||||
|
setActiveToggle(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res.data.success) {
|
||||||
|
toast.error(
|
||||||
|
`AV: ${i.row.original.av} encountered an error when trying to delete: ${res.data.message}`,
|
||||||
|
);
|
||||||
|
refetch();
|
||||||
|
setActiveToggle(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setActiveToggle(false);
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
disabled={activeToggle}
|
||||||
|
onClick={onTrigger}
|
||||||
|
>
|
||||||
|
{activeToggle ? (
|
||||||
|
<span>
|
||||||
|
<Spinner />
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span>
|
||||||
|
<Trash />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
118
frontend/src/routes/warehouse/dockdoorscanning/$dock.tsx
Normal file
118
frontend/src/routes/warehouse/dockdoorscanning/$dock.tsx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
||||||
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
import { Button } from "../../../components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
} from "../../../components/ui/card";
|
||||||
|
import { Separator } from "../../../components/ui/separator";
|
||||||
|
import { getActiveLoadingOrders } from "../../../lib/queries/getActiveDockScanners";
|
||||||
|
import { getActiveDockScanners } from "../../../lib/queries/getActiveLoadingOrders";
|
||||||
|
import { finishLoadingOrder} from './index'
|
||||||
|
import { api } from "../../../lib/apiHelper";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/warehouse/dockdoorscanning/$dock")({
|
||||||
|
component: RouteComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const startOrder = async (loadingOrder: string, dockId: string, refetch:any, refetchActiveLoading:any) => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await api.post("/dockDoor/startLoad", {
|
||||||
|
"loadingOrder":String(loadingOrder),
|
||||||
|
"dockId":dockId
|
||||||
|
},{validateStatus: (status) => status < 500,})
|
||||||
|
|
||||||
|
if (!res.data.success) {
|
||||||
|
toast.error(res.data.message)
|
||||||
|
refetch()
|
||||||
|
refetchActiveLoading()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
toast.success(res.data.message)
|
||||||
|
refetch()
|
||||||
|
refetchActiveLoading()
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
toast.error(`Encountered error: ${JSON.stringify(error)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
const { dock } = Route.useParams();
|
||||||
|
const { data, refetch } = useSuspenseQuery(getActiveDockScanners());
|
||||||
|
const { data: loadingPlanItems, refetch: refetchActiveLoading } = useSuspenseQuery(getActiveLoadingOrders());
|
||||||
|
|
||||||
|
const dockData = data.filter((i: any) => i.dockId === dock);
|
||||||
|
const loadingPlans = loadingPlanItems.filter(
|
||||||
|
(l: any) => l.dockId === Number(dock),
|
||||||
|
);
|
||||||
|
console.log(dockData[0].currentLoadingOrder === "");
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<p>Please select an active loading order for {dockData[0].name}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-center mt-5 gap-2">
|
||||||
|
{loadingPlans &&
|
||||||
|
loadingPlans.length > 0 &&
|
||||||
|
loadingPlans.map((i: any) => {
|
||||||
|
return (
|
||||||
|
<Card key={i.id} className="max-w-96">
|
||||||
|
<CardHeader>
|
||||||
|
Loading order ID: {i.id}{" "}
|
||||||
|
<p>
|
||||||
|
Loading Date: {format(i.loadingDate, "MM/dd/yyyy HH:mm")}
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardDescription className="">
|
||||||
|
<p className="p-3">
|
||||||
|
Below are the loading order details please validate the
|
||||||
|
loading order you are selecting before pressing start.
|
||||||
|
</p>
|
||||||
|
</CardDescription>
|
||||||
|
{/* Mapping the items out so in case we have more than 1 it will display correctly */}
|
||||||
|
<CardContent>
|
||||||
|
{i?.loadingPlanItems?.map((l: any) => {
|
||||||
|
return (
|
||||||
|
<div key={i.id}>
|
||||||
|
<p>Loading Sequence {l.loadingSequence}</p>
|
||||||
|
<p>
|
||||||
|
Article: {l.articleId} - {l.articleDescription}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Current loaded: {l.loadedQuantityLUs}/
|
||||||
|
{l.plannedQuantityLUs}
|
||||||
|
</p>
|
||||||
|
{l.remark !== "" && <p>Remark: {l.remark}</p>}
|
||||||
|
|
||||||
|
{i?.loadingPlanItems.length > 1 && (
|
||||||
|
<Separator className="m-2" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<div className="flex flex-row justify-between">
|
||||||
|
<Button
|
||||||
|
onClick={()=> startOrder(i.id, dock, refetch, refetchActiveLoading)}
|
||||||
|
disabled={dockData[0].currentLoadingOrder !== "" ? true : false}>Start Loading</Button>
|
||||||
|
<Button>Scan progress</Button>
|
||||||
|
<Button onClick={()=> finishLoadingOrder(String(i.id), dock, refetch, refetchActiveLoading)}
|
||||||
|
disabled={dockData[0].currentLoadingOrder === "" ? true : false}>Finish Loading</Button>
|
||||||
|
</div>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/warehouse/dockdoorscanning/$dockScans")({
|
||||||
|
component: RouteComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
const { dockScans } = Route.useParams();
|
||||||
|
return <div>Hello "/warehouse/dockdoorscanning/$docScans"! {dockScans}</div>;
|
||||||
|
}
|
||||||
120
frontend/src/routes/warehouse/dockdoorscanning/index.tsx
Normal file
120
frontend/src/routes/warehouse/dockdoorscanning/index.tsx
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
||||||
|
import { createFileRoute, useNavigate } from "@tanstack/react-router";
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader } from "../../../components/ui/card";
|
||||||
|
import { getActiveLoadingOrders } from "../../../lib/queries/getActiveDockScanners";
|
||||||
|
import { getActiveDockScanners } from "../../../lib/queries/getActiveLoadingOrders";
|
||||||
|
import { Button } from "../../../components/ui/button";
|
||||||
|
import { api } from "../../../lib/apiHelper";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/warehouse/dockdoorscanning/")({
|
||||||
|
component: RouteComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const finishLoadingOrder = async (loadingOrder: string, dockId: string, refetch:any, refetchActiveLoading:any) => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await api.post("/dockDoor/finishOrder", {
|
||||||
|
"loadingOrder":loadingOrder,
|
||||||
|
"dockId":dockId
|
||||||
|
},{validateStatus: (status) => status < 500,})
|
||||||
|
|
||||||
|
if (!res.data.success) {
|
||||||
|
toast.error(res.data.message)
|
||||||
|
refetch()
|
||||||
|
refetchActiveLoading()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
toast.info(res.data.message)
|
||||||
|
refetch()
|
||||||
|
refetchActiveLoading()
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
toast.error(`Encountered error: ${JSON.stringify(error)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
const { data, isLoading, refetch } = useSuspenseQuery(getActiveDockScanners());
|
||||||
|
const { data: loadingPlanItems, refetch : refetchActiveLoading } = useSuspenseQuery(getActiveLoadingOrders());
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center-safe">
|
||||||
|
<p>Loading active dock scanners....</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col ">
|
||||||
|
<div className="flex justify-center-safe">
|
||||||
|
<p className="text-2xl underline">
|
||||||
|
Select a dock you would like to work with
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-center gap-3 mt-5">
|
||||||
|
{!isLoading &&
|
||||||
|
data.length > 0 &&
|
||||||
|
data.map((i: any) => {
|
||||||
|
const loadingPlan =
|
||||||
|
i.currentLoadingOrder !== ""
|
||||||
|
? loadingPlanItems.filter(
|
||||||
|
(x: any) => x.id === Number(i.currentLoadingOrder),
|
||||||
|
)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
key={i.id}
|
||||||
|
className="max-w-96"
|
||||||
|
onClick={() => {
|
||||||
|
if (i.currentLoadingOrder === "") {
|
||||||
|
navigate({
|
||||||
|
to: "/warehouse/dockdoorscanning/$dock",
|
||||||
|
params: { dock: i.dockId },
|
||||||
|
search: {
|
||||||
|
name: i.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardHeader className="text-center">{i.name}</CardHeader>
|
||||||
|
<CardDescription>For Abbott loads reminder: 3 lots per load max.</CardDescription>
|
||||||
|
|
||||||
|
{i.currentLoadingOrder !== "" ? (
|
||||||
|
<CardContent>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
Current loading order: {i.currentLoadingOrder}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
|
||||||
|
{loadingPlan && loadingPlan.length !== 0 ? (<>
|
||||||
|
|
||||||
|
<p>{`${loadingPlan[0].loadingPlanItems[0].articleId} - ${loadingPlan[0].loadingPlanItems[0].articleDescription}`}</p>
|
||||||
|
|
||||||
|
<p>Current Loaded :{" "}
|
||||||
|
{loadingPlan[0].loadingPlanItems[0].loadedQuantityLUs} /{" "}
|
||||||
|
{loadingPlan[0].loadingPlanItems[0].plannedQuantityLUs}</p></>
|
||||||
|
): <><p>The Current Loading order is invalid</p>
|
||||||
|
<p> It appears it could have been finished via another process</p>
|
||||||
|
<div className="m-2 flex justify-center">
|
||||||
|
<Button onClick={()=> finishLoadingOrder(i.currentLoadingOrder, i.dockId, refetch, refetchActiveLoading)}>Clear {i.currentLoadingOrder}</Button></div></>}</div>
|
||||||
|
</CardContent>
|
||||||
|
) : (
|
||||||
|
<CardContent>
|
||||||
|
No active loading orders please click me to select an order
|
||||||
|
</CardContent>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
13
migrations/0060_freezing_hercules.sql
Normal file
13
migrations/0060_freezing_hercules.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
CREATE TABLE "dock_door_scans" (
|
||||||
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"loading_order" text NOT NULL,
|
||||||
|
"loading_Unit" text,
|
||||||
|
"loading_unit_status" text DEFAULT 'loaded',
|
||||||
|
"message" text,
|
||||||
|
"status" text DEFAULT 'active',
|
||||||
|
"add_date" timestamp with time zone DEFAULT now(),
|
||||||
|
"add_user" text DEFAULT 'lst-system',
|
||||||
|
"upd_date" timestamp with time zone DEFAULT now(),
|
||||||
|
"upd_user" text DEFAULT 'lst-system',
|
||||||
|
CONSTRAINT "dock_door_scans_loading_Unit_unique" UNIQUE("loading_Unit")
|
||||||
|
);
|
||||||
1
migrations/0061_wide_marrow.sql
Normal file
1
migrations/0061_wide_marrow.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "dock_door_scans" ADD COLUMN "dock_id" text NOT NULL;
|
||||||
2691
migrations/meta/0060_snapshot.json
Normal file
2691
migrations/meta/0060_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
2697
migrations/meta/0061_snapshot.json
Normal file
2697
migrations/meta/0061_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -421,6 +421,20 @@
|
|||||||
"when": 1780349486711,
|
"when": 1780349486711,
|
||||||
"tag": "0059_sparkling_joystick",
|
"tag": "0059_sparkling_joystick",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 60,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1780584999699,
|
||||||
|
"tag": "0060_freezing_hercules",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 61,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1780692629119,
|
||||||
|
"tag": "0061_wide_marrow",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user