diff --git a/html/work-package-suite-app.js b/html/work-package-suite-app.js index 069354d..c71de16 100644 --- a/html/work-package-suite-app.js +++ b/html/work-package-suite-app.js @@ -432,6 +432,18 @@ function loadSampleData(){ // Step 7 already has defaults + // CR-016 / T5.7. The sample is the Micron EUV configuration, and Micron does not + // use Assets: its content duplicates the database Clinton's team maintains, and + // that integration is deferred. Off by toggle, so the section and its model stay + // in the application for the integration to land in — and any other project can + // turn it back on from step 12 without a code change. + // + // A partial map on purpose. WPSections.normalize fills the rest in as ON, so a + // section added after today is not silently off for this SOP. + if(typeof WPSections !== 'undefined'){ + state.sections = WPSections.normalize({assets: false}); + } + // The Micron FMCS sample includes BIM/VDC — enable it so the sequence shows the // full BIM → construction flow (BIM steps first) and the Creator offers IWP/EWP. state.bimEnabled = true; diff --git a/html/wp-creation-app.js b/html/wp-creation-app.js index 75a1410..33c6ed7 100644 --- a/html/wp-creation-app.js +++ b/html/wp-creation-app.js @@ -6,6 +6,16 @@ // ── SAMPLE SOP (same shape the Configuration tool exports) ─────────────────── const SAMPLE_SOP = { meta:{tool:'Work Package Configuration', sample:true}, + // CR-016 / T5.7. This sample IS the Micron EUV configuration as far as the + // repository is concerned — it is what the standalone creator shows when there + // is no project SOP to read. Assets is off because its content duplicates the + // database Clinton's team maintains and that integration is deferred; the + // section, its data model and every value already captured stay exactly where + // they are, which is the whole point of expressing this as a toggle. + // + // Written as a partial map, not a full one: WPSections.normalize fills the rest + // in as ON, so a section added later is not silently off for this SOP. + sections:{assets:false}, project:{name:'Micron — INC Construction Work Packages', number:'26-67-008', client:'Micron Technology, Inc.', division:'Semiconductor', pm:'Nick Siegfried', cm:'K. Boyd', qm:'D. Nguyen', site:'Boise, ID — Fab'}, roles:[{role:'General Foreman',name:'M. Torres'},{role:'Superintendent',name:'K. Boyd'},{role:'Safety Manager / Lead',name:'A. Reyes'},{role:'Quality Manager',name:'D. Nguyen'},{role:'Planner',name:'L. Graver'}], governance:{ issuance:['By Sector / Area','By Discipline'], woSize:'Standard — 3–5 days (≈40–80 hrs)', woFormat:'WP##-[Sector]-[TYPE]', disciplines:['Mechanical','Electrical','Tech'], discMode:'choice', instanceSuffix:'letter', sizeHoursMax:'80' }, diff --git a/tests/sections_check.py b/tests/sections_check.py index d211cb7..34590d5 100644 --- a/tests/sections_check.py +++ b/tests/sections_check.py @@ -503,6 +503,59 @@ def run(page, base, tok, db_path): "Electrical Install" not in doc5 and "PROBE-ACUMATICA-TASK" not in doc5) set_sop(db_path, {}) + print("\nCR-016 (T5.7). Assets is off for Micron EUV, and only for it") + # The creator with no project falls back to SAMPLE_SOP, which is the Micron + # configuration as far as this repository is concerned — it is what the + # standalone page shows when there is no project SOP to read. + # + # localStorage cleared first, and this is not tidiness: activeProjectId falls + # back to ProjectData.getActiveId(), so a project left over from an earlier + # navigation sends bootSOP() down the real-project branch and the sample is + # never loaded. The probe would then report on Job A while claiming Micron. + page.eval("localStorage.clear(); true") + page.goto(base + "/wp-creation-index.html") + chk("the standalone creator boots on the Micron sample", wait_creator(page)) + settle(1.4) + page.eval(STUB) + chk("the sample really is the Micron one", + "Micron" in (page.eval("(SOP && SOP.project && SOP.project.name) || ''") or ""), + page.eval("(SOP && SOP.project && SOP.project.name) || ''")) + chk("Assets does not render in the form", + page.eval("document.getElementById('asset-card').hidden")) + chk("...and not in the section chip strip", + "Assets" not in (page.eval("(document.getElementById('section-nav')||{}).textContent||''")), + page.eval("(document.getElementById('section-nav')||{}).textContent||''")) + page.eval("renderPackage(%s)" % json.dumps(FULL_PKG)) + settle(0.7) + mdoc = page.eval("document.getElementById('pkg-doc').innerHTML") + chk("...nor in the detail view", MARKERS["assets"] not in mdoc) + chk("...nor in the PDF export, which is that document", + page.eval("document.getElementById('pkg-doc').innerHTML") == mdoc) + chk("every other section is untouched by CR-016", + all(v in mdoc for k, v in MARKERS.items() if k != "assets"), + [k for k, v in MARKERS.items() if v not in mdoc]) + chk("the section and its model are still in the codebase, not deleted", + page.eval("!!document.getElementById('asset-card')") + and page.eval("typeof pkgAssets !== 'undefined'")) + chk("...and the sample switches it off by TOGGLE, not by removing the data", + page.eval("JSON.stringify((SOP||{}).sections||{})").find("assets") >= 0, + page.eval("JSON.stringify((SOP||{}).sections||{})")) + chk("...naming only assets, so a section added later is not silently off too", + json.loads(page.eval("JSON.stringify(Object.keys((SOP||{}).sections||{})" + ".filter(k => (SOP.sections||{})[k] === false))")) == ["assets"], + page.eval("JSON.stringify((SOP||{}).sections||{})")) + + print(" another SOP enables Assets and it works") + set_sop(db_path, {}) + page.goto(base + "/wp-creation-index.html?project=projA") + chk("a different project's creator boots", wait_creator(page)) + settle(1.2) + chk("Assets renders there", not page.eval("document.getElementById('asset-card').hidden")) + page.eval("renderPackage(%s)" % json.dumps(FULL_PKG)) + settle(0.7) + chk("...and its content is in that project's document", + MARKERS["assets"] in page.eval("document.getElementById('pkg-doc').innerHTML")) + chk("no native dialog was opened anywhere in this flow", not json.loads(page.eval("JSON.stringify(window.__dialogs||[])")), page.eval("JSON.stringify(window.__dialogs||[])"))