diff --git a/html/work-package-suite-app.js b/html/work-package-suite-app.js index 2137be5..6f40a55 100644 --- a/html/work-package-suite-app.js +++ b/html/work-package-suite-app.js @@ -24,7 +24,7 @@ function onSizePresetChange(){ } let state = { - mode: 'standard', // 'standard' (field IWP) | 'bim' (BIM/VDC EWP) — set by the BIM template + bimEnabled: false, // does this project also produce BIM/VDC packages? If so the Creator tags each WP Install (IWP) or BIM (EWP); if not, it's IWP-only. project: {name:'', number:'', client:'', division:'', site:''}, team: {pm:'', apm:'', cm:'', qm:''}, teamMembers: [], @@ -148,8 +148,9 @@ const LABOR_COST_CODES = [ // ── BIM / VDC TEMPLATE ────────────────────────────────────────────────────────── // The BIM/VDC department also produces work packages under Advanced Work Packaging — // model & engineering deliverables (EWPs) that feed the field's install packages. -// These defaults are drawn from the EN06 SOP + work instructions and are applied by -// loadBIMTemplate() (the "Load BIM / VDC template" button on Step 4). Everything +// These defaults are drawn from the EN06 SOP + work instructions and are added by +// enableBIM() when the "Include BIM / VDC work packages" box is ticked on Step 4 +// (each is flagged bim so the Creator can offer them under the EWP kind). Everything // remains editable afterward. const BIM_WP_TYPES = [ 'Model Area Package', 'Conduit Routing Package', 'Coordination / Clash Package', @@ -196,48 +197,43 @@ const BIM_SOURCES = [ {label:'Constructability Review Sheet (CRS)', ph:'SharePoint'} ]; -function loadBIMTemplate(){ - if(!confirm('Load the BIM / VDC template?\n\nThis sets the WP types, release-gate constraints, sign-off roles, construction sequence, reference sources, disciplines (install phases) and numbering format to BIM/VDC defaults from the EN06 SOPs. Your project details (Step 1) and team (Step 2) are left alone, and you can edit everything afterward.')) return; - - state.mode = 'bim'; // flags the Creator to show BIM fields / hide field-only sections - - // Step 4 — deliverable package types - state.wpTypes = BIM_WP_TYPES.map(n => ({name:n, enabled:true, notes:'', approval:''})); +// Toggle BIM/VDC capability on the project. ON augments the SOP with BIM package +// types + release gates (flagged bim) plus BIM roles/sources/sequence steps, so the +// project produces both install (IWP) and BIM (EWP) packages. OFF strips the +// bim-flagged items. Everything stays editable. +function setBimEnabled(on){ + state.bimEnabled = !!on; + if(on) enableBIM(); else disableBIM(); + const cb = document.getElementById('bim_enabled'); if(cb) cb.checked = !!on; + track(on ? 'bim_enabled' : 'bim_disabled'); +} +function enableBIM(){ + // Package types (flagged bim so the Creator can offer them under "BIM (EWP)"). + BIM_WP_TYPES.forEach(n => { + const t = state.wpTypes.find(x => x.name === n); + if(t){ t.bim = true; t.enabled = true; } + else state.wpTypes.push({name:n, enabled:true, notes:'', approval:'', bim:true}); + }); renderWPTypes(); - - // Step 5 — disciplines become install phases; multi-discipline; model numbering - state.governance.disciplines = BIM_PHASES.slice(); - state.governance.discMode = 'multi'; - state.governance.woformat = 'MWP##-[Area]-[PHASE]'; - const setVal = (id, v) => { const el = document.getElementById(id); if(el) el.value = v; }; - setVal('gov_disciplines', BIM_PHASES.join(', ')); - setVal('gov_discmode', 'multi'); - setVal('gov_woformat', 'MWP##-[Area]-[PHASE]'); - - // Step 3 — set the two required roles to BIM titles, then add the rest as optional - state.signoffRoles[0] = {role:'BIM Coordinator', name: (state.signoffRoles[0] && state.signoffRoles[0].name) || ''}; - state.signoffRoles[1] = {role:'Construction Lead (CRS)', name: (state.signoffRoles[1] && state.signoffRoles[1].name) || ''}; - setVal('role_super_title', 'BIM Coordinator'); - setVal('role_foreman_title', 'Construction Lead (CRS)'); - BIM_TEMPLATE_ROLES.filter(r => r !== 'BIM Coordinator' && r !== 'Construction Lead (CRS)') - .forEach(r => { if(!state.signoffRoles.some(x => x.role === r)) state.signoffRoles.push({role:r, name:''}); }); - renderOptionalRoles(); - - // Step 9 — BIM release-gate constraints (replaces the field's standard 10) - state.constraints = BIM_CONSTRAINTS.map(c => ({...c})); + // Release-gate constraints (seed standard 10 first if empty, then add BIM gates). + if(!state.constraints || !state.constraints.length) state.constraints = STANDARD_10_CONSTRAINTS.map(c => ({...c})); _constraintsSeeded = true; + BIM_CONSTRAINTS.forEach(c => { if(!state.constraints.some(x => x.name === c.name)) state.constraints.push({...c, bim:true}); }); renderStandardConstraints(); - - // Step 8 — BIM process sequence - state.sequence = BIM_SEQUENCE.map(s => ({label:s, kind:'step'})); + // BIM sign-off roles (optional), reference sources, and process steps (idempotent). + BIM_TEMPLATE_ROLES.forEach(r => { if(!state.signoffRoles.some(x => x.role === r)) state.signoffRoles.push({role:r, name:'', bim:true}); }); + renderOptionalRoles(); + BIM_SEQUENCE.forEach(lbl => { if(!state.sequence.some(s => s.label === lbl)) state.sequence.push({label:lbl, kind:'step', bim:true}); }); renderSequenceSteps(); - - // Step 10 — reference sources - state.sources = BIM_SOURCES.map(s => ({label:s.label, system:'', notes:'', link:'', ph:s.ph, preset:true})); + BIM_SOURCES.forEach(s => { if(!state.sources.some(x => x.label === s.label)) state.sources.push({label:s.label, system:'', notes:'', link:'', ph:s.ph, preset:true, bim:true}); }); renderSources(); - - track('bim_template_loaded'); - alert('BIM / VDC template loaded.\n\nReview Step 5 (disciplines are now the install phases; numbering = MWP##-[Area]-[PHASE]) and Step 3 (BIM Coordinator + Construction Lead were added; leave the built-in Superintendent/Foreman blank if not used). Adjust anything as needed, then finish the SOP.'); +} +function disableBIM(){ + state.wpTypes = state.wpTypes.filter(t => !t.bim); renderWPTypes(); + state.constraints = (state.constraints || []).filter(c => !c.bim); renderStandardConstraints(); + state.signoffRoles = state.signoffRoles.filter((r,i) => i < 2 || !r.bim); renderOptionalRoles(); + state.sequence = (state.sequence || []).filter(s => !s.bim); renderSequenceSteps(); + state.sources = (state.sources || []).filter(s => !s.bim); renderSources(); } // ── INITIALIZATION ──────────────────────────────────────────────────────────── @@ -307,8 +303,9 @@ function loadSampleData(){ document.getElementById('proj_cm').value = 'K. Boyd'; document.getElementById('proj_qm').value = 'D. Nguyen'; - // Step 3 — standard required roles - state.mode = 'standard'; + // Step 3 — standard required roles (sample is an install-only project) + state.bimEnabled = false; + const beEl = document.getElementById('bim_enabled'); if(beEl) beEl.checked = false; if(state.signoffRoles[0]) state.signoffRoles[0].role = 'Superintendent'; if(state.signoffRoles[1]) state.signoffRoles[1].role = 'Foreman'; const stEl = document.getElementById('role_super_title'); if(stEl) stEl.value = 'Superintendent'; @@ -400,6 +397,7 @@ function repopulateForm(){ set('plat_commissioning', state.platforms.commissioning); set('plat_tracking_url', state.platforms.trackingUrl); set('plat_commissioning_url', state.platforms.commissioningUrl); + const beEl = document.getElementById('bim_enabled'); if(beEl) beEl.checked = !!state.bimEnabled; } // ── TOOL SWITCHING ──────────────────────────────────────────────────────────── @@ -522,9 +520,8 @@ function renderWPTypes(){ container.appendChild(row); }); const addRow = document.createElement('div'); - addRow.style.cssText = 'margin-top:0.85rem; display:flex; gap:0.5rem; flex-wrap:wrap;'; - addRow.innerHTML = ` - `; + addRow.style.cssText = 'margin-top:0.85rem;'; + addRow.innerHTML = ``; container.appendChild(addRow); } @@ -900,7 +897,7 @@ function completeSOP(){ sop = { meta: {tool:'Work Package Configuration', sample:false}, - mode: state.mode || 'standard', // 'bim' hides field-only sections + shows BIM fields in the Creator + bimEnabled: !!state.bimEnabled, // project also produces BIM (EWP) packages → Creator offers per-package IWP/EWP kind project: { name: state.project.name, number: state.project.number, @@ -928,7 +925,8 @@ function completeSOP(){ name: t.name.trim(), enabled: true, notes: t.notes || '', - approval: t.approval || '' + approval: t.approval || '', + bim: !!t.bim })), sources: state.sources.filter(s=>s.label), field: {trackPlatform: state.platforms.tracking, trackPlatformUrl: state.platforms.trackingUrl || ''}, @@ -950,7 +948,7 @@ function completeSOP(){ kind: s.kind || 'step' })), costCodes: LABOR_COST_CODES, - constraints: state.constraints.map(c=>({name: c.name, description: c.description || ''})) + constraints: state.constraints.map(c=>({name: c.name, description: c.description || '', bim: !!c.bim})) }; sopComplete = true; diff --git a/html/work-package-suite.html b/html/work-package-suite.html index ab3888c..bc4330e 100644 --- a/html/work-package-suite.html +++ b/html/work-package-suite.html @@ -158,6 +158,11 @@
diff --git a/html/wp-creation-app.js b/html/wp-creation-app.js index 58225d4..944fb17 100644 --- a/html/wp-creation-app.js +++ b/html/wp-creation-app.js @@ -43,6 +43,7 @@ const EXAMPLE_PKG = {"number":"WP02-1P-ELEC-Conduit","status":"Issue","subject": // ── STATE ──────────────────────────────────────────────────────────────────── let SOP=null, editingId=null, numberDirty=false; +let pkgKind='iwp'; // 'iwp' (install) | 'ewp' (BIM) — per-package, only relevant when SOP.bimEnabled let activeProjectId=''; // set at boot from ?project=