diff --git a/sites/shared/components/workbench/edit.js b/sites/shared/components/workbench/edit.js
new file mode 100644
index 00000000000..48f904a9a7a
--- /dev/null
+++ b/sites/shared/components/workbench/edit.js
@@ -0,0 +1,67 @@
+import yaml from 'js-yaml'
+import hljs from 'highlight.js/lib/common'
+import defaultSettings from './default-settings'
+import validateGist from './gist-validator'
+import { useEffect, useState, useRef } from 'react'
+
+const countLines = (txt) => txt.split('\n').length
+const Edit = (props) => {
+ let { gist, setGist, design } = props
+
+ const inputRef = useRef(null)
+ const [gistAsYaml, setGistAsYaml] = useState(null)
+ const [numLines, setNumLines] = useState(0)
+
+ useEffect(() => {
+ setGistAsYaml(yaml.dump(gist))
+ }, [gist])
+ useEffect(() => {
+ if (gistAsYaml) setNumLines(countLines(gistAsYaml))
+ }, [gistAsYaml])
+
+ const onChange = (e) => {
+ const editedAsJson = yaml.load(inputRef.current.value)
+ if (validateGist(editedAsJson, design).valid) {
+ setGist({ ...defaultSettings, ...editedAsJson, design: gist.design })
+ }
+ }
+
+ const onKeyUp = (e) => {
+ setNumLines(countLines(e.target.value))
+ }
+
+ return (
+
+
Edit Pattern Configuration
+
+
+
+ {Array.from({ length: numLines }, (_, i) => (
+
+ {' '}
+ {i + 1}{' '}
+
+ ))}
+
+
+
+
+
+
+ )
+}
+
+export default Edit
diff --git a/sites/shared/components/workbench/gist-validator.js b/sites/shared/components/workbench/gist-validator.js
new file mode 100644
index 00000000000..4e45622faad
--- /dev/null
+++ b/sites/shared/components/workbench/gist-validator.js
@@ -0,0 +1,53 @@
+import defaultSettings from './default-settings'
+
+class GistValidator {
+ givenGist
+ design
+ errors
+ valid = true
+
+ constructor(givenGist, design) {
+ this.givenGist = givenGist
+ this.design = design
+ this.errors = {}
+ }
+
+ validateSettings() {
+ for (var key in defaultSettings) {
+ if (typeof this.givenGist[key] !== typeof defaultSettings[key]) {
+ this.errors[key] = 'TypeError'
+ this.valid = false
+ }
+ }
+ }
+
+ validateMeasurements() {
+ this.errors.measurements = {}
+ for (const m of this.design.patternConfig.measurements || []) {
+ if (this.givenGist.measurements[m] === undefined) {
+ this.errors.measurements[m] = 'MissingMeasurement'
+ this.valid = false
+ } else if (isNaN(this.givenGist.measurements[m])) {
+ this.errors.measurements[m] = 'TypeError'
+ this.valid = false
+ }
+ }
+ }
+
+ validateOptions() {
+ console.log(this.design.patternConfig)
+ }
+
+ validate() {
+ this.validateSettings()
+ this.validateMeasurements()
+ this.validateOptions()
+
+ return { valid: this.valid, errors: this.errors }
+ }
+}
+
+export default function validateGist(givenGist, design) {
+ const validator = new GistValidator(givenGist, design)
+ return validator.validate()
+}
diff --git a/sites/shared/components/wrappers/workbench.mjs b/sites/shared/components/wrappers/workbench.mjs
index c443d8e13fb..be1c87f1d52 100644
--- a/sites/shared/components/wrappers/workbench.mjs
+++ b/sites/shared/components/wrappers/workbench.mjs
@@ -19,6 +19,7 @@ import { DraftLogs } from 'shared/components/workbench/logs.mjs'
import { CutLayout } from 'shared/components/workbench/layout/cut/index.mjs'
import { PrintLayout } from 'shared/components/workbench/layout/print/index.mjs'
+
const views = {
measurements: WorkbenchMeasurements,
draft: LabDraft,
@@ -29,6 +30,7 @@ const views = {
logs: DraftLogs,
yaml: GistAsYaml,
json: GistAsJson,
+ edit: Edit,
welcome: () => TODO
,
}
@@ -76,7 +78,7 @@ export const WorkbenchWrapper = ({
// force view to measurements
useEffect(() => {
if (!gistReady) return
- if (gist._state?.view !== 'measurements' && !hasRequiredMeasurements)
+ if (!['measurements', 'edit'].includes(gist._state?.view) && !hasRequiredMeasurements)
updateGist(['_state', 'view'], 'measurements')
}, [gistReady, gist._state?.view, hasRequiredMeasurements])