Round-1 test feedback + smoke-test script
- API smoke test (server/smoketest.py): stdlib end-to-end check of health, projects, SOPs, WPs, the AWP issue gate (409 → 200), status, metrics, comments, and cascade delete. Referenced from DEPLOYMENT.md. SOP config: - Constraints: fix custom constraints never appearing — renderStandardConstraints no longer clobbers state.constraints; customs render in their own list with remove buttons; modal gains a free-text "Add" field. - Sources: add column headers (Data Type / Location-Platform / URL / Notes); preset data types are now fixed labels, "Add Source" creates an editable custom row. - Issuance strategy: add a tooltip + worked examples for each option. - Remove the "Comment submitted" acknowledgement popup (home + suite); keep the commenter name between comments. WP creator: - Clearing the last open constraint now offers to mark the package Issued and scrolls to the status control. - Form sections are collapsible (click a section heading to fold it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -529,6 +529,20 @@ function setConstraint(i,val){
|
||||
if(val==='open' && STATUS_ORDER.indexOf(getRadio('status'))>=ISSUED_IDX){
|
||||
prevStatus=getRadio('status'); holdContext={index:i, before};
|
||||
openHoldModal(pkgConstraints[i].name, true);
|
||||
return;
|
||||
}
|
||||
// Clearing the LAST open constraint makes the package release-ready — offer to
|
||||
// issue it and scroll up to the status control so the change is visible.
|
||||
if(before==='open' && val!=='open' && readiness().open===0){
|
||||
const st=getRadio('status');
|
||||
if(STATUS_ORDER.indexOf(st) < ISSUED_IDX){
|
||||
if(confirm('All constraints are cleared — this Work Package is release-ready.\n\nMark it as Issued now?')){
|
||||
setRadio('status','Issued'); prevStatus='Issued'; updateReleaseBanner();
|
||||
track('status_change',{status:'Issued',via:'constraint_clear'});
|
||||
}
|
||||
const sg=document.getElementById('status-group');
|
||||
if(sg) sg.scrollIntoView({behavior:'smooth', block:'center'});
|
||||
}
|
||||
}
|
||||
}
|
||||
function readiness(){ const open=pkgConstraints.filter(c=>c.status==='open').length; return {open, total:pkgConstraints.length, cleared:pkgConstraints.filter(c=>c.status==='cleared').length, ready:open===0}; }
|
||||
@@ -771,7 +785,24 @@ function setFormChrome(on){
|
||||
if(nav) nav.style.display = on ? '' : 'none';
|
||||
if(save) save.style.display = on ? 'flex' : 'none';
|
||||
document.body.classList.toggle('has-sticky-save', !!on);
|
||||
if(on){ buildSectionNav(); updateStickyStatus(); }
|
||||
if(on){ buildSectionNav(); updateStickyStatus(); makeCollapsible(); }
|
||||
}
|
||||
// Make each form card collapsible by clicking its heading (idempotent).
|
||||
function makeCollapsible(){
|
||||
document.querySelectorAll('.main > .card').forEach(card=>{
|
||||
if(card.id==='saved-card') return;
|
||||
const head=card.querySelector('.section-header, .sub-heading');
|
||||
if(!head || head.dataset.collapsible) return;
|
||||
head.dataset.collapsible='1';
|
||||
head.style.cursor='pointer';
|
||||
const chev=document.createElement('span'); chev.className='collapse-chev'; chev.textContent='▾';
|
||||
head.insertBefore(chev, head.firstChild);
|
||||
head.addEventListener('click', e=>{
|
||||
if(['INPUT','SELECT','TEXTAREA','BUTTON','A'].includes(e.target.tagName) || e.target.classList.contains('help-tip')) return;
|
||||
const collapsed=card.classList.toggle('collapsed');
|
||||
chev.textContent = collapsed ? '▸' : '▾';
|
||||
});
|
||||
});
|
||||
}
|
||||
function buildSectionNav(){
|
||||
const nav=document.getElementById('section-nav'); if(!nav) return;
|
||||
|
||||
Reference in New Issue
Block a user