diff --git a/build_form.js b/build_form.js new file mode 100644 index 0000000..70fefe8 --- /dev/null +++ b/build_form.js @@ -0,0 +1,134 @@ +window.JSONEditor.defaults.callbacks.autocomplete = { + 'search_deposition': function (editor, input) { + if (input.length < 3) { + return []; + } + + return restRequest({ + url: 'deposition', + method: 'GET', + data: { + q: input, + limit: 10 + } + }) + }, + 'render_deposition': function (editor, result, props) { + try { + const localId = result.metadata.alternateIdentifiers.find( + (id) => id.alternateIdentifierType.toLowerCase() === 'local' + ); + return `
  • ${result.igsn} (localId: ${localId.alternateIdentifier})
  • `; + } catch (e) { + return `
  • ${result.igsn} (title: ${result.metadata.titles[0]['title']})
  • `; + } + }, + 'get_deposition_value': function (editor, result) { + try { + const localId = result.metadata.alternateIdentifiers.find( + (id) => id.alternateIdentifierType.toLowerCase() === 'local' + ); + return `${result.igsn}`; + } catch (e) { + return `${result.igsn}`; + } + } +}; + +Handlebars.registerHelper('split', function (string, separator, index) { + try { + return string.split(separator)[index].trim(); + } catch (e) { + return ''; + } +}); + +Handlebars.registerHelper('replaceAll', function (string, search, replacement) { + return (string !== undefined && string !== null) ? string.replaceAll(search, replacement) : ''; +}); +Handlebars.registerHelper('joinarray', function (a, sep, prefix=false) { + if (!a || !Array.isArray(a) || a.length === 0) { + // Handle empty or undefined array + return ''; + } + const result = a.join(sep); + if (result !== '' && prefix) { + return `${sep}${result}`; + } + return result; +}); + +Handlebars.registerHelper('formatBuildParams', function (params) { + if (!params || !Array.isArray(params) || params.length === 0) { + return ''; + } + + return params + .map(p => `${p.type}:${p.laserSpeed}:${p.laserPower}:${p.layerThickness}:${p.hatchSpacing}`) + .join('_'); +}); + +JSONEditor.defaults.custom_validators.push(function (schema, value, path) { + // Only validate the buildParameters array + if (schema.title !== "Build Process Parameters") { + return []; + } + + if (!Array.isArray(value)) { + return []; + } + + const seen = new Set(); + const duplicates = new Set(); + + value.forEach(item => { + if (item && item.type) { + if (seen.has(item.type)) { + duplicates.add(item.type); + } + seen.add(item.type); + } + }); + + if (duplicates.size > 0) { + return [{ + path: path, + property: 'type', + message: `Duplicate build parameter type(s) not allowed: ${[...duplicates].join(', ')}. +Each type (upskin, downskin, infill, contouring) may only appear once.` + }]; + } + + return []; +}); + + +JSONEditor.defaults.custom_validators.push(function (schema, value, path) { + // Only validate the IGSNs field + if (schema.title !== "IGSNs") { + return []; + } + + if (!Array.isArray(value)) { + return []; + } + + const seen = new Set(); + const duplicates = new Set(); + + value.forEach(v => { + if (seen.has(v)) { + duplicates.add(v); + } + seen.add(v); + }); + + if (duplicates.size > 0) { + return [{ + path: path, + message: `Duplicate IGSN(s) are not allowed: ${[...duplicates].join(', ')}` + }]; + } + + return []; +}); diff --git a/build_form.json b/build_form.json new file mode 100644 index 0000000..e4fd3b8 --- /dev/null +++ b/build_form.json @@ -0,0 +1,123 @@ +{ + "title": "Build Metadata Schema", + "description": "Schema for recording metadata of builds (build parameters)", + "type": "object", + "properties": { + "lookup": { + "type": "array", + "title": "IGSNs", + "description": "Select one or more IGSNs", + "minItems": 1, + "items": { + "type": "string", + "format": "autocomplete", + "options": { + "autocomplete": { + "search": "search_deposition", + "renderResult": "render_deposition", + "getResultValue": "get_deposition_value", + "autoSelect": true, + "debounceTime": 500 + } + } + }, + "propertyOrder": 0 + }, + "depositionId": { + "type": "string", + "title": "IGSN ID", + "description": "Unique identifier for the deposition", + "readOnly": true, + "propertyOrder": 999, + "watch": { + "igsn": "lookup" + }, + "template": "{{split igsn ' - ' 1}}", + "options": { + "grid_columns": 12, + "hidden": true + } + }, + "printerBuildID": { + "title": "Printer Build ID", + "description": "Automatically generated identifier for the printer build", + "type": "string", + "template": "{{formatBuildParams params}}", + "readOnly": true, + "propertyOrder": 2, + "watch": { + "params": "root.buildParameters" + }, + "options": { + "grid_columns": 12 + } + }, + "buildParameters": { + "title": "Build Process Parameters", + "description": "Laser process parameters for all regions of the build. Each type (upskin, downskin, infill, contouring) can appear only once.", + "propertyOrder": 3, + "type": "array", + "minItems": 1, + "maxItems": 4, + "uniqueItemProperties": ["type"], + "items": { + "type": "object", + "format": "grid", + "options": { + "grid_columns": 12 + }, + "properties": { + "type": { + "type": "string", + "enum": ["upskin", "downskin", "infill", "contouring"], + "description": "Type of build region", + "propertyOrder": 1 + }, + "laserSpeed": { + "type": "number", + "minimum": 0, + "maximum": 10000, + "description": "PRC-3-2-9", + "propertyOrder": 2, + "options": { + "grid_row": 12 + } + }, + "laserPower": { + "type": "number", + "minimum": 0, + "maximum": 370, + "description": "PRC-3-2-3", + "propertyOrder": 3, + "options": { + "grid_row": 12 + } + }, + "layerThickness": { + "type": "number", + "minimum": 0, + "maximum": 100, + "description": "PRC-3-2-1", + "propertyOrder": 4, + "options": { + "grid_row": 12 + } + }, + "hatchSpacing": { + "type": "number", + "minimum": 0, + "maximum": 300, + "description": "PRC-3-2-6", + "propertyOrder": 5, + "options": { + "grid_row": 12 + } + } + }, + "required": ["type", "laserSpeed", "laserPower", "layerThickness", "hatchSpacing"], + "additionalProperties": false + } + } + }, + "required": ["lookup", "buildParameters"] +} \ No newline at end of file diff --git a/printer_build_schema.json b/printer_build_schema.json index fde3311..1ade9aa 100644 --- a/printer_build_schema.json +++ b/printer_build_schema.json @@ -667,7 +667,10 @@ "enum": [ "Evan Adcock", "Nick Lamprinakos", - "Katie O'Donnell" + "Katie O'Donnell", + "Sierra Green", + "Justin Miner", + "David Reyes Ortiz" ] }, "propertyOrder": 3