103103 .file-btn-pdf : hover { filter : drop-shadow (0 0 3px # e53935 ); box-shadow : 0 0 6px rgba (229 , 57 , 53 , 0.4 ); }
104104 .file-btn-rev { color : var (--amber ); border-color : rgba (240 , 165 , 0 , 0.3 ); background : rgba (240 , 165 , 0 , 0.08 ); }
105105 .file-btn-rev : hover { filter : drop-shadow (0 0 3px var (--amber )); box-shadow : 0 0 6px rgba (240 , 165 , 0 , 0.4 ); }
106+ .file-btn-ghost { opacity : 0.2 ; pointer-events : none; cursor : default; }
106107
107108 /* Detail row */
108109 .detail-row td { padding : 0 ; }
215216 < div class ="section-header ">
216217 < div style ="display:flex;gap:6px;align-items:center;flex-wrap:wrap; " id ="summary-pills "> </ div >
217218 < div style ="display:flex;gap:4px; ">
218- < button class ="btn btn-blue " id ="btn-render " onclick ="renderAll() " style =" display:none; " > Render </ button >
219- < button class ="btn btn-blue " id ="btn-upload-all " onclick ="uploadAll() " style =" display:none; " > Upload </ button >
219+ < button class ="btn btn-blue " id ="btn-render " onclick ="renderAll() " disabled > RENDER ALL </ button >
220+ < button class ="btn btn-blue " id ="btn-upload-all " onclick ="uploadAll() " disabled > UPLOAD </ button >
220221 </ div >
221222 </ div >
222223 < div class ="filter-bar ">
@@ -403,6 +404,13 @@ <h2>Activity Log</h2>
403404
404405// -- Papers --
405406
407+ function fileBadge ( path , cls , label , openTitle , missingTitle ) {
408+ if ( path ) {
409+ return `<a class="file-btn ${ cls } " href="/api/file?path=${ encodeURIComponent ( path ) } " target="_blank" onclick="event.stopPropagation()" title="${ esc ( openTitle ) } ">${ label } </a>` ;
410+ }
411+ return `<span class="file-btn ${ cls } file-btn-ghost" title="${ esc ( missingTitle ) } ">${ label } </span>` ;
412+ }
413+
406414function toggleFolderSort ( ) { _folderSort = ! _folderSort ; renderPapers ( ) ; }
407415function renderPapers ( ) {
408416 const tbody = document . getElementById ( 'tbody' ) , empty = document . getElementById ( 'empty' ) , tw = document . getElementById ( 'table-wrap' ) ;
@@ -416,20 +424,22 @@ <h2>Activity Log</h2>
416424 return `<tr onclick="toggleDetail(${ idx } )" data-idx="${ idx } ">
417425 <td class="mono muted" style="width:24px;text-align:center;font-size:10px">${ esc ( '' + ( p . folder_idx || '' ) ) } </td>
418426 <td class="mono${ p . intent === 'ask' ?' ask-paper' :'' } " style="padding-right:2px">${ esc ( p . doc_number ) || '-' } ${ dirty } </td>
419- <td style="width:30px;text-align:center;padding-left:0;padding-right:4px">${ p . md_path ? `<a class=" file-btn file-btn-md" href="/api/file?path= ${ encodeURIComponent ( p . md_path ) } " target="_blank" onclick="event.stopPropagation()" title=" Open Markdown">MD</a>` : '' } </td>
420- <td style="width:34px;text-align:center;padding-left:0;padding-right:4px">${ p . pdf_path ? `<a class=" file-btn file-btn- pdf" href="/api/file?path= ${ encodeURIComponent ( p . pdf_path ) } " target="_blank" onclick="event.stopPropagation()" title=" Open PDF">PDF</a>` : '' } </td>
427+ <td style="width:30px;text-align:center;padding-left:0;padding-right:4px">${ fileBadge ( p . md_path , ' file-btn-md' , 'MD' , ' Open Markdown' , 'No markdown file' ) } </td>
428+ <td style="width:34px;text-align:center;padding-left:0;padding-right:4px">${ fileBadge ( p . pdf_path , ' file-btn- pdf' , 'PDF' , ' Open PDF' , 'No PDF' ) } </td>
421429 <td style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-left:16px">${ esc ( p . title ) || '' } </td>
422430 <td class="mono muted" style="white-space:nowrap">${ esc ( p . date ) || '' } </td>
423431 <td style="width:70px;text-align:center;overflow:hidden" onclick="event.stopPropagation()">${ badgeHtml ( p . status , idx ) } </td>
424432 </tr>` ;
425433 } ) . join ( '' ) ;
426434 const allMd = _papers . filter ( p => p . md_path ) . length ;
427435 const rb = document . getElementById ( 'btn-render' ) ;
428- rb . textContent = 'RENDER ALL' ;
429- rb . style . display = allMd > 0 ?'inline-block' : 'none' ;
436+ rb . disabled = allMd === 0 ;
437+ rb . title = allMd === 0 ?'No markdown papers' : `Render all ${ allMd } papers` ;
430438 const uploadCount = _papers . filter ( p => p . pdf_path && p . remote && p . status !== 'mailed' ) . length ;
431439 const ub = document . getElementById ( 'btn-upload-all' ) ;
432- if ( uploadCount > 0 ) { ub . textContent = `UPLOAD ${ uploadCount } ` ; ub . style . display = 'inline-block' ; } else ub . style . display = 'none' ;
440+ ub . textContent = uploadCount > 0 ?`UPLOAD ${ uploadCount } ` :'UPLOAD' ;
441+ ub . disabled = uploadCount === 0 || ! _authenticated ;
442+ ub . title = ! _authenticated ?'Not connected to isocpp.org' :uploadCount === 0 ?'No papers ready to upload' :`Upload ${ uploadCount } papers` ;
433443 const restoreIdx = _expandedIdx ;
434444 _expandedIdx = null ;
435445 if ( restoreIdx !== null ) toggleDetail ( restoreIdx ) ;
@@ -452,13 +462,16 @@ <h2>Activity Log</h2>
452462 const uploadWk = busy ?' working' :'' ;
453463 const uploadTitle = ! _authenticated ?'Not connected to isocpp.org' :! p . pdf_path ?'No PDF available' :! p . remote ?'No remote entry on isocpp.org' :'Force upload to isocpp.org' ;
454464 let acts = '' ;
455- if ( p . md_path ) acts += `<button class="btn btn-blue${ wk } " onclick="event.stopPropagation();renderSingle(${ idx } )"${ dis } >RENDER</button>` ;
465+ const renderDis = ( ! p . md_path || busy ) ?' disabled' :'' ;
466+ const renderTitle = ! p . md_path ?'No markdown file' :'' ;
467+ acts += `<button class="btn btn-blue${ p . md_path ?wk :'' } " onclick="event.stopPropagation();renderSingle(${ idx } )"${ renderDis } title="${ renderTitle } ">RENDER</button>` ;
456468 acts += `<button class="btn btn-blue${ uploadWk } " onclick="event.stopPropagation();submitUpload(${ idx } )"${ uploadDis } title="${ uploadTitle } ">UPLOAD</button>` ;
457469 d . innerHTML = `<td colspan="7"><div class="detail-content"><div class="detail-grid">
458470 <span class="dl">Document</span><span class="dv">${ esc ( p . doc_number ) || '-' } </span>
459471 <span class="dl">Title</span><span class="dv">${ esc ( p . title ) || '-' } </span>
460472 <span class="dl">Authors</span><span class="dv">${ esc ( p . authors ) || '-' } </span>
461473 <span class="dl">Audience</span><span class="dv">${ esc ( p . audience ) || '-' } </span>
474+ ${ p . intent ?`<span class="dl">Intent</span><span class="dv">${ esc ( { info :'Inform' , ask :'Ask' } [ p . intent ] || p . intent ) } </span>` :'' }
462475 ${ p . md_path ?`<span class="dl">Markdown</span><span class="dv" style="font-family:var(--mono);font-size:10px">${ esc ( p . md_path ) } </span>` :'' }
463476 ${ p . pdf_path ?`<span class="dl">PDF</span><span class="dv" style="font-family:var(--mono);font-size:10px">${ esc ( p . pdf_path ) } </span>` :'' }
464477 ${ p . brutal_summary ?`<span class="dl">Abstract</span><span class="dv">${ esc ( p . brutal_summary ) } </span>` :'' }
@@ -530,7 +543,9 @@ <h2>Activity Log</h2>
530543function submitUpload ( idx ) {
531544 const p = _papers [ idx ] ;
532545 if ( ! p || ! p . remote ) return ;
533- submitJob ( idx , '/api/upload' , { form_id : p . remote . form_id , doc_number : p . doc_number , path : p . pdf_path , title : p . title , author : p . primary_author || '' , abstract : p . brutal_summary || '' , status : ( p . remote && p . remote . status ) || '' , audience : p . audience || '' } ) ;
546+ const intentMap = { info : 'Info' , ask : 'Ask' } ;
547+ const title = p . intent ? ( intentMap [ p . intent ] || p . intent ) + ': ' + ( p . title || '' ) : ( p . title || '' ) ;
548+ submitJob ( idx , '/api/upload' , { form_id : p . remote . form_id , doc_number : p . doc_number , path : p . pdf_path , title, author : p . primary_author || '' , abstract : p . brutal_summary || '' , status : ( p . remote && p . remote . status ) || '' , audience : p . audience || '' , intent : p . intent || '' } ) ;
534549}
535550function renderSingle ( idx ) {
536551 const p = _papers [ idx ] ;
0 commit comments