Rewrote subjob handling so it works and better progress updates too.
This commit is contained in:
parent
79ed7691f9
commit
7f17f5f205
2848
package-lock.json
generated
2848
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@ -17,13 +17,13 @@
|
||||
"author": "Tom Butcher",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@nats-io/nats-core": "^3.1.0",
|
||||
"@nats-io/transport-node": "^3.1.0",
|
||||
"axios": "^1.11.0",
|
||||
"@nats-io/nats-core": "^3.2.0",
|
||||
"@nats-io/transport-node": "^3.2.0",
|
||||
"axios": "^1.13.2",
|
||||
"canonical-json": "^0.2.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dotenv": "^17.2.1",
|
||||
"dayjs": "^1.11.19",
|
||||
"dotenv": "^17.2.3",
|
||||
"ejs": "^3.1.10",
|
||||
"etcd3": "^1.1.2",
|
||||
"express": "^5.1.0",
|
||||
@ -31,20 +31,23 @@
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"lodash": "^4.17.21",
|
||||
"log4js": "^6.9.1",
|
||||
"mongodb": "^6.18.0",
|
||||
"mongoose": "^8.17.1",
|
||||
"nanoid": "^5.1.5",
|
||||
"mongodb": "6",
|
||||
"mongoose": "^8.19.4",
|
||||
"nanoid": "^5.1.6",
|
||||
"node-cache": "^5.1.2",
|
||||
"object-hash": "^3.0.0",
|
||||
"posthtml": "^0.16.6",
|
||||
"posthtml": "^0.16.7",
|
||||
"puppeteer": "^24.31.0",
|
||||
"redis": "^4.6.14",
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-adapter-mongo": "^2.0.5",
|
||||
"socketio-jwt": "^4.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^9.33.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"nodemon": "^3.1.11",
|
||||
"prettier": "^3.6.2",
|
||||
"standard": "^17.1.2"
|
||||
}
|
||||
|
||||
@ -360,7 +360,8 @@ export const editObject = async ({
|
||||
updateData,
|
||||
owner = undefined,
|
||||
ownerType = undefined,
|
||||
populate = []
|
||||
populate = [],
|
||||
auditLog = true
|
||||
}) => {
|
||||
try {
|
||||
// Determine parentType from model name
|
||||
@ -389,7 +390,7 @@ export const editObject = async ({
|
||||
const previousExpandedObject = expandObjectIds(previousObject);
|
||||
const newExpandedObject = expandObjectIds(newObject);
|
||||
|
||||
if (owner != undefined && ownerType != undefined) {
|
||||
if (auditLog == true && owner != undefined && ownerType != undefined) {
|
||||
// Audit log before update
|
||||
await editAuditLog(
|
||||
previousExpandedObject,
|
||||
|
||||
@ -1,36 +1,35 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
// Define the main filamentStock schema
|
||||
const filamentStockSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
state: {
|
||||
type: { type: String, required: true },
|
||||
progress: { type: String, required: true }
|
||||
progress: { type: Number, required: false },
|
||||
},
|
||||
startingWeight: {
|
||||
net: { type: Number, required: true },
|
||||
gross: { type: Number, required: true }
|
||||
gross: { type: Number, required: true },
|
||||
},
|
||||
currentWeight: {
|
||||
net: { type: Number, required: true },
|
||||
gross: { type: Number, required: true }
|
||||
gross: { type: Number, required: true },
|
||||
},
|
||||
filament: { type: mongoose.Schema.Types.ObjectId, ref: 'filament' }
|
||||
filament: { type: mongoose.Schema.Types.ObjectId, ref: 'filament', required: true },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
// Add virtual id getter
|
||||
filamentStockSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
filamentStockSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
// Create and export the model
|
||||
export const filamentStockModel = mongoose.model(
|
||||
'filamentStock',
|
||||
filamentStockSchema
|
||||
);
|
||||
export const filamentStockModel = mongoose.model('filamentStock', filamentStockSchema);
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
// Define the main partStock schema
|
||||
const partStockSchema = new Schema(
|
||||
{
|
||||
name: { type: String, required: true },
|
||||
fileName: { type: String, required: false },
|
||||
part: { type: mongoose.Schema.Types.ObjectId, ref: 'part' },
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
state: {
|
||||
type: { type: String, required: true },
|
||||
progress: { type: Number, required: false },
|
||||
},
|
||||
part: { type: mongoose.Schema.Types.ObjectId, ref: 'part', required: true },
|
||||
startingQuantity: { type: Number, required: true },
|
||||
currentQuantity: { type: Number, required: true },
|
||||
},
|
||||
@ -15,7 +19,7 @@ const partStockSchema = new Schema(
|
||||
|
||||
// Add virtual id getter
|
||||
partStockSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const stockAuditItemSchema = new Schema({
|
||||
@ -11,6 +12,7 @@ const stockAuditItemSchema = new Schema({
|
||||
|
||||
const stockAuditSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
type: { type: String, required: true },
|
||||
status: {
|
||||
type: String,
|
||||
@ -28,7 +30,7 @@ const stockAuditSchema = new Schema(
|
||||
|
||||
// Add virtual id getter
|
||||
stockAuditSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const stockEventSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
value: { type: Number, required: true },
|
||||
current: { type: Number, required: true },
|
||||
unit: { type: String, required: true },
|
||||
parent: {
|
||||
type: Schema.Types.ObjectId,
|
||||
@ -33,7 +34,7 @@ const stockEventSchema = new Schema(
|
||||
|
||||
// Add virtual id getter
|
||||
stockEventSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,60 +1,44 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const auditLogSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
changes: {
|
||||
old: { type: Object, required: true },
|
||||
new: { type: Object, required: true }
|
||||
},
|
||||
parent: {
|
||||
type: Schema.Types.ObjectId,
|
||||
refPath: 'parentType',
|
||||
required: true
|
||||
},
|
||||
parentType: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: [
|
||||
'printer',
|
||||
'job',
|
||||
'subJob',
|
||||
'filamentStock',
|
||||
'stockEvent',
|
||||
'vendor',
|
||||
'part',
|
||||
'product',
|
||||
'material',
|
||||
'filament',
|
||||
'gcodeFile',
|
||||
'noteType',
|
||||
'note',
|
||||
'user',
|
||||
'host'
|
||||
] // Add other models as needed
|
||||
},
|
||||
owner: {
|
||||
type: Schema.Types.ObjectId,
|
||||
refPath: 'ownerType',
|
||||
required: true
|
||||
},
|
||||
ownerType: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: ['user', 'printer', 'host']
|
||||
old: { type: Object, required: false },
|
||||
new: { type: Object, required: false },
|
||||
},
|
||||
operation: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: ['edit', 'new', 'delete']
|
||||
}
|
||||
},
|
||||
parent: {
|
||||
type: Schema.Types.ObjectId,
|
||||
refPath: 'parentType',
|
||||
required: true,
|
||||
},
|
||||
parentType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
owner: {
|
||||
type: Schema.Types.ObjectId,
|
||||
refPath: 'ownerType',
|
||||
required: true,
|
||||
},
|
||||
ownerType: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: ['user', 'printer', 'host'],
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
// Add virtual id getter
|
||||
auditLogSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const documentJobSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
@ -38,7 +40,7 @@ const documentJobSchema = new Schema(
|
||||
|
||||
// Add virtual id getter
|
||||
documentJobSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const connectionSchema = new Schema(
|
||||
@ -6,50 +7,42 @@ const connectionSchema = new Schema(
|
||||
interface: { type: String, required: true },
|
||||
protocol: { type: String, required: true },
|
||||
host: { type: String, required: true },
|
||||
port: { type: Number, required: false }
|
||||
port: { type: Number, required: false },
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const documentPrinterSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true
|
||||
unique: true,
|
||||
},
|
||||
connection: { type: connectionSchema, required: true },
|
||||
currentDocumentSize: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'documentSize',
|
||||
required: false
|
||||
},
|
||||
currentDocumentSize: { type: Schema.Types.ObjectId, ref: 'documentSize', required: false },
|
||||
tags: [{ type: String }],
|
||||
online: { type: Boolean, required: true, default: false },
|
||||
active: { type: Boolean, required: true, default: true },
|
||||
state: {
|
||||
type: { type: String, required: true, default: 'offline' },
|
||||
message: { type: String, required: false },
|
||||
progress: { type: Number, required: false }
|
||||
progress: { type: Number, required: false },
|
||||
},
|
||||
connectedAt: { type: Date, default: null },
|
||||
host: { type: Schema.Types.ObjectId, ref: 'host', required: true },
|
||||
queue: [
|
||||
{ type: Schema.Types.ObjectId, ref: 'documentJob', required: false }
|
||||
]
|
||||
queue: [{ type: Schema.Types.ObjectId, ref: 'documentJob', required: false }],
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
// Add virtual id getter
|
||||
documentPrinterSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
documentPrinterSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
export const documentPrinterModel = mongoose.model(
|
||||
'documentPrinter',
|
||||
documentPrinterSchema
|
||||
);
|
||||
export const documentPrinterModel = mongoose.model('documentPrinter', documentPrinterSchema);
|
||||
|
||||
@ -1,41 +1,40 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const documentSizeSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true
|
||||
unique: true,
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0
|
||||
default: 0,
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0
|
||||
default: 0,
|
||||
},
|
||||
infiniteHeight: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
// Add virtual id getter
|
||||
documentSizeSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
documentSizeSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
export const documentSizeModel = mongoose.model(
|
||||
'documentSize',
|
||||
documentSizeSchema
|
||||
);
|
||||
export const documentSizeModel = mongoose.model('documentSize', documentSizeSchema);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const documentTemplateSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
@ -52,7 +54,7 @@ const documentTemplateSchema = new Schema(
|
||||
|
||||
// Add virtual id getter
|
||||
documentTemplateSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const filamentSchema = new mongoose.Schema({
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { required: true, type: String },
|
||||
barcode: { required: false, type: String },
|
||||
url: { required: false, type: String },
|
||||
@ -18,7 +20,7 @@ const filamentSchema = new mongoose.Schema({
|
||||
});
|
||||
|
||||
filamentSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
filamentSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
22
src/database/schemas/management/file.schema.js
Normal file
22
src/database/schemas/management/file.schema.js
Normal file
@ -0,0 +1,22 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
|
||||
const fileSchema = new mongoose.Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { required: true, type: String },
|
||||
type: { required: true, type: String },
|
||||
extension: { required: true, type: String },
|
||||
size: { required: false, type: Number },
|
||||
metaData: { required: false, type: Object },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
fileSchema.virtual('id').get(function () {
|
||||
return this._id;
|
||||
});
|
||||
|
||||
fileSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
export const fileModel = mongoose.model('file', fileSchema);
|
||||
@ -1,4 +1,5 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
|
||||
// Define the device schema
|
||||
const deviceInfoSchema = new mongoose.Schema(
|
||||
@ -9,56 +10,56 @@ const deviceInfoSchema = new mongoose.Schema(
|
||||
release: { type: String },
|
||||
arch: { type: String },
|
||||
hostname: { type: String },
|
||||
uptime: { type: Number }
|
||||
uptime: { type: Number },
|
||||
},
|
||||
cpu: {
|
||||
cores: { type: Number },
|
||||
model: { type: String },
|
||||
speedMHz: { type: Number }
|
||||
speedMHz: { type: Number },
|
||||
},
|
||||
memory: {
|
||||
totalGB: { type: String }, // stored as string from .toFixed(2), could also use Number
|
||||
freeGB: { type: String }
|
||||
freeGB: { type: String },
|
||||
},
|
||||
network: {
|
||||
type: mongoose.Schema.Types.Mixed // since it's an object with dynamic interface names
|
||||
type: mongoose.Schema.Types.Mixed, // since it's an object with dynamic interface names
|
||||
},
|
||||
user: {
|
||||
uid: { type: Number },
|
||||
gid: { type: Number },
|
||||
username: { type: String },
|
||||
homedir: { type: String },
|
||||
shell: { type: String }
|
||||
shell: { type: String },
|
||||
},
|
||||
process: {
|
||||
nodeVersion: { type: String },
|
||||
pid: { type: Number },
|
||||
cwd: { type: String },
|
||||
execPath: { type: String }
|
||||
}
|
||||
execPath: { type: String },
|
||||
},
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const hostSchema = new mongoose.Schema({
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { required: true, type: String },
|
||||
tags: [{ required: false, type: String }],
|
||||
online: { required: true, type: Boolean, default: false },
|
||||
state: {
|
||||
type: { type: String, required: true, default: 'offline' },
|
||||
message: { type: String, required: false },
|
||||
percent: { type: Number, required: false }
|
||||
percent: { type: Number, required: false },
|
||||
},
|
||||
active: { required: true, type: Boolean, default: true },
|
||||
connectedAt: { required: false, type: Date },
|
||||
authCode: { required: false, type: String },
|
||||
otp: { required: false, type: String },
|
||||
otpExpiresAt: { required: false, type: Date },
|
||||
deviceInfo: deviceInfoSchema
|
||||
authCode: { type: { required: false, type: String } },
|
||||
deviceInfo: { deviceInfoSchema },
|
||||
files: [{ type: mongoose.Schema.Types.ObjectId, ref: 'file' }],
|
||||
});
|
||||
|
||||
hostSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
hostSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
|
||||
const materialSchema = new mongoose.Schema({
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { required: true, type: String },
|
||||
url: { required: false, type: String },
|
||||
image: { required: false, type: Buffer },
|
||||
@ -8,7 +10,7 @@ const materialSchema = new mongoose.Schema({
|
||||
});
|
||||
|
||||
materialSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
materialSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const noteTypeSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
@ -23,7 +25,7 @@ const noteTypeSchema = new Schema(
|
||||
|
||||
// Add virtual id getter
|
||||
noteTypeSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,23 +1,26 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
// Define the main part schema
|
||||
const partSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { type: String, required: true },
|
||||
fileName: { type: String, required: false },
|
||||
product: { type: mongoose.Schema.Types.ObjectId, ref: 'product' },
|
||||
globalPricing: { type: Boolean, default: true },
|
||||
priceMode: { type: String, default: 'margin' },
|
||||
amount: { type: Number, required: false },
|
||||
margin: { type: Number, required: false },
|
||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
||||
file: { type: mongoose.SchemaTypes.ObjectId, ref: 'file', required: false },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
// Add virtual id getter
|
||||
partSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const partSchema = new Schema({
|
||||
part: { type: Schema.Types.ObjectId, ref: 'part', required: true },
|
||||
quantity: { type: Number, required: true },
|
||||
});
|
||||
|
||||
// Define the main product schema
|
||||
const productSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { type: String, required: true },
|
||||
tags: [{ type: String }],
|
||||
version: { type: String },
|
||||
@ -11,12 +18,13 @@ const productSchema = new Schema(
|
||||
margin: { type: Number, required: false },
|
||||
amount: { type: Number, required: false },
|
||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
||||
parts: [partSchema],
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
// Add virtual id getter
|
||||
productSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,18 +1,21 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
|
||||
const userSchema = new mongoose.Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
username: { required: true, type: String },
|
||||
name: { required: true, type: String },
|
||||
firstName: { required: false, type: String },
|
||||
lastName: { required: false, type: String },
|
||||
email: { required: true, type: String },
|
||||
profileImage: { type: mongoose.SchemaTypes.ObjectId, ref: 'file', required: false },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
userSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
userSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
|
||||
const vendorSchema = new mongoose.Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { required: true, type: String },
|
||||
website: { required: false, type: String },
|
||||
email: { required: false, type: String },
|
||||
@ -13,7 +15,7 @@ const vendorSchema = new mongoose.Schema(
|
||||
);
|
||||
|
||||
vendorSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
vendorSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const noteSchema = new mongoose.Schema({
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
parent: {
|
||||
type: Schema.Types.ObjectId,
|
||||
refPath: 'parentType',
|
||||
required: true,
|
||||
},
|
||||
parentType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
content: {
|
||||
@ -33,7 +40,7 @@ const noteSchema = new mongoose.Schema({
|
||||
});
|
||||
|
||||
noteSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
noteSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
@ -1,22 +1,30 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const gcodeFileSchema = new mongoose.Schema({
|
||||
name: { required: true, type: String },
|
||||
gcodeFileName: { required: false, type: String },
|
||||
gcodeFileInfo: { required: true, type: Object },
|
||||
size: { type: Number, required: false },
|
||||
filament: { type: Schema.Types.ObjectId, ref: 'filament', required: true },
|
||||
parts: [{ type: Schema.Types.ObjectId, ref: 'part', required: true }],
|
||||
cost: { type: Number, required: false },
|
||||
createdAt: { type: Date },
|
||||
updatedAt: { type: Date },
|
||||
const partSchema = new mongoose.Schema({
|
||||
part: { type: Schema.Types.ObjectId, ref: 'part', required: true },
|
||||
quantity: { type: Number, required: true },
|
||||
});
|
||||
|
||||
const gcodeFileSchema = new mongoose.Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { required: true, type: String },
|
||||
gcodeFileName: { required: false, type: String },
|
||||
size: { type: Number, required: false },
|
||||
filament: { type: Schema.Types.ObjectId, ref: 'filament', required: true },
|
||||
parts: [partSchema],
|
||||
file: { type: mongoose.SchemaTypes.ObjectId, ref: 'file', required: false },
|
||||
cost: { type: Number, required: false },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
gcodeFileSchema.index({ name: 'text', brand: 'text' });
|
||||
|
||||
gcodeFileSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
gcodeFileSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
@ -1,32 +1,38 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const jobSchema = new mongoose.Schema({
|
||||
state: {
|
||||
type: { required: true, type: String },
|
||||
const jobSchema = new mongoose.Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
state: {
|
||||
type: { required: true, type: String },
|
||||
progress: { type: Number, required: false },
|
||||
},
|
||||
printers: [{ type: Schema.Types.ObjectId, ref: 'printer', required: false }],
|
||||
createdAt: { required: true, type: Date },
|
||||
updatedAt: { required: true, type: Date },
|
||||
startedAt: { required: false, type: Date },
|
||||
finishedAt: { required: false, type: Date },
|
||||
gcodeFile: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'gcodeFile',
|
||||
required: false,
|
||||
},
|
||||
quantity: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 1,
|
||||
min: 1,
|
||||
},
|
||||
subJobs: [{ type: Schema.Types.ObjectId, ref: 'subJob', required: false }],
|
||||
notes: [{ type: Schema.Types.ObjectId, ref: 'note', required: false }],
|
||||
},
|
||||
printers: [{ type: Schema.Types.ObjectId, ref: 'printer', required: false }],
|
||||
createdAt: { required: true, type: Date },
|
||||
updatedAt: { required: true, type: Date },
|
||||
startedAt: { required: false, type: Date },
|
||||
finishedAt: { required: false, type: Date },
|
||||
gcodeFile: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'gcodeFile',
|
||||
required: false,
|
||||
},
|
||||
quantity: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 1,
|
||||
min: 1,
|
||||
},
|
||||
subJobs: [{ type: Schema.Types.ObjectId, ref: 'subJob', required: false }],
|
||||
notes: [{ type: Schema.Types.ObjectId, ref: 'note', required: false }],
|
||||
});
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
jobSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
jobSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
// Define the moonraker connection schema
|
||||
@ -7,35 +8,39 @@ const moonrakerSchema = new Schema(
|
||||
host: { type: String, required: true },
|
||||
port: { type: Number, required: true },
|
||||
protocol: { type: String, required: true },
|
||||
apiKey: { type: String, default: null, required: false }
|
||||
apiKey: { type: String, default: null, required: false },
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
// Define the alert schema
|
||||
const alertSchema = new Schema(
|
||||
{
|
||||
priority: { type: String, required: true }, // order to show
|
||||
type: { type: String, required: true }, // selectFilament, error, info, message
|
||||
message: { type: String, required: false }
|
||||
type: { type: String, required: true }, // error, info, message
|
||||
message: { type: String, required: false },
|
||||
actions: [{ type: String, required: false, default: [] }],
|
||||
_id: { type: String, required: true },
|
||||
canDismiss: { type: Boolean, required: true, default: true },
|
||||
},
|
||||
{ timestamps: true, _id: false }
|
||||
);
|
||||
|
||||
// Define the main FDM printer schema
|
||||
// Define the main printer schema
|
||||
const printerSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { type: String, required: true },
|
||||
online: { type: Boolean, required: true, default: false },
|
||||
active: { type: Boolean, required: true, default: true },
|
||||
state: {
|
||||
type: { type: String, required: true, default: 'offline' },
|
||||
progress: { type: Number, required: false, default: 0 }
|
||||
message: { type: String, required: false },
|
||||
progress: { type: Number, required: false },
|
||||
},
|
||||
connectedAt: { type: Date, default: null },
|
||||
loadedFilament: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'filament',
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
moonraker: { type: moonrakerSchema, required: true },
|
||||
tags: [{ type: String }],
|
||||
@ -43,27 +48,17 @@ const printerSchema = new Schema(
|
||||
currentJob: { type: Schema.Types.ObjectId, ref: 'job' },
|
||||
currentSubJob: { type: Schema.Types.ObjectId, ref: 'subJob' },
|
||||
currentFilamentStock: { type: Schema.Types.ObjectId, ref: 'filamentStock' },
|
||||
subJobs: [{ type: Schema.Types.ObjectId, ref: 'subJob' }],
|
||||
vendor: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'vendor',
|
||||
default: null,
|
||||
required: true
|
||||
},
|
||||
host: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'host',
|
||||
default: null,
|
||||
required: true
|
||||
},
|
||||
alerts: [alertSchema]
|
||||
queue: [{ type: Schema.Types.ObjectId, ref: 'subJob' }],
|
||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', default: null },
|
||||
host: { type: Schema.Types.ObjectId, ref: 'host', default: null },
|
||||
alerts: [alertSchema],
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
// Add virtual id getter
|
||||
printerSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
// Configure JSON serialization to include virtuals
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const subJobSchema = new mongoose.Schema({
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
printer: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'printer',
|
||||
@ -12,9 +14,9 @@ const subJobSchema = new mongoose.Schema({
|
||||
ref: 'job',
|
||||
required: true,
|
||||
},
|
||||
subJobId: {
|
||||
moonrakerJobId: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: false,
|
||||
},
|
||||
gcodeFile: {
|
||||
type: Schema.Types.ObjectId,
|
||||
@ -23,7 +25,7 @@ const subJobSchema = new mongoose.Schema({
|
||||
},
|
||||
state: {
|
||||
type: { required: true, type: String },
|
||||
percent: { required: false, type: Number },
|
||||
progress: { required: false, type: Number },
|
||||
},
|
||||
number: {
|
||||
type: Number,
|
||||
@ -42,7 +44,7 @@ const subJobSchema = new mongoose.Schema({
|
||||
});
|
||||
|
||||
subJobSchema.virtual('id').get(function () {
|
||||
return this._id.toHexString();
|
||||
return this._id;
|
||||
});
|
||||
|
||||
subJobSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
@ -2,6 +2,14 @@ import { ObjectId } from 'mongodb';
|
||||
import { auditLogModel } from './schemas/management/auditlog.schema.js';
|
||||
import { natsServer } from './nats.js';
|
||||
|
||||
import { customAlphabet } from 'nanoid';
|
||||
|
||||
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
export const generateId = () => {
|
||||
// 10 characters
|
||||
return customAlphabet(ALPHABET, 12);
|
||||
};
|
||||
|
||||
function parseFilter(property, value) {
|
||||
if (typeof value === 'string') {
|
||||
var trimmed = value.trim();
|
||||
@ -309,7 +317,18 @@ function getChangedValues(oldObj, newObj, old = false) {
|
||||
} else {
|
||||
const nestedChanges = getChangedValues(oldVal, newVal, old);
|
||||
if (Object.keys(nestedChanges).length > 0) {
|
||||
changes[key] = nestedChanges;
|
||||
// Exclude progress and currentWeight from nested changes
|
||||
const excludeKeys = ['progress', 'currentWeight', 'net', 'gross'];
|
||||
const filteredChanges = Object.keys(nestedChanges)
|
||||
.filter(nestedKey => !excludeKeys.includes(nestedKey))
|
||||
.reduce((acc, nestedKey) => {
|
||||
acc[nestedKey] = nestedChanges[nestedKey];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
if (Object.keys(filteredChanges).length > 0) {
|
||||
changes[key] = filteredChanges;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
|
||||
@ -350,6 +369,9 @@ async function editAuditLog(
|
||||
owner,
|
||||
ownerType
|
||||
) {
|
||||
if (parentType === 'stockEvent') {
|
||||
return;
|
||||
}
|
||||
// Get only the changed values
|
||||
const changedOldValues = getChangedValues(oldValue, newValue, true);
|
||||
const changedNewValues = getChangedValues(oldValue, newValue, false);
|
||||
|
||||
@ -14,12 +14,16 @@ logger.level = config.server.logLevel;
|
||||
export class EventManager {
|
||||
constructor(socketClient) {
|
||||
this.socketClient = socketClient;
|
||||
this.subscriptions = new Set();
|
||||
}
|
||||
|
||||
async subscribeToObjectEvent(id, objectType, eventType) {
|
||||
logger.debug('Subscribing to object event:', eventType, id, objectType);
|
||||
const subject = `${objectType}s.${id}.events.${eventType}`;
|
||||
const subscriptionKey = `${subject}:${this.socketClient.socketId}`;
|
||||
|
||||
await natsServer.subscribe(
|
||||
`${objectType}s.${id}.events.${eventType}`,
|
||||
subject,
|
||||
this.socketClient.socketId,
|
||||
(key, value) => {
|
||||
if (!value?.result) {
|
||||
@ -32,15 +36,19 @@ export class EventManager {
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
this.subscriptions.add(subscriptionKey);
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async removeObjectEventsListener(id, objectType, eventType) {
|
||||
// Remove specific event subscription for this object
|
||||
await natsServer.removeSubscription(
|
||||
`${objectType}s.${id}.events.${eventType}`,
|
||||
this.socketClient.socketId
|
||||
);
|
||||
const subject = `${objectType}s.${id}.events.${eventType}`;
|
||||
const subscriptionKey = `${subject}:${this.socketClient.socketId}`;
|
||||
|
||||
await natsServer.removeSubscription(subject, this.socketClient.socketId);
|
||||
|
||||
this.subscriptions.delete(subscriptionKey);
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
@ -68,4 +76,19 @@ export class EventManager {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async removeAllListeners() {
|
||||
logger.debug('Removing all event listeners...');
|
||||
const removePromises = Array.from(this.subscriptions).map(
|
||||
subscriptionKey => {
|
||||
const [subject, socketId] = subscriptionKey.split(':');
|
||||
return natsServer.removeSubscription(subject, socketId);
|
||||
}
|
||||
);
|
||||
|
||||
await Promise.all(removePromises);
|
||||
this.subscriptions.clear();
|
||||
logger.debug(`Removed ${removePromises.length} event listener(s)`);
|
||||
return { success: true };
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,8 +23,8 @@ import { mongoServer } from './database/mongo.js';
|
||||
|
||||
// Connect to Etcd (await)
|
||||
try {
|
||||
await etcdServer.connect();
|
||||
logger.info('Connected to Etcd');
|
||||
//await etcdServer.connect();
|
||||
// logger.info('Connected to Etcd');
|
||||
} catch (err) {
|
||||
logger.error('Failed to connect to Etcd:', err);
|
||||
throw err;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { etcdServer } from '../database/etcd.js';
|
||||
import { natsServer } from '../database/nats.js';
|
||||
import { redisServer } from '../database/redis.js';
|
||||
import log4js from 'log4js';
|
||||
import { loadConfig } from '../config.js';
|
||||
const config = loadConfig();
|
||||
@ -17,33 +18,43 @@ export class LockManager {
|
||||
}
|
||||
|
||||
async lockObject(object) {
|
||||
// Add a 'lock' event to the 'locks' stream
|
||||
// Persist lock in Redis and publish via NATS
|
||||
logger.debug('Locking object:', object._id);
|
||||
try {
|
||||
await etcdServer.setKey(`/locks/${object.type}s/${object._id}`, {
|
||||
const redisKey = `locks:${object.type}s:${object._id}`;
|
||||
const lockPayload = {
|
||||
...object,
|
||||
locked: true
|
||||
});
|
||||
logger.info(`Lock event to id: ${object._id}`);
|
||||
};
|
||||
await redisServer.setKey(redisKey, lockPayload);
|
||||
const subject = `locks.${object.type}s.${object._id}`;
|
||||
await natsServer.publish(subject, lockPayload);
|
||||
logger.info(`Lock event published for id: ${object._id}`);
|
||||
return true;
|
||||
} catch (err) {
|
||||
logger.error(`Error adding lock event to: ${object._id}:`, err);
|
||||
logger.error(`Error locking object ${object._id}:`, err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async unlockObject(object) {
|
||||
// Add an 'unlock' event to the 'locks' stream
|
||||
const key = `/locks/${object.type}s/${object._id}`;
|
||||
// Remove lock from Redis (if owned by user) and publish via NATS
|
||||
const redisKey = `locks:${object.type}s:${object._id}`;
|
||||
try {
|
||||
logger.debug('Checking user can unlock:', object._id);
|
||||
|
||||
const lockEvent = await etcdServer.getKey(key);
|
||||
const lockEvent = await redisServer.getKey(redisKey);
|
||||
|
||||
if (lockEvent?.user === object.user) {
|
||||
logger.debug('Unlocking object:', object._id);
|
||||
await etcdServer.deleteKey(key);
|
||||
logger.info(`Unlocked object: ${object._id}`);
|
||||
await redisServer.deleteKey(redisKey);
|
||||
const subject = `locks.${object.type}s.${object._id}`;
|
||||
await natsServer.publish(subject, {
|
||||
_id: object._id,
|
||||
type: object.type,
|
||||
locked: false
|
||||
});
|
||||
logger.info(`Unlocked object and published event: ${object._id}`);
|
||||
return true;
|
||||
}
|
||||
} catch (err) {
|
||||
@ -53,11 +64,11 @@ export class LockManager {
|
||||
}
|
||||
|
||||
async getObjectLock(object) {
|
||||
// Get the current lock status of an object and broadcast it
|
||||
// Get the current lock status of an object
|
||||
logger.info('Getting lock status for object:', object._id);
|
||||
try {
|
||||
const lockKey = `/locks/${object.type}s/${object._id}`;
|
||||
const lockValue = await etcdServer.getKey(lockKey);
|
||||
const lockKey = `locks:${object.type}s:${object._id}`;
|
||||
const lockValue = await redisServer.getKey(lockKey);
|
||||
|
||||
if (lockValue) {
|
||||
// Object is locked
|
||||
@ -81,26 +92,26 @@ export class LockManager {
|
||||
}
|
||||
|
||||
setupLocksListeners() {
|
||||
etcdServer.onPrefixPutEvent(
|
||||
'/locks',
|
||||
this.socketClient.id,
|
||||
(key, value) => {
|
||||
const id = key.split('/').pop();
|
||||
logger.debug('Lock object event:', id);
|
||||
this.socketClient.socket.emit('lockUpdate', {
|
||||
...value,
|
||||
locked: true
|
||||
});
|
||||
}
|
||||
);
|
||||
etcdServer.onPrefixDeleteEvent('/locks', this.socketClient.id, key => {
|
||||
const id = key.split('/').pop();
|
||||
logger.debug('Unlock object event:', id);
|
||||
this.socketClient.socket.emit('lockUpdate', {
|
||||
_id: id,
|
||||
locked: false
|
||||
// Subscribe to NATS subject for lock changes and emit via socket
|
||||
const subject = 'locks.>';
|
||||
natsServer
|
||||
.subscribe(subject, this.socketClient.id, (_subject, value) => {
|
||||
// Expected subjects: locks.{type}s.{id}
|
||||
const parts = _subject.split('.');
|
||||
const last = parts[parts.length - 1];
|
||||
const id = last;
|
||||
const payload =
|
||||
typeof value === 'object'
|
||||
? value
|
||||
: { _id: id, locked: !!value?.locked };
|
||||
logger.debug('Lock event received:', _subject);
|
||||
this.socketClient.socket.emit('lockUpdate', payload);
|
||||
})
|
||||
.then(() => {
|
||||
logger.info('Subscribed to NATS for lock changes.');
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error('Failed to subscribe to NATS lock changes:', err);
|
||||
});
|
||||
});
|
||||
logger.info('Subscribed to Etcd stream for lock changes.');
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +152,8 @@ export class SocketHost {
|
||||
updateData: data.updateData,
|
||||
populate: data.populate,
|
||||
owner: this.host,
|
||||
ownerType: 'host'
|
||||
ownerType: 'host',
|
||||
auditLog: data?.auditLog
|
||||
});
|
||||
callback(object);
|
||||
}
|
||||
@ -279,7 +280,7 @@ export class SocketHost {
|
||||
if (this.authenticated) {
|
||||
await editObject({
|
||||
model: hostModel,
|
||||
id: this.host._id,
|
||||
id: this.id,
|
||||
updateData: {
|
||||
online: false,
|
||||
state: { type: 'offline' },
|
||||
|
||||
0
src/templates/assets/previewpagination.js
Normal file
0
src/templates/assets/previewpagination.js
Normal file
@ -11,15 +11,26 @@ body {
|
||||
display: flex;
|
||||
justify-content: center; /* Horizontal center */
|
||||
align-items: center; /* Vertical center */
|
||||
transform-origin: center center;
|
||||
padding: 60px;
|
||||
box-sizing: border-box;
|
||||
width: fit-content;
|
||||
}
|
||||
.previewWrapper {
|
||||
position: relative;
|
||||
}
|
||||
.previewDocument {
|
||||
background: #ffffff;
|
||||
border: 1px solid #000;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
transform-origin: top left;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.documentText {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
}
|
||||
.documentTitle {
|
||||
margin: 0;
|
||||
@ -27,7 +38,7 @@ body {
|
||||
|
||||
h1.documentTitle {
|
||||
font-weight: 800;
|
||||
font-size: 38px;
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
h2.documentTitle {
|
||||
@ -74,6 +85,47 @@ h4.documentTitle {
|
||||
}
|
||||
|
||||
.documentBarcode {
|
||||
width: 100% !important;
|
||||
width: auto !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.documentProgressBar {
|
||||
height: 8px;
|
||||
width: 260px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #000000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.documentProgressBarInner {
|
||||
height: 100%;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.documentTable {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
.documentTableRow {
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
.documentTableRow td,
|
||||
.documentTableRowHeader th,
|
||||
.documentTableRowFooter td {
|
||||
padding: 4px;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
.documentTableRowHeader {
|
||||
background: #0000002e;
|
||||
text-align: left;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
.documentTableRowFooter {
|
||||
background: #0000002e;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
@ -46,6 +46,7 @@ export class UpdateManager {
|
||||
}
|
||||
|
||||
async subscribeToObjectUpdate(id, objectType) {
|
||||
logger.debug('Subscribing to object update...', id, objectType);
|
||||
await natsServer.subscribe(
|
||||
`${objectType}s.${id}.object`,
|
||||
this.socketClient.socketId,
|
||||
|
||||
14
src/utils.js
14
src/utils.js
@ -7,11 +7,17 @@ import canonicalize from 'canonical-json';
|
||||
import { loadConfig } from './config.js';
|
||||
import { userModel } from './database/schemas/management/user.schema.js';
|
||||
import { documentSizeModel } from './database/schemas/management/documentsize.schema.js';
|
||||
import { documentJobModel } from './database/schemas/management/documentjob.schema.js';
|
||||
import { documentTemplateModel } from './database/schemas/management/documenttemplate.schema.js';
|
||||
import { documentPrinterModel } from './database/schemas/management/documentprinter.schema.js';
|
||||
import { printerModel } from './database/schemas/production/printer.schema.js';
|
||||
import { subJobModel } from './database/schemas/production/subjob.schema.js';
|
||||
import { jobModel } from './database/schemas/production/job.schema.js';
|
||||
import { filamentStockModel } from './database/schemas/inventory/filamentstock.schema.js';
|
||||
import { fileModel } from './database/schemas/management/file.schema.js';
|
||||
import { gcodeFileModel } from './database/schemas/production/gcodefile.schema.js';
|
||||
import { stockEventModel } from './database/schemas/inventory/stockevent.schema.js';
|
||||
import { filamentModel } from './database/schemas/management/filament.schema.js';
|
||||
|
||||
const config = loadConfig();
|
||||
|
||||
@ -21,11 +27,17 @@ const modelList = [
|
||||
hostModel,
|
||||
userModel,
|
||||
documentSizeModel,
|
||||
documentJobModel,
|
||||
documentTemplateModel,
|
||||
documentPrinterModel,
|
||||
printerModel,
|
||||
jobModel,
|
||||
subJobModel,
|
||||
filamentStockModel
|
||||
fileModel,
|
||||
gcodeFileModel,
|
||||
filamentStockModel,
|
||||
stockEventModel,
|
||||
filamentModel
|
||||
];
|
||||
|
||||
export async function generateHostOTP(id) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user